mirror of
https://github.com/QL-Win/QuickLook.git
synced 2025-09-14 12:19:08 +00:00
Add pan and zoom support to SVG image viewer
This commit is contained in:
@@ -33,29 +33,79 @@
|
|||||||
const base64 = encodeSvgToBase64(fixSvgSize(svgString));
|
const base64 = encodeSvgToBase64(fixSvgSize(svgString));
|
||||||
const img = new Image();
|
const img = new Image();
|
||||||
img.src = `data:image/svg+xml;base64,${base64}`;
|
img.src = `data:image/svg+xml;base64,${base64}`;
|
||||||
img.style.transform = "scale(1)";
|
img.draggable = false;
|
||||||
|
|
||||||
let scale = 1;
|
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() {
|
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) => {
|
document.addEventListener("wheel", (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
const scaleFactor = 1.2;
|
const scaleFactor = 1.2;
|
||||||
|
const prevScale = scale;
|
||||||
scale *= (e.deltaY < 0 ? scaleFactor : 1 / scaleFactor);
|
scale *= (e.deltaY < 0 ? scaleFactor : 1 / scaleFactor);
|
||||||
|
// Zoom based on window center, do not adjust offsetX/offsetY
|
||||||
updateTransform();
|
updateTransform();
|
||||||
}, { passive: false });
|
}, { 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", () => {
|
wrapper.addEventListener("dblclick", () => {
|
||||||
scale = 1;
|
scale = 1;
|
||||||
|
offsetX = 0;
|
||||||
|
offsetY = 0;
|
||||||
updateTransform();
|
updateTransform();
|
||||||
});
|
});
|
||||||
|
|
||||||
wrapper.appendChild(img);
|
wrapper.appendChild(img);
|
||||||
updateTransform();
|
|
||||||
})();
|
})();
|
||||||
|
Reference in New Issue
Block a user