diff --git a/_extensions/closeread/closeread.css b/_extensions/closeread/closeread.css index fd7a76f..f7947a5 100644 --- a/_extensions/closeread/closeread.css +++ b/_extensions/closeread/closeread.css @@ -38,12 +38,20 @@ .cr-section .sticky-col { grid-row: 1; } +.cr-section .sticky-col .sticky { + transition: transform 3s ease-in-out; +} +.cr-section .sticky-col .sticky img { + transition: clip-path 1s cubic-bezier(0.4, 0, 0.2, 1); +} .cr-section .sticky-col .sticky-col-stack { display: grid; height: 100dvh; position: sticky; overflow: hidden; top: 0; + transition: + transform 3s ease-in-out !important; } .cr-section .sticky-col .sticky-col-stack .sticky { grid-area: 1/1; diff --git a/_extensions/closeread/closeread.js b/_extensions/closeread/closeread.js index 5bfa88e..1e35e45 100644 --- a/_extensions/closeread/closeread.js +++ b/_extensions/closeread/closeread.js @@ -179,12 +179,14 @@ document.addEventListener("DOMContentLoaded", () => { // updateStickies: triggers effects on the focused sticky function updateStickies(allStickies, focusedStickyName, trigger) { const focusedSticky = document.querySelectorAll("[id=" + focusedStickyName)[0]; - - // update which sticky is active - allStickies.forEach(node => {node.classList.remove("cr-active")}); + + allStickies.forEach(node => { + node.classList.remove("cr-active"); + applyCrop(node, null); // Reset crop on all stickies + }); + focusedSticky.classList.add("cr-active"); - - // apply additional effects + transformSticky(focusedSticky, trigger.element); highlightSpans(focusedSticky, trigger.element); @@ -303,6 +305,7 @@ function transformSticky(focusedSticky, trigger) { let translateStr = ""; let scaleStr = ""; let transformStr = ""; + let cropStr = ""; // determine type of transform if (trigger.hasAttribute("data-pan-to")) { @@ -318,6 +321,9 @@ function transformSticky(focusedSticky, trigger) { if (trigger.hasAttribute("data-zoom-to")) { transformStr = zoomToTransform(focusedSticky, trigger); } + if (trigger.hasAttribute("data-crop")) { + cropStr = trigger.getAttribute("data-crop"); + } // zooming will override pan-to and scale-by if (!transformStr) { @@ -332,9 +338,26 @@ function transformSticky(focusedSticky, trigger) { // use the string to transform the sticky focusedSticky.style.transform = transformStr; - + if (cropStr) { + applyCrop(focusedSticky, cropStr); + } } +function applyCrop(element, cropStr) { + const img = element.querySelector('img'); + if (img) { + if (cropStr === null || cropStr === undefined) { + // Reset the crop + img.style.clipPath = 'inset(0% 0% 0% 0%)'; + } else { + const [left, top, right, bottom] = cropStr.split(',').map(v => parseFloat(v)); + setTimeout(() => { + img.style.clipPath = `inset(${top}% ${right}% ${bottom}% ${left}%)`; + }, 100); // Small delay to allow transform to start first + } + } + } + function zoomToTransform(focusedSticky, trigger) { const paddingX = 75; diff --git a/_extensions/closeread/closeread.lua b/_extensions/closeread/closeread.lua index f263498..c764f38 100644 --- a/_extensions/closeread/closeread.lua +++ b/_extensions/closeread/closeread.lua @@ -11,7 +11,8 @@ local debug_mode = false local trigger_selectors = {["focus-on"] = true} local cr_attributes = {["pan-to"] = true, ["scale-by"] = true, - ["highlight-spans"] = true} + ["highlight-spans"] = true, + ["data-crop"] = true} local remove_header_space = false local global_layout = "sidebar-left" diff --git a/docs/guide/focus-effects.qmd b/docs/guide/focus-effects.qmd index 469776f..c0126af 100644 --- a/docs/guide/focus-effects.qmd +++ b/docs/guide/focus-effects.qmd @@ -53,6 +53,14 @@ You can highlight parts of the code and text of your sticky using the following Line highlighting (1 and 2) works on code cells and line blocks while span highlighting (3 and 4) only works on line blocks. +## Cropping + +When you want to focus on a specific part of a figure, you can crop it to guide your audience's attention. + +1. `[@cr-myfigure]{data-crop="10%, 20%, 30%, 40%"}`: crops 10% from the top, 20% from the right, 30% from the bottom, and 40% from the left. +2. `[@cr-myfigure]{data-crop="20%, 20%, 30%, 20%"}`: this will further crops 10% from the top and releases 20% on the left compared to the previous example. +3. `@cr-myfigure` directly call the figure to remove all cropping effects. + ### Code cell examples This will highlight lines 1 and 2: