Skip to content

Commit 4a591e7

Browse files
committed
[FEATURE] Add pinch zoom gesture (WIP)
Related: #42
1 parent 03f57b7 commit 4a591e7

File tree

5 files changed

+169
-45
lines changed

5 files changed

+169
-45
lines changed

dist/js/parvus.esm.js

+52-15
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,13 @@ var en = {
6969
slideLabel: 'Image'
7070
};
7171

72+
/**
73+
* Parvus Lightbox
74+
*
75+
* @param {Object} userOptions - User configuration options
76+
* @returns {Object} Parvus instance
77+
*/
7278
function Parvus(userOptions) {
73-
/**
74-
* Global variables
75-
*
76-
*/
7779
const BROWSER_WINDOW = window;
7880
const GROUP_ATTRIBUTES = {
7981
triggerElements: [],
@@ -82,6 +84,7 @@ function Parvus(userOptions) {
8284
contentElements: []
8385
};
8486
const GROUPS = {};
87+
const activePointers = new Map();
8588
let groupIdCounter = 0;
8689
let newGroup = null;
8790
let activeGroup = null;
@@ -102,6 +105,11 @@ function Parvus(userOptions) {
102105
let isDraggingX = false;
103106
let isDraggingY = false;
104107
let pointerDown = false;
108+
let pinchStartDistance = 0;
109+
let currentScale = 1;
110+
let isPinching = false;
111+
let lastScale = 1;
112+
let baseScale = 1;
105113
let offset = null;
106114
let offsetTmp = null;
107115
let resizeTicking = false;
@@ -1059,16 +1067,14 @@ function Parvus(userOptions) {
10591067
const pointerdownHandler = event => {
10601068
event.preventDefault();
10611069
event.stopPropagation();
1062-
if (event.pointerType === 'mouse' && !config.simulateTouch) {
1063-
return;
1064-
}
10651070
isDraggingX = false;
10661071
isDraggingY = false;
10671072
pointerDown = true;
10681073
const {
10691074
pageX,
10701075
pageY
10711076
} = event;
1077+
activePointers.set(event.pointerId, event);
10721078
drag.startX = pageX;
10731079
drag.startY = pageY;
10741080
const {
@@ -1089,15 +1095,39 @@ function Parvus(userOptions) {
10891095
*/
10901096
const pointermoveHandler = event => {
10911097
event.preventDefault();
1092-
if (pointerDown) {
1093-
const {
1094-
pageX,
1095-
pageY
1096-
} = event;
1097-
drag.endX = pageX;
1098-
drag.endY = pageY;
1099-
doSwipe();
1098+
if (!pointerDown) {
1099+
return;
1100+
}
1101+
const currentImg = GROUPS[activeGroup].sliderElements[currentIndex];
1102+
1103+
// Update pointer position
1104+
activePointers.set(event.pointerId, event);
1105+
1106+
// Zoom
1107+
if (activePointers.size === 2) {
1108+
const points = Array.from(activePointers.values());
1109+
const distance = Math.hypot(points[1].clientX - points[0].clientX, points[1].clientY - points[0].clientY);
1110+
if (!isPinching) {
1111+
pinchStartDistance = distance;
1112+
isPinching = true;
1113+
baseScale = lastScale;
1114+
}
1115+
currentScale = baseScale * (distance / pinchStartDistance);
1116+
currentScale = Math.min(Math.max(1, currentScale), 3);
1117+
currentImg.style.transform = `scale(${currentScale})`;
1118+
lastScale = currentScale;
1119+
return;
11001120
}
1121+
if (currentScale > 1) {
1122+
return;
1123+
}
1124+
const {
1125+
pageX,
1126+
pageY
1127+
} = event;
1128+
drag.endX = pageX;
1129+
drag.endY = pageY;
1130+
doSwipe();
11011131
};
11021132

11031133
/**
@@ -1111,6 +1141,7 @@ function Parvus(userOptions) {
11111141
const pointerupHandler = event => {
11121142
event.stopPropagation();
11131143
pointerDown = false;
1144+
isPinching = false;
11141145
const {
11151146
slider
11161147
} = GROUPS[activeGroup];
@@ -1120,6 +1151,12 @@ function Parvus(userOptions) {
11201151
updateAfterDrag();
11211152
}
11221153
clearDrag();
1154+
activePointers.delete(event.pointerId);
1155+
if (currentScale > 1) {
1156+
baseScale = lastScale;
1157+
} else {
1158+
pinchStartDistance = 0;
1159+
}
11231160
};
11241161

11251162
/**

dist/js/parvus.esm.min.js

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/js/parvus.js

+52-15
Original file line numberDiff line numberDiff line change
@@ -75,11 +75,13 @@
7575
slideLabel: 'Image'
7676
};
7777

78+
/**
79+
* Parvus Lightbox
80+
*
81+
* @param {Object} userOptions - User configuration options
82+
* @returns {Object} Parvus instance
83+
*/
7884
function Parvus(userOptions) {
79-
/**
80-
* Global variables
81-
*
82-
*/
8385
const BROWSER_WINDOW = window;
8486
const GROUP_ATTRIBUTES = {
8587
triggerElements: [],
@@ -88,6 +90,7 @@
8890
contentElements: []
8991
};
9092
const GROUPS = {};
93+
const activePointers = new Map();
9194
let groupIdCounter = 0;
9295
let newGroup = null;
9396
let activeGroup = null;
@@ -108,6 +111,11 @@
108111
let isDraggingX = false;
109112
let isDraggingY = false;
110113
let pointerDown = false;
114+
let pinchStartDistance = 0;
115+
let currentScale = 1;
116+
let isPinching = false;
117+
let lastScale = 1;
118+
let baseScale = 1;
111119
let offset = null;
112120
let offsetTmp = null;
113121
let resizeTicking = false;
@@ -1065,16 +1073,14 @@
10651073
const pointerdownHandler = event => {
10661074
event.preventDefault();
10671075
event.stopPropagation();
1068-
if (event.pointerType === 'mouse' && !config.simulateTouch) {
1069-
return;
1070-
}
10711076
isDraggingX = false;
10721077
isDraggingY = false;
10731078
pointerDown = true;
10741079
const {
10751080
pageX,
10761081
pageY
10771082
} = event;
1083+
activePointers.set(event.pointerId, event);
10781084
drag.startX = pageX;
10791085
drag.startY = pageY;
10801086
const {
@@ -1095,15 +1101,39 @@
10951101
*/
10961102
const pointermoveHandler = event => {
10971103
event.preventDefault();
1098-
if (pointerDown) {
1099-
const {
1100-
pageX,
1101-
pageY
1102-
} = event;
1103-
drag.endX = pageX;
1104-
drag.endY = pageY;
1105-
doSwipe();
1104+
if (!pointerDown) {
1105+
return;
1106+
}
1107+
const currentImg = GROUPS[activeGroup].sliderElements[currentIndex];
1108+
1109+
// Update pointer position
1110+
activePointers.set(event.pointerId, event);
1111+
1112+
// Zoom
1113+
if (activePointers.size === 2) {
1114+
const points = Array.from(activePointers.values());
1115+
const distance = Math.hypot(points[1].clientX - points[0].clientX, points[1].clientY - points[0].clientY);
1116+
if (!isPinching) {
1117+
pinchStartDistance = distance;
1118+
isPinching = true;
1119+
baseScale = lastScale;
1120+
}
1121+
currentScale = baseScale * (distance / pinchStartDistance);
1122+
currentScale = Math.min(Math.max(1, currentScale), 3);
1123+
currentImg.style.transform = `scale(${currentScale})`;
1124+
lastScale = currentScale;
1125+
return;
11061126
}
1127+
if (currentScale > 1) {
1128+
return;
1129+
}
1130+
const {
1131+
pageX,
1132+
pageY
1133+
} = event;
1134+
drag.endX = pageX;
1135+
drag.endY = pageY;
1136+
doSwipe();
11071137
};
11081138

11091139
/**
@@ -1117,6 +1147,7 @@
11171147
const pointerupHandler = event => {
11181148
event.stopPropagation();
11191149
pointerDown = false;
1150+
isPinching = false;
11201151
const {
11211152
slider
11221153
} = GROUPS[activeGroup];
@@ -1126,6 +1157,12 @@
11261157
updateAfterDrag();
11271158
}
11281159
clearDrag();
1160+
activePointers.delete(event.pointerId);
1161+
if (currentScale > 1) {
1162+
baseScale = lastScale;
1163+
} else {
1164+
pinchStartDistance = 0;
1165+
}
11291166
};
11301167

11311168
/**

0 commit comments

Comments
 (0)