From 7d3bbe03ac083af21cc113954f4249aadba0622e Mon Sep 17 00:00:00 2001 From: Austin Riba Date: Tue, 15 Feb 2022 11:25:21 -0800 Subject: [PATCH] lightbox: Swap panzoom library to anvaka/panzoom. This PR changes the library used for panning and zooming in the lightbox module from timmywil/panzoom to avanka/panzoom. The original (timmywil) version of the library contains a bug where if you have a high resolution touchpad and Firefox and you zoom in and out repeatedly on an image, the image may drift. avanka/panzoom does not appear to display this behavior. Restores the behaviour from before 5f83bc5cfea8, where clicking outside the image closes the lightbox, primarily by way of swapping out the panzoom library. Fixes: #21163. --- package.json | 2 +- static/js/lightbox.js | 60 ++++++++++++++++++++++++++++---------- static/styles/lightbox.css | 1 + version.py | 2 +- yarn.lock | 36 +++++++++++++++++++---- 5 files changed, 79 insertions(+), 22 deletions(-) diff --git a/package.json b/package.json index 3b71f14edef90..789618e9cdaf6 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,6 @@ "@formatjs/intl": "^1.9.7", "@giphy/js-components": "^5.0.5", "@giphy/js-fetch-api": "^4.0.1", - "@panzoom/panzoom": "^4.4.3", "@uppy/core": "^1.7.1", "@uppy/progress-bar": "^1.3.4", "@uppy/xhr-upload": "^1.4.2", @@ -50,6 +49,7 @@ "lodash": "^4.17.19", "micromodal": "^0.4.6", "mini-css-extract-plugin": "^2.2.2", + "panzoom": "^9.4.2", "plotly.js": "^2.0.0", "postcss": "^8.0.3", "postcss-calc": "^8.0.0", diff --git a/static/js/lightbox.js b/static/js/lightbox.js index 92aa53c333795..edd9e746a64fa 100644 --- a/static/js/lightbox.js +++ b/static/js/lightbox.js @@ -1,5 +1,5 @@ -import panzoom from "@panzoom/panzoom"; import $ from "jquery"; +import panzoom from "panzoom"; import render_lightbox_overlay from "../templates/lightbox_overlay.hbs"; @@ -21,20 +21,27 @@ export class PanZoomControl { constructor(container) { this.container = container; this.panzoom = panzoom(this.container, { - disablePan: true, - disableZoom: true, - cursor: "auto", + smoothScroll: false, + bounds: true, + maxZoom: 5, + minZoom: 0.1, + filterKey() { + // Disable the library's built in keybindings + return true; + }, }); + // Start with pan/zoom disabled. + this.disablePanZoom(); // The following events are necessary to prevent the click event // firing where the user "unclicks" at the end of the drag, which // was causing accidental overlay closes in some situations. - this.container.addEventListener("panzoomstart", () => { + this.panzoom.on("pan", () => { // Marks this overlay as needing to stay open. $("#lightbox_overlay").data("noclose", true); }); - this.container.addEventListener("panzoomend", () => { + this.panzoom.on("panend", () => { // Don't remove the noclose attribute on this overlay until after paint, // otherwise it will be removed too early and close the lightbox // unintentionally. @@ -67,26 +74,36 @@ export class PanZoomControl { } reset() { - this.panzoom.reset(); + this.panzoom.zoomAbs(0, 0, 1); + this.panzoom.moveTo(0, 0); + $("#lightbox_overlay").data("noclose", false); } disablePanZoom() { - this.container.removeEventListener("wheel", this.panzoom.zoomWithWheel); - this.panzoom.setOptions({disableZoom: true, disablePan: true, cursor: "auto"}); + $(".image-preview .zoom-element img").css("cursor", "auto"); this.reset(); + this.panzoom.pause(); } enablePanZoom() { - this.panzoom.setOptions({disableZoom: false, disablePan: false, cursor: "move"}); - this.container.addEventListener("wheel", this.panzoom.zoomWithWheel); + $(".image-preview .zoom-element img").css("cursor", "move"); + this.panzoom.resume(); } zoomIn() { - this.panzoom.zoomIn(); + const w = $(".image-preview").width(); + const h = $(".image-preview").height(); + this.panzoom.smoothZoom(w / 2, h / 2, 1.5); } zoomOut() { - this.panzoom.zoomOut(); + const w = $(".image-preview").width(); + const h = $(".image-preview").height(); + this.panzoom.smoothZoom(w / 2, h / 2, 0.5); + } + + isActive() { + return $(".image-preview .zoom-element img").length > 0; } } @@ -124,7 +141,9 @@ function display_image(payload) { render_lightbox_list_images(payload.preview); $(".player-container").hide(); - $(".image-actions, .image-description, .download, .lightbox-canvas-trigger").show(); + $( + ".image-preview, .image-actions, .image-description, .download, .lightbox-canvas-trigger", + ).show(); const img_container = $("#lightbox_overlay .image-preview > .zoom-element"); const img = new Image(); @@ -364,7 +383,9 @@ export function initialize() { $(".player-container iframe").remove(); is_open = false; document.activeElement.blur(); - pan_zoom_control.disablePanZoom(); + if (pan_zoom_control.isActive()) { + pan_zoom_control.disablePanZoom(); + } $(".lightbox-canvas-trigger").removeClass("enabled"); }; @@ -457,4 +478,13 @@ export function initialize() { overlays.close_overlay("lightbox"); } }); + + $("#lightbox_overlay .image-preview").on("click", (e) => { + // Ensure that the click isn't on the image itself, and that + // the window isn't marked as disabled to click to close. + if (!$(e.target).is("img") && !$("#lightbox_overlay").data("noclose")) { + reset_lightbox_state(); + overlays.close_overlay("lightbox"); + } + }); } diff --git a/static/styles/lightbox.css b/static/styles/lightbox.css index 937572900d1c7..1b8c4641f0d67 100644 --- a/static/styles/lightbox.css +++ b/static/styles/lightbox.css @@ -9,6 +9,7 @@ width: 100%; height: calc(100% - 65px - 95px); margin: 0; + overflow: hidden; background-size: contain; background-repeat: no-repeat; diff --git a/version.py b/version.py index 3b25488fb2e52..a0765283f99ac 100644 --- a/version.py +++ b/version.py @@ -48,4 +48,4 @@ # historical commits sharing the same major version, in which case a # minor version bump suffices. -PROVISION_VERSION = "178.0" +PROVISION_VERSION = "179.0" diff --git a/yarn.lock b/yarn.lock index 5d8188ce790a0..0447ac4c0da8b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1377,11 +1377,6 @@ mkdirp "^1.0.4" rimraf "^3.0.2" -"@panzoom/panzoom@^4.4.3": - version "4.4.3" - resolved "https://registry.yarnpkg.com/@panzoom/panzoom/-/panzoom-4.4.3.tgz#439ef0c3eba1cba0ad9b661fda5961aa2e2eec64" - integrity sha512-fTAr7/bc9ukvWKxxqdoAuIhKhvu6TwuNiGcA0N3lrSj5OZGlISGLXcSZZyN7kgqH/6icYS7b18UT/Iq/W2rTOA== - "@plotly/d3-sankey-circular@0.33.1": version "0.33.1" resolved "https://registry.yarnpkg.com/@plotly/d3-sankey-circular/-/d3-sankey-circular-0.33.1.tgz#15d1e0337e0e4b1135bdf0e2195c88adacace1a7" @@ -2352,6 +2347,13 @@ almost-equal@^1.1.0: resolved "https://registry.yarnpkg.com/almost-equal/-/almost-equal-1.1.0.tgz#f851c631138757994276aa2efbe8dfa3066cccdd" integrity sha1-+FHGMROHV5lCdqou++jfowZszN0= +amator@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/amator/-/amator-1.1.0.tgz#08c6b60bc93aec2b61bbfc0c4d677d30323cc0f1" + integrity sha1-CMa2C8k67Cthu/wMTWd9MDI8wPE= + dependencies: + bezier-easing "^2.0.3" + ansi-escapes@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" @@ -2713,6 +2715,11 @@ batch@0.6.1: resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16" integrity sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY= +bezier-easing@^2.0.3: + version "2.1.0" + resolved "https://registry.yarnpkg.com/bezier-easing/-/bezier-easing-2.1.0.tgz#c04dfe8b926d6ecaca1813d69ff179b7c2025d86" + integrity sha1-wE3+i5JtbsrKGBPWn/F5t8ICXYY= + big.js@^3.1.3: version "3.2.0" resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.2.0.tgz#a5fc298b81b9e0dca2e458824784b65c52ba588e" @@ -7455,6 +7462,11 @@ next-tick@~1.0.0: resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" integrity sha1-yobR/ogoFpsBICCOPchCS524NCw= +ngraph.events@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ngraph.events/-/ngraph.events-1.2.1.tgz#6e40425ef9dec1e074bbef6da56c8d79b9188fd8" + integrity sha512-D4C+nXH/RFxioGXQdHu8ELDtC6EaCiNsZtih0IvyGN81OZSUby4jXoJ5+RNWasfsd0FnKxxpAROyUMzw64QNsw== + no-case@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d" @@ -7909,6 +7921,15 @@ pako@^2.0.3: resolved "https://registry.yarnpkg.com/pako/-/pako-2.0.4.tgz#6cebc4bbb0b6c73b0d5b8d7e8476e2b2fbea576d" integrity sha512-v8tweI900AUkZN6heMU/4Uy4cXRc2AYNRggVmTR+dEncawDJgCdLMximOVA2p4qO57WMynangsfGRb5WD6L1Bg== +panzoom@^9.4.2: + version "9.4.2" + resolved "https://registry.yarnpkg.com/panzoom/-/panzoom-9.4.2.tgz#5b3ebdb72efbedfbd51e09bca6134248ad8ccad7" + integrity sha512-sQLr0t6EmNFXpZHag0HQVtOKqF9xjF7iZdgWg3Ss1o7uh2QZLvcrz7S0Cl8M0d2TkPZ69JfPJdknXN3I0e/2aQ== + dependencies: + amator "^1.1.0" + ngraph.events "^1.2.1" + wheel "^1.0.0" + param-case@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/param-case/-/param-case-3.0.4.tgz#7d17fe4aa12bde34d4a77d91acfb6219caad01c5" @@ -11177,6 +11198,11 @@ whatwg-url@^5.0.0: tr46 "~0.0.3" webidl-conversions "^3.0.0" +wheel@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/wheel/-/wheel-1.0.0.tgz#6cf46e06a854181adb8649228077f8b0d5c574ce" + integrity sha512-XiCMHibOiqalCQ+BaNSwRoZ9FDTAvOsXxGHXChBugewDj7HC8VBIER71dEOiRH1fSdLbRCQzngKTSiZ06ZQzeA== + which-boxed-primitive@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6"