@@ -105,11 +105,10 @@ function Parvus(userOptions) {
105
105
let isDraggingX = false ;
106
106
let isDraggingY = false ;
107
107
let pointerDown = false ;
108
- let pinchStartDistance = 0 ;
109
108
let currentScale = 1 ;
110
109
let isPinching = false ;
111
- let lastScale = 1 ;
112
- let baseScale = 1 ;
110
+ let pinchStartDistance = 0 ;
111
+ let lastPointersId = null ;
113
112
let offset = null ;
114
113
let offsetTmp = null ;
115
114
let resizeTicking = false ;
@@ -997,6 +996,40 @@ function Parvus(userOptions) {
997
996
contentEl . style . height = USE_ORIGINAL_SIZE ? '' : `${ NEW_HEIGHT } px` ;
998
997
} ;
999
998
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
+
1000
1033
/**
1001
1034
* Click event handler to trigger Parvus
1002
1035
*
@@ -1092,13 +1125,11 @@ function Parvus(userOptions) {
1092
1125
isDraggingX = false ;
1093
1126
isDraggingY = false ;
1094
1127
pointerDown = true ;
1095
- const {
1096
- pageX,
1097
- pageY
1098
- } = event ;
1099
1128
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 ;
1102
1133
const {
1103
1134
slider
1104
1135
} = GROUPS [ activeGroup ] ;
@@ -1122,38 +1153,23 @@ function Parvus(userOptions) {
1122
1153
if ( ! pointerDown ) {
1123
1154
return ;
1124
1155
}
1125
- const currentImg = GROUPS [ activeGroup ] . contentElements [ currentIndex ] ;
1156
+ const CURRENT_IMAGE = GROUPS [ activeGroup ] . contentElements [ currentIndex ] ;
1126
1157
1127
1158
// Update pointer position
1128
1159
activePointers . set ( event . pointerId , event ) ;
1129
1160
1130
1161
// Zoom
1131
- if ( currentImg && currentImg . tagName === 'IMG' ) {
1162
+ if ( CURRENT_IMAGE && CURRENT_IMAGE . tagName === 'IMG' ) {
1132
1163
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 ) ;
1145
1165
return ;
1146
1166
}
1147
1167
if ( currentScale > 1 ) {
1148
1168
return ;
1149
1169
}
1150
1170
}
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 ;
1157
1173
doSwipe ( ) ;
1158
1174
} ;
1159
1175
@@ -1170,25 +1186,39 @@ function Parvus(userOptions) {
1170
1186
const {
1171
1187
slider
1172
1188
} = GROUPS [ activeGroup ] ;
1189
+ activePointers . delete ( event . pointerId ) ;
1190
+ if ( activePointers . size > 0 ) {
1191
+ return ;
1192
+ }
1173
1193
pointerDown = false ;
1174
- isPinching = false ;
1175
1194
const CURRENT_IMAGE = GROUPS [ activeGroup ] . contentElements [ currentIndex ] ;
1195
+
1176
1196
slider . classList . remove ( 'parvus__slider--is-dragging' ) ;
1177
1197
slider . style . willChange = '' ;
1178
1198
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
+ ` ;
1182
1203
}
1183
1204
} 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
+ }
1186
1217
if ( drag . endX || drag . endY ) {
1187
1218
updateAfterDrag ( ) ;
1188
1219
}
1189
1220
}
1190
1221
clearDrag ( ) ;
1191
- activePointers . delete ( event . pointerId ) ;
1192
1222
} ;
1193
1223
1194
1224
/**
0 commit comments