diff --git a/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Resources/svg2html.js b/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Resources/svg2html.js index 0946a2f..dd6b08e 100644 --- a/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Resources/svg2html.js +++ b/QuickLook.Plugin/QuickLook.Plugin.ImageViewer/Resources/svg2html.js @@ -33,29 +33,79 @@ const base64 = encodeSvgToBase64(fixSvgSize(svgString)); const img = new Image(); img.src = `data:image/svg+xml;base64,${base64}`; - img.style.transform = "scale(1)"; + img.draggable = false; let scale = 1; + let offsetX = 0; + let offsetY = 0; + let startX = 0; + let startY = 0; + let isDragging = false; + let imgNaturalWidth = 0; + let imgNaturalHeight = 0; + let canDragX = false; + let canDragY = false; + + function clamp(val, min, max) { + return Math.max(min, Math.min(max, val)); + } function updateTransform() { - img.style.transform = `scale(${scale})`; + // Calculate draggable range + const wrapperRect = wrapper.getBoundingClientRect(); + const w = imgNaturalWidth * scale; + const h = imgNaturalHeight * scale; + canDragX = w > wrapperRect.width; + canDragY = h > wrapperRect.height; + const maxOffsetX = canDragX ? (w - wrapperRect.width) / 2 : 0; + const maxOffsetY = canDragY ? (h - wrapperRect.height) / 2 : 0; + offsetX = canDragX ? clamp(offsetX, -maxOffsetX, maxOffsetX) : 0; + offsetY = canDragY ? clamp(offsetY, -maxOffsetY, maxOffsetY) : 0; + img.style.transform = `translate(${offsetX}px, ${offsetY}px) scale(${scale})`; } + img.onload = function () { + imgNaturalWidth = img.naturalWidth; + imgNaturalHeight = img.naturalHeight; + updateTransform(); + }; + document.addEventListener("wheel", (e) => { e.preventDefault(); - const scaleFactor = 1.2; - + const prevScale = scale; scale *= (e.deltaY < 0 ? scaleFactor : 1 / scaleFactor); + // Zoom based on window center, do not adjust offsetX/offsetY updateTransform(); }, { passive: false }); - // Add double-click event to reset zoom + // Drag events + img.addEventListener("mousedown", (e) => { + if (!(canDragX || canDragY)) return; + isDragging = true; + startX = e.clientX - offsetX; + startY = e.clientY - offsetY; + }); + document.addEventListener("mousemove", (e) => { + if (!isDragging) return; + if (canDragX) offsetX = e.clientX - startX; else offsetX = 0; + if (canDragY) offsetY = e.clientY - startY; else offsetY = 0; + updateTransform(); + }); + document.addEventListener("mouseup", () => { + isDragging = false; + }); + document.addEventListener("mouseleave", () => { + isDragging = false; + }); + + // Double-click to reset zoom and position wrapper.addEventListener("dblclick", () => { scale = 1; + offsetX = 0; + offsetY = 0; updateTransform(); }); wrapper.appendChild(img); - updateTransform(); })();