Skip to content

Commit fd4ebf1

Browse files
committed
[TASK] Improve pointer event handler, separate pinchZoom function
1 parent 3687c15 commit fd4ebf1

File tree

5 files changed

+222
-114
lines changed

5 files changed

+222
-114
lines changed

dist/js/parvus.esm.js

+66-36
Original file line numberDiff line numberDiff line change
@@ -105,11 +105,10 @@ function Parvus(userOptions) {
105105
let isDraggingX = false;
106106
let isDraggingY = false;
107107
let pointerDown = false;
108-
let pinchStartDistance = 0;
109108
let currentScale = 1;
110109
let isPinching = false;
111-
let lastScale = 1;
112-
let baseScale = 1;
110+
let pinchStartDistance = 0;
111+
let lastPointersId = null;
113112
let offset = null;
114113
let offsetTmp = null;
115114
let resizeTicking = false;
@@ -997,6 +996,40 @@ function Parvus(userOptions) {
997996
contentEl.style.height = USE_ORIGINAL_SIZE ? '' : `${NEW_HEIGHT}px`;
998997
};
999998

999+
/**
1000+
* Pinch zoom gesture
1001+
*
1002+
* @param {HTMLImageElement} currentImg - The image to zoom
1003+
*/
1004+
const pinchZoom = currentImg => {
1005+
// Determine current finger positions
1006+
const points = Array.from(activePointers.values());
1007+
1008+
// Calculate current distance between fingers
1009+
const currentDistance = Math.hypot(points[1].clientX - points[0].clientX, points[1].clientY - points[0].clientY);
1010+
1011+
// When pinch gesture is about to start or the finger IDs have changed
1012+
// We use a unique ID based on the pointer IDs to recognize changes
1013+
const currentPointersId = points.map(p => p.pointerId).sort().join('-');
1014+
const isNewPointerCombination = lastPointersId !== currentPointersId;
1015+
if (!isPinching || isNewPointerCombination) {
1016+
isPinching = true;
1017+
lastPointersId = currentPointersId;
1018+
1019+
// Save the start distance and current scaling as a basis
1020+
pinchStartDistance = currentDistance / currentScale;
1021+
lightbox.classList.add('parvus--is-zooming');
1022+
}
1023+
1024+
// Calculate scaling factor based on distance change
1025+
const scaleFactor = currentDistance / pinchStartDistance;
1026+
1027+
// Limit scaling to 1 - 3
1028+
currentScale = Math.min(Math.max(1, scaleFactor), 3);
1029+
currentImg.style.willChange = 'transform';
1030+
currentImg.style.transform = `scale(${currentScale})`;
1031+
};
1032+
10001033
/**
10011034
* Click event handler to trigger Parvus
10021035
*
@@ -1092,13 +1125,11 @@ function Parvus(userOptions) {
10921125
isDraggingX = false;
10931126
isDraggingY = false;
10941127
pointerDown = true;
1095-
const {
1096-
pageX,
1097-
pageY
1098-
} = event;
10991128
activePointers.set(event.pointerId, event);
1100-
drag.startX = pageX;
1101-
drag.startY = pageY;
1129+
drag.startX = event.pageX;
1130+
drag.startY = event.pageY;
1131+
drag.endX = event.pageX;
1132+
drag.endY = event.pageY;
11021133
const {
11031134
slider
11041135
} = GROUPS[activeGroup];
@@ -1122,38 +1153,23 @@ function Parvus(userOptions) {
11221153
if (!pointerDown) {
11231154
return;
11241155
}
1125-
const currentImg = GROUPS[activeGroup].contentElements[currentIndex];
1156+
const CURRENT_IMAGE = GROUPS[activeGroup].contentElements[currentIndex];
11261157

11271158
// Update pointer position
11281159
activePointers.set(event.pointerId, event);
11291160

11301161
// Zoom
1131-
if (currentImg && currentImg.tagName === 'IMG') {
1162+
if (CURRENT_IMAGE && CURRENT_IMAGE.tagName === 'IMG') {
11321163
if (activePointers.size === 2) {
1133-
const points = Array.from(activePointers.values());
1134-
const distance = Math.hypot(points[1].clientX - points[0].clientX, points[1].clientY - points[0].clientY);
1135-
if (!isPinching) {
1136-
pinchStartDistance = distance;
1137-
isPinching = true;
1138-
baseScale = lastScale;
1139-
lightbox.classList.add('parvus--is-zooming');
1140-
}
1141-
currentScale = Math.min(Math.max(1, baseScale * (distance / pinchStartDistance)), 3);
1142-
currentImg.style.willChange = 'transform';
1143-
currentImg.style.transform = `scale(${currentScale})`;
1144-
lastScale = currentScale;
1164+
pinchZoom(CURRENT_IMAGE);
11451165
return;
11461166
}
11471167
if (currentScale > 1) {
11481168
return;
11491169
}
11501170
}
1151-
const {
1152-
pageX,
1153-
pageY
1154-
} = event;
1155-
drag.endX = pageX;
1156-
drag.endY = pageY;
1171+
drag.endX = event.pageX;
1172+
drag.endY = event.pageY;
11571173
doSwipe();
11581174
};
11591175

@@ -1170,25 +1186,39 @@ function Parvus(userOptions) {
11701186
const {
11711187
slider
11721188
} = GROUPS[activeGroup];
1189+
activePointers.delete(event.pointerId);
1190+
if (activePointers.size > 0) {
1191+
return;
1192+
}
11731193
pointerDown = false;
1174-
isPinching = false;
11751194
const CURRENT_IMAGE = GROUPS[activeGroup].contentElements[currentIndex];
1195+
11761196
slider.classList.remove('parvus__slider--is-dragging');
11771197
slider.style.willChange = '';
11781198
if (currentScale > 1) {
1179-
baseScale = lastScale;
1180-
if (CURRENT_IMAGE && CURRENT_IMAGE.tagName === 'IMG') {
1181-
CURRENT_IMAGE.style.transform = `scale(${currentScale})`;
1199+
{
1200+
CURRENT_IMAGE.style.transform = `
1201+
scale(${currentScale})
1202+
`;
11821203
}
11831204
} else {
1184-
pinchStartDistance = 0;
1185-
lightbox.classList.remove('parvus--is-zooming');
1205+
if (isPinching) {
1206+
CURRENT_IMAGE.style.transition = 'transform 0.3s ease';
1207+
CURRENT_IMAGE.style.transform = '';
1208+
setTimeout(() => {
1209+
CURRENT_IMAGE.style.transition = '';
1210+
}, 300);
1211+
isPinching = false;
1212+
currentScale = 1;
1213+
pinchStartDistance = 0;
1214+
lastPointersId = '';
1215+
lightbox.classList.remove('parvus--is-zooming');
1216+
}
11861217
if (drag.endX || drag.endY) {
11871218
updateAfterDrag();
11881219
}
11891220
}
11901221
clearDrag();
1191-
activePointers.delete(event.pointerId);
11921222
};
11931223

11941224
/**

0 commit comments

Comments
 (0)