fix: zoom
This commit is contained in:
@@ -16,6 +16,10 @@ class ImageGallery extends HTMLElement {
|
|||||||
this.startY = 0;
|
this.startY = 0;
|
||||||
this.lastTranslateX = 0;
|
this.lastTranslateX = 0;
|
||||||
this.lastTranslateY = 0;
|
this.lastTranslateY = 0;
|
||||||
|
|
||||||
|
// Pinch zoom state
|
||||||
|
this.initialPinchDistance = 0;
|
||||||
|
this.initialZoom = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
connectedCallback() {
|
connectedCallback() {
|
||||||
@@ -90,7 +94,81 @@ class ImageGallery extends HTMLElement {
|
|||||||
|
|
||||||
// Prevent default drag behavior
|
// Prevent default drag behavior
|
||||||
modalImage.addEventListener("dragstart", (e) => e.preventDefault());
|
modalImage.addEventListener("dragstart", (e) => e.preventDefault());
|
||||||
|
|
||||||
|
// Mouse wheel zoom
|
||||||
|
modalImage.addEventListener("wheel", (e) => this.handleWheel(e), { passive: false });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Pinch zoom for touch devices on modal content
|
||||||
|
const modalContent = this.shadowRoot.querySelector(".modal-content");
|
||||||
|
if (modalContent) {
|
||||||
|
modalContent.addEventListener("touchstart", (e) => this.handleTouchStart(e), { passive: false });
|
||||||
|
modalContent.addEventListener("touchmove", (e) => this.handleTouchMove(e), { passive: false });
|
||||||
|
modalContent.addEventListener("touchend", (e) => this.handleTouchEnd(e));
|
||||||
|
|
||||||
|
// Prevent default browser gestures on the modal
|
||||||
|
modalContent.addEventListener("gesturestart", (e) => e.preventDefault());
|
||||||
|
modalContent.addEventListener("gesturechange", (e) => e.preventDefault());
|
||||||
|
modalContent.addEventListener("gestureend", (e) => e.preventDefault());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleWheel(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
|
||||||
|
const delta = e.deltaY > 0 ? -0.1 : 0.1;
|
||||||
|
this.zoom(delta);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleTouchStart(e) {
|
||||||
|
if (e.touches.length === 2) {
|
||||||
|
// Pinch zoom start
|
||||||
|
e.preventDefault();
|
||||||
|
this.initialPinchDistance = this.getPinchDistance(e.touches);
|
||||||
|
this.initialZoom = this.currentZoom;
|
||||||
|
} else if (e.touches.length === 1 && this.currentZoom > 1) {
|
||||||
|
// Single touch drag when zoomed
|
||||||
|
this.startDrag(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleTouchMove(e) {
|
||||||
|
if (e.touches.length === 2) {
|
||||||
|
// Pinch zoom
|
||||||
|
e.preventDefault();
|
||||||
|
const currentDistance = this.getPinchDistance(e.touches);
|
||||||
|
const scale = currentDistance / this.initialPinchDistance;
|
||||||
|
const newZoom = Math.max(1, Math.min(4, this.initialZoom * scale));
|
||||||
|
|
||||||
|
this.currentZoom = newZoom;
|
||||||
|
|
||||||
|
if (this.currentZoom === 1) {
|
||||||
|
this.translateX = 0;
|
||||||
|
this.translateY = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.updateImageTransform();
|
||||||
|
|
||||||
|
const modalImage = this.shadowRoot.querySelector(".modal-image");
|
||||||
|
if (modalImage) {
|
||||||
|
modalImage.style.cursor = this.currentZoom > 1 ? "grab" : "default";
|
||||||
|
}
|
||||||
|
} else if (e.touches.length === 1 && this.isDragging) {
|
||||||
|
// Single touch drag
|
||||||
|
this.drag(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleTouchEnd(e) {
|
||||||
|
this.initialPinchDistance = 0;
|
||||||
|
this.endDrag();
|
||||||
|
}
|
||||||
|
|
||||||
|
getPinchDistance(touches) {
|
||||||
|
const dx = touches[0].clientX - touches[1].clientX;
|
||||||
|
const dy = touches[0].clientY - touches[1].clientY;
|
||||||
|
return Math.sqrt(dx * dx + dy * dy);
|
||||||
}
|
}
|
||||||
|
|
||||||
startDrag(e) {
|
startDrag(e) {
|
||||||
@@ -263,6 +341,8 @@ class ImageGallery extends HTMLElement {
|
|||||||
background-color: rgba(0, 0, 0, 0.95);
|
background-color: rgba(0, 0, 0, 0.95);
|
||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
touch-action: none;
|
||||||
|
-webkit-touch-callout: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-overlay.open {
|
.modal-overlay.open {
|
||||||
@@ -321,11 +401,13 @@ class ImageGallery extends HTMLElement {
|
|||||||
|
|
||||||
.modal-content {
|
.modal-content {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
overflow: auto;
|
overflow: hidden;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
padding: var(--spacing-md, 1rem);
|
padding: var(--spacing-md, 1rem);
|
||||||
|
touch-action: none;
|
||||||
|
-webkit-touch-callout: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-image {
|
.modal-image {
|
||||||
@@ -336,6 +418,7 @@ class ImageGallery extends HTMLElement {
|
|||||||
cursor: default;
|
cursor: default;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
-webkit-user-drag: none;
|
-webkit-user-drag: none;
|
||||||
|
touch-action: none;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user