From 9fc50bd6126cc4bb1be5378af8efc12f24045852 Mon Sep 17 00:00:00 2001 From: Edvard Rejthar Date: Fri, 27 Oct 2023 12:52:22 +0200 Subject: [PATCH] zoom coordinates stable against screen size --- README.md | 12 +++++++++++ slidershow/frame.js | 41 ++++++++++++++++++++++++------------ slidershow/launch.js | 2 ++ slidershow/property_panel.js | 11 +++++----- slidershow/slidershow.js | 2 +- style.css | 3 ++- style.less | 3 ++- 7 files changed, 52 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 796af30..19680d9 100644 --- a/README.md +++ b/README.md @@ -347,6 +347,18 @@ In this example, the image starts at `[100, 10, 2]`, then zooms out `[]`, then g ``` +Position `0,0` is at the image centre. Its real dimension is taken into account so the value remains stable while changing the browser size (different displays). We recommend to use the property panel (Alt+P) to determine the coordinates. + +Every image in the sections slowly zooms out from the center. (Images in header and footer are ignored.) + +```html +
+
+
+
+
+``` + #### Panoramatic images When an image is much longer than the screen, we show it slowly first before resizing it to fit the screen. This will delay the `
`'s `data-duration`. It starts when the image proportion width / height > `data-panorama-threshold=2`. diff --git a/slidershow/frame.js b/slidershow/frame.js index 4b95538..4e35640 100644 --- a/slidershow/frame.js +++ b/slidershow/frame.js @@ -146,15 +146,19 @@ class Frame { .filter((_, el) => this.prop("step-li", $(el)))) // [data-step-points] affects all .add($("img", this.$frame) - .filter((_, el) => this.prop("step-points", $(el))) + .filter((_, el) => !$(el).closest("header, footer").length) // filter out images in header/footer .map((_, el) => { // generate multiple steps (dummy ) for points const $el = $(el) - const points = $el.data("step-points") - if(!points.length) { + const points = this.prop("step-points", $(el)) + if (!points?.length) { return } + // what is the first zoom position we see + // XX When multiple zoomed images at frame (or zooming steps along with classic data-step) are tested, + // this will pose a problem. Because this.step_index points to the frame step, + // not to the image animation step. const init_point = Array.from(points[this.step_index]) if (init_point) { // init point has no transition duration, it's straight there when we come to the frame @@ -737,11 +741,11 @@ class Frame { rescale: wzoom => { // the function seems to be called unintuitively with grab moving const scale = wzoom.content.currentScale wzoom.content.maxScale = Math.max(maxScale_default, scale + 3) - $el.trigger("wzoomed", [wzoom, last_scale===scale]) + $el.trigger("wzoomed", [last_scale === scale]) last_scale = scale }, dragScrollableOptions: { - onDrop: (_, wzoom) => $el.trigger("wzoomed", wzoom) + onDrop: () => $el.trigger("wzoomed") } }) // Why correcting viewport? When having data-step-points and calling `zoom_set` from `prepare`, @@ -751,13 +755,16 @@ class Frame { // this simulates the parent. wzoom.viewport.originalLeft = $el.position().left wzoom.viewport.originalTop = $el.position().top - wzoom.viewport.originalWidth = $el.width() - wzoom.viewport.originalHeight = $el.height() - - console.log("753: wzoom.viewport", wzoom.viewport) // TODO - + const refresh_viewport = () => { + wzoom.viewport.originalWidth = $el.width() + wzoom.viewport.originalHeight = $el.height() + } + refresh_viewport() + $(window).on("resize.wzoom", refresh_viewport) $el + .data("wzoom_get_ratio", () => $el.width() / $el.prop("naturalWidth")) + .data("wzoom_resize_off", () => $(window).off("resize.wzoom", refresh_viewport)) // DOC // we have zoomed in, do not playback further .off("click wheel") .on("click wheel", () => this.playback.moving = false) @@ -773,15 +780,20 @@ class Frame { const $el = $(el) setTimeout(() => { // we have to timeout - wzoom bug, has to finish before it can be destroyed $el.data("wzoom").destroy() - $el.data("wzoom", null) - $el.attr("data-wzoom", null) + $el.data("wzoom_resize_off")() + $el + .data("wzoom", null) + .data("wzoom_get_ratio", null) + .data("wzoom_resize_off", null) + .attr("data-wzoom", null) }) }) } zoom_get($el) { const { currentLeft, currentTop, currentScale } = this.zoom_init($el).content - return [currentLeft, currentTop, currentScale] + const ratio = $el.data("wzoom_get_ratio")() + return [currentLeft / ratio, currentTop / ratio, currentScale] } /** @@ -796,9 +808,10 @@ class Frame { zoom_set($el, left = 0, top = 0, scale = 1, transition_duration = null, duration = null) { const wzoom = this.zoom_init($el) transition_duration ??= prop("step-transition-duration", $el, null, "transition-duration") + const ratio = $el.data("wzoom_get_ratio")() const orig = wzoom.options.smoothTime wzoom.options.smoothTime = transition_duration - wzoom.transform(top, left, scale) + wzoom.transform(top * ratio, left * ratio, scale) wzoom.options.smoothTime = orig this.add_effect(resolve => $el.on("transitionend", () => resolve())) return duration ?? prop("step-duration", $el, null, "duration") diff --git a/slidershow/launch.js b/slidershow/launch.js index 367523c..2f11770 100644 --- a/slidershow/launch.js +++ b/slidershow/launch.js @@ -48,6 +48,8 @@ Private attributes that are not documented in the README because the user should * .step-not-yet-visible Auxiliary window highlights not-yet-seen elements. * Tags that help distinguish image zoom step from the image step. * trigger("wzoomed") Img with wzoom action. +* data("wzoom_get_ratio") Img with wzoom screen aware ratio. +* data("wzoom_resize_off") Img with wzoom event destructor. */ // var variables that a hacky user might wish to change. Might become data-attributes in the future. diff --git a/slidershow/property_panel.js b/slidershow/property_panel.js index b17d6ba..a17b798 100644 --- a/slidershow/property_panel.js +++ b/slidershow/property_panel.js @@ -15,8 +15,9 @@ class PropertyPanel { const cc = this.playback.change_controller const $actor = frame.$actor const points = JSON.parse($input.val() || '[]') // load set of points from the given - - $wrap.append(points.map(p => new_point(p))) + if (points.length) { + $wrap.append(points.map(p => new_point(p))) + } $input // refresh from either: user editing , user did undo, not from us having edited .off("change.step-points undo-performed") .on("change.step-points undo-performed", () => { @@ -32,7 +33,7 @@ class PropertyPanel { const $new_point = new_point(frame.zoom_get($actor), true).trigger("click").appendTo($wrap) cc.change(() => $new_point.trigger("dblclick")) }) - .insertAfter($wrap) + .insertBefore($wrap) function new_point(point, push = false) { if (push) { @@ -50,8 +51,8 @@ class PropertyPanel { $(this).addClass("active") $actor .off("wzoomed") - .on("wzoomed", (_, wzoom, minor_move) => { - const { currentLeft, currentTop, currentScale } = wzoom.content + .on("wzoomed", (_, minor_move) => { + const [currentLeft, currentTop, currentScale] = frame.zoom_get($actor) point[0] = Math.round(currentLeft) point[1] = Math.round(currentTop) point[2] = Math.round(currentScale) diff --git a/slidershow/slidershow.js b/slidershow/slidershow.js index d74cdd1..1022dee 100644 --- a/slidershow/slidershow.js +++ b/slidershow/slidershow.js @@ -26,7 +26,7 @@ loadjQuery(() => { crossOrigin: "anonymous" }, { src: "https://cdn.jsdelivr.net/npm/js-circle-progress@0.2.4/dist/jquery.circle-progress.min.js" }, - { src: "https://cdn.jsdelivr.net/gh/e3rd/WebHotkeys@0.8.1/WebHotkeys.js" }, + { src: "https://cdn.jsdelivr.net/gh/e3rd/WebHotkeys@f198e3f82c841e12c8bbdda6326e676d332c9714/WebHotkeys.js" }, // put proper version TODO { src: "https://cdn.jsdelivr.net/npm/exif-js" }, { src: "https://cdn.jsdelivr.net/npm/showdown@2.1.0/dist/showdown.min.js" }, MAP_ENABLE ? { src: "https://api.mapy.cz/loader.js" } : null, diff --git a/style.css b/style.css index 17c7d0b..c0c71d4 100644 --- a/style.css +++ b/style.css @@ -174,6 +174,7 @@ frame-preview > article-map [data-step].step-not-yet-visible { cursor: pointer; display: inline-block; background-color: lightyellow; + border: 1px solid gray; border-radius: 5px; padding: 3px; } @@ -181,7 +182,7 @@ frame-preview > article-map [data-step].step-not-yet-visible { background-color: yellow; } #hud #hud-properties > .hud-point { - padding: 5px; + margin-bottom: 0px; display: inline-block; } #map-hud { diff --git a/style.less b/style.less index 3f4341d..25de785 100644 --- a/style.less +++ b/style.less @@ -223,6 +223,7 @@ frame-preview { cursor: pointer; display: inline-block; background-color: lightyellow; + border: 1px solid gray; border-radius: 5px; padding: 3px; } @@ -234,7 +235,7 @@ frame-preview { } >.hud-point { - padding: 5px; + margin-bottom: 0px; display: inline-block; } }