From 44d0f14ba08896c694a4fdcdc169c717212c3795 Mon Sep 17 00:00:00 2001 From: WeedLordVegeta420 <81525421+WeedLordVegeta420@users.noreply.github.com> Date: Thu, 20 Nov 2025 07:41:09 -0500 Subject: [PATCH] [imageGalleryNavigation] Add basic zoom/pan to Image detail page. --- plugins/imageGalleryNavigation/README.md | 3 +- .../imageGalleryNavigation.js | 94 +++++++++++++++++++ .../imageGalleryNavigation.yml | 7 +- 3 files changed, 102 insertions(+), 2 deletions(-) diff --git a/plugins/imageGalleryNavigation/README.md b/plugins/imageGalleryNavigation/README.md index a915e6d9..6879ab80 100644 --- a/plugins/imageGalleryNavigation/README.md +++ b/plugins/imageGalleryNavigation/README.md @@ -4,9 +4,10 @@ https://discourse.stashapp.cc/t/imagegallerynavigation/1857 This plugin adds features for navigating between images within a Gallery from the Image details page. This is intended to make it easier to edit metadata on each Image in a Gallery one at a time without constantly having to go back and forth between the Gallery and Image page. -This plugin currently adds two things to the Image details page: +This plugin currently adds the following to the Image details page: - A line above the tabs in the left panel that indicates the current page and total number of pages in the current Gallery. The current image number can be changed to jump to a specific image within the Gallery. - Buttons along the left/right side of the main Image display panel that allow moving to the previous/next image in the Gallery. + - Basic zoom (mouse wheel) and pan (click and drag) functionality (can be enabled/disabled in plugin settings). Zooming out to original scale will also reset the image position. In the case of Images that are in multiple Galleries, the Gallery being navigated is set by accessing an Image from the Gallery you want to navigate. When navigating to an Image from a Gallery, the sorting/filtering currently on the Gallery view will also be applied to the Gallery navigation on the Image page. diff --git a/plugins/imageGalleryNavigation/imageGalleryNavigation.js b/plugins/imageGalleryNavigation/imageGalleryNavigation.js index 4be69eed..7de67bef 100644 --- a/plugins/imageGalleryNavigation/imageGalleryNavigation.js +++ b/plugins/imageGalleryNavigation/imageGalleryNavigation.js @@ -7,6 +7,11 @@ sortdir: "asc", }); + let pluginSettings = {}; + const defaultPluginSettings = { + enableTransform: true + }; + // In order to handle scenarios where an image is in multiple galleries, capture ID of gallery the user is navigating from. // If user navigates directly to an image URL and image is in multiple galleries, we will just use the first gallery in list. // This may break if user jumps around in browser history, in which case we will fall back to basic scenario of assuming first gallery in list. @@ -26,6 +31,12 @@ // On image page, get data about gallery (image's position within gallery, next/prev image IDs), // add arrow buttons to page, and register arrow keypress handlers, async function setupImageContainer() { + const configSettings = await csLib.getConfiguration("imageGalleryNavigation", {}); // getConfiguration is from cs-ui-lib.js + pluginSettings = { + ...defaultPluginSettings, + ...configSettings, + }; + var imageID = window.location.pathname.split("/")[2]; var imageGalleries = await findImage(imageID); @@ -66,6 +77,11 @@ insertGalleryToolbar(currentImageIndex, totalImageCount, galleryImages); insertArrowButtons(nextImageID, prevImageID); insertArrowKeyHandlers(nextImageID, prevImageID); + + // Add translate/scale controls. + if (pluginSettings.enableTransform) { + setupMouseEventHandlers(); + } } } @@ -131,6 +147,84 @@ // }); } + function setupMouseEventHandlers() { + var img = document.querySelector("div.image-container img"); + + // Init transform values. + imgScale = 1.0; + imgTranslateX = 0.0; + imgTranslateY = 0.0; + + // Prevent listeners from being attached twice. + img.removeEventListener('mousedown', onStartDrag); + img.removeEventListener('mousemove', onDrag); + document.removeEventListener('mouseup', onStopDrag); + img.removeEventListener('wheel', onMouseWheel); + + // Add event listeners. + img.addEventListener('mousedown', onStartDrag); + img.addEventListener('mousemove', onDrag); + document.addEventListener('mouseup', onStopDrag); + img.addEventListener('wheel', onMouseWheel); + } + + // *** Mouse Event Handlers *** // + var imgScale = 1.0; + var imgTranslateX = 0.0; + var imgTranslateY = 0.0; + var dragStartX = 0.0; + var dragStartY = 0.0; + var dragStartTranslateX = 0.0; + var dragStartTranslateY = 0.0; + var dragActive = false; + + function onStartDrag(event) { + if (event.button === 0) { + event.preventDefault(); // Needed to prevent drag from being blocked. + dragActive = true; + dragStartX = event.clientX; + dragStartY = event.clientY; + dragStartTranslateX = imgTranslateX; + dragStartTranslateY = imgTranslateY; + } + } + + function onStopDrag(event) { + if (event.button === 0) { + dragActive = false; + } + } + + function onDrag(event) { + if (dragActive) { + imgTranslateX = dragStartTranslateX + (event.clientX - dragStartX); + imgTranslateY = dragStartTranslateY + (event.clientY - dragStartY); + applyImageTransform(); + } + } + + function onMouseWheel(event) { + event.preventDefault(); + + // TODO: Zoom to cursor. + // var img = document.querySelector("div.image-container img"); + // img.style.transformOrigin = `${event.offsetX}px ${event.offsetY}px` + imgScale += (event.deltaY * -0.001); + imgScale = Math.max(imgScale, 1.0); + + if (imgScale == 1.0) { + imgTranslateX = 0.0; + imgTranslateY = 0.0; + } + + applyImageTransform(); + } + + function applyImageTransform() { + var img = document.querySelector("div.image-container img"); + img.style.transform = `translate(${imgTranslateX}px,${imgTranslateY}px) scale(${imgScale})` + } + // *** Utility Functions *** function redirectToImage(imageID) { diff --git a/plugins/imageGalleryNavigation/imageGalleryNavigation.yml b/plugins/imageGalleryNavigation/imageGalleryNavigation.yml index 1e6a99e6..d00d0026 100644 --- a/plugins/imageGalleryNavigation/imageGalleryNavigation.yml +++ b/plugins/imageGalleryNavigation/imageGalleryNavigation.yml @@ -1,7 +1,12 @@ name: imageGalleryNavigation # requires: CommunityScriptsUILibrary description: This plugin adds features for navigating between images within a Gallery from the Image details page. -version: 0.2 +version: 0.3 +settings: + enableTransform: + displayName: Enable Zoom/Pan + description: Enable zoom (mouse wheel) and pan (click and drag) on Image detail page. + type: BOOLEAN ui: requires: - CommunityScriptsUILibrary