react-native-gesture-image-viewer 2.2.0 → 2.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -1
- package/lib/module/GestureViewer.js +2 -2
- package/lib/module/GestureViewer.js.map +1 -1
- package/lib/module/GestureViewerManager.js +27 -23
- package/lib/module/GestureViewerManager.js.map +1 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/useGestureViewer.js +156 -106
- package/lib/module/useGestureViewer.js.map +1 -1
- package/lib/module/useGestureViewerEvent.js +15 -1
- package/lib/module/useGestureViewerEvent.js.map +1 -1
- package/lib/module/useGestureViewerPaging.js +1 -1
- package/lib/module/useGestureViewerPaging.js.map +1 -1
- package/lib/module/useGestureViewerPaging.web.js +47 -26
- package/lib/module/useGestureViewerPaging.web.js.map +1 -1
- package/lib/module/utils/dismiss.js +25 -0
- package/lib/module/utils/dismiss.js.map +1 -0
- package/lib/module/utils/tapZoom.js +6 -6
- package/lib/module/utils/tapZoom.js.map +1 -1
- package/lib/typescript/src/GestureViewer.d.ts.map +1 -1
- package/lib/typescript/src/GestureViewerManager.d.ts +2 -1
- package/lib/typescript/src/GestureViewerManager.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +1 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/types.d.ts +33 -4
- package/lib/typescript/src/types.d.ts.map +1 -1
- package/lib/typescript/src/useGestureViewer.d.ts +2 -2
- package/lib/typescript/src/useGestureViewer.d.ts.map +1 -1
- package/lib/typescript/src/useGestureViewerEvent.d.ts +15 -1
- package/lib/typescript/src/useGestureViewerEvent.d.ts.map +1 -1
- package/lib/typescript/src/useGestureViewerPaging.types.d.ts +9 -1
- package/lib/typescript/src/useGestureViewerPaging.types.d.ts.map +1 -1
- package/lib/typescript/src/useGestureViewerPaging.web.d.ts +1 -1
- package/lib/typescript/src/useGestureViewerPaging.web.d.ts.map +1 -1
- package/lib/typescript/src/utils/dismiss.d.ts +4 -0
- package/lib/typescript/src/utils/dismiss.d.ts.map +1 -0
- package/package.json +1 -1
- package/src/GestureViewer.tsx +4 -2
- package/src/GestureViewerManager.ts +31 -25
- package/src/index.tsx +1 -0
- package/src/types.ts +31 -4
- package/src/useGestureViewer.ts +239 -157
- package/src/useGestureViewerEvent.ts +15 -1
- package/src/useGestureViewerPaging.ts +1 -1
- package/src/useGestureViewerPaging.types.ts +7 -1
- package/src/useGestureViewerPaging.web.ts +56 -32
- package/src/utils/dismiss.ts +36 -0
- package/src/utils/tapZoom.ts +6 -6
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { useCallback, useEffect, useRef } from 'react';
|
|
1
|
+
import { useCallback, useEffect, useRef, type MouseEvent } from 'react';
|
|
2
2
|
import type { NativeScrollEvent, NativeSyntheticEvent } from 'react-native';
|
|
3
3
|
|
|
4
4
|
import type {
|
|
5
5
|
UseGestureViewerPagingArgs,
|
|
6
6
|
UseGestureViewerPagingResult,
|
|
7
|
+
WebClickTarget,
|
|
7
8
|
} from './useGestureViewerPaging.types';
|
|
8
9
|
import { applyTapZoomAtPoint } from './utils/tapZoom';
|
|
9
10
|
import {
|
|
@@ -35,6 +36,7 @@ export function useGestureViewerPaging({
|
|
|
35
36
|
enableHorizontalSwipe,
|
|
36
37
|
enableLoop,
|
|
37
38
|
height,
|
|
39
|
+
onSingleTap,
|
|
38
40
|
isRotated,
|
|
39
41
|
isZoomed,
|
|
40
42
|
itemSpacing,
|
|
@@ -48,6 +50,8 @@ export function useGestureViewerPaging({
|
|
|
48
50
|
translateY,
|
|
49
51
|
width,
|
|
50
52
|
}: UseGestureViewerPagingArgs): UseGestureViewerPagingResult {
|
|
53
|
+
const webSingleTapTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
54
|
+
|
|
51
55
|
const webScrollRuntimeRef = useRef<WebScrollRuntime>({
|
|
52
56
|
actor: 'idle',
|
|
53
57
|
isAutoplayPausedByUser: false,
|
|
@@ -59,6 +63,13 @@ export function useGestureViewerPaging({
|
|
|
59
63
|
resumeAutoplayTimer: null,
|
|
60
64
|
});
|
|
61
65
|
|
|
66
|
+
const clearWebSingleTapTimer = useCallback(() => {
|
|
67
|
+
if (webSingleTapTimerRef.current) {
|
|
68
|
+
clearTimeout(webSingleTapTimerRef.current);
|
|
69
|
+
webSingleTapTimerRef.current = null;
|
|
70
|
+
}
|
|
71
|
+
}, []);
|
|
72
|
+
|
|
62
73
|
const clearWebSettleTimer = useCallback(() => {
|
|
63
74
|
const runtime = webScrollRuntimeRef.current;
|
|
64
75
|
|
|
@@ -232,10 +243,11 @@ export function useGestureViewerPaging({
|
|
|
232
243
|
|
|
233
244
|
useEffect(() => {
|
|
234
245
|
return () => {
|
|
246
|
+
clearWebSingleTapTimer();
|
|
235
247
|
clearWebSettleTimer();
|
|
236
248
|
clearWebAutoplayResumeTimer();
|
|
237
249
|
};
|
|
238
|
-
}, [clearWebAutoplayResumeTimer, clearWebSettleTimer]);
|
|
250
|
+
}, [clearWebAutoplayResumeTimer, clearWebSettleTimer, clearWebSingleTapTimer]);
|
|
239
251
|
|
|
240
252
|
useEffect(() => {
|
|
241
253
|
if (
|
|
@@ -351,50 +363,62 @@ export function useGestureViewerPaging({
|
|
|
351
363
|
manager?.handleScrollBeginDrag();
|
|
352
364
|
}, [beginWebUserInteraction, clearWebSettleTimer, manager]);
|
|
353
365
|
|
|
354
|
-
const
|
|
355
|
-
(event:
|
|
356
|
-
|
|
366
|
+
const onWebClick = useCallback(
|
|
367
|
+
(event: MouseEvent<WebClickTarget>) => {
|
|
368
|
+
const detail = event.detail;
|
|
369
|
+
const rect = event.currentTarget.getBoundingClientRect();
|
|
370
|
+
const resolvedX = event.clientX - rect.left;
|
|
371
|
+
const resolvedY = event.clientY - rect.top;
|
|
372
|
+
|
|
373
|
+
if (!enableDoubleTapZoom) {
|
|
374
|
+
if (!onSingleTap) {
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
clearWebSingleTapTimer();
|
|
379
|
+
onSingleTap(resolvedX, resolvedY);
|
|
357
380
|
return;
|
|
358
381
|
}
|
|
359
382
|
|
|
360
|
-
|
|
361
|
-
|
|
383
|
+
if (detail === 2) {
|
|
384
|
+
clearWebSingleTapTimer();
|
|
362
385
|
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
let locationX = nativeEvent?.locationX;
|
|
366
|
-
let locationY = nativeEvent?.locationY;
|
|
386
|
+
pauseWebAutoplayWithoutPagingInteraction();
|
|
387
|
+
scheduleWebAutoplayResume();
|
|
367
388
|
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
389
|
+
applyTapZoomAtPoint({
|
|
390
|
+
x: resolvedX,
|
|
391
|
+
y: resolvedY,
|
|
392
|
+
width,
|
|
393
|
+
height,
|
|
394
|
+
maxZoomScale,
|
|
395
|
+
scale,
|
|
396
|
+
translateX,
|
|
397
|
+
translateY,
|
|
398
|
+
});
|
|
399
|
+
return;
|
|
400
|
+
}
|
|
375
401
|
|
|
376
|
-
|
|
377
|
-
|
|
402
|
+
if (detail !== 1 || !onSingleTap) {
|
|
403
|
+
return;
|
|
378
404
|
}
|
|
379
405
|
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
scale,
|
|
387
|
-
translateX,
|
|
388
|
-
translateY,
|
|
389
|
-
});
|
|
406
|
+
clearWebSingleTapTimer();
|
|
407
|
+
|
|
408
|
+
webSingleTapTimerRef.current = setTimeout(() => {
|
|
409
|
+
onSingleTap(resolvedX, resolvedY);
|
|
410
|
+
webSingleTapTimerRef.current = null;
|
|
411
|
+
}, 250);
|
|
390
412
|
},
|
|
391
413
|
[
|
|
414
|
+
clearWebSingleTapTimer,
|
|
392
415
|
enableDoubleTapZoom,
|
|
393
416
|
height,
|
|
394
417
|
maxZoomScale,
|
|
418
|
+
onSingleTap,
|
|
395
419
|
pauseWebAutoplayWithoutPagingInteraction,
|
|
396
|
-
scheduleWebAutoplayResume,
|
|
397
420
|
scale,
|
|
421
|
+
scheduleWebAutoplayResume,
|
|
398
422
|
translateX,
|
|
399
423
|
translateY,
|
|
400
424
|
width,
|
|
@@ -405,6 +429,6 @@ export function useGestureViewerPaging({
|
|
|
405
429
|
onMomentumScrollEnd,
|
|
406
430
|
onScroll,
|
|
407
431
|
onScrollBeginDrag,
|
|
408
|
-
|
|
432
|
+
onWebClick,
|
|
409
433
|
};
|
|
410
434
|
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { GestureViewerDismissDirection } from '../types';
|
|
2
|
+
|
|
3
|
+
export const shouldDismissByDirection = (
|
|
4
|
+
translationY: number,
|
|
5
|
+
threshold: number,
|
|
6
|
+
direction: GestureViewerDismissDirection,
|
|
7
|
+
): boolean => {
|
|
8
|
+
'worklet';
|
|
9
|
+
|
|
10
|
+
if (direction === 'up') {
|
|
11
|
+
return translationY < -threshold;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
if (direction === 'both') {
|
|
15
|
+
return Math.abs(translationY) > threshold;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return translationY > threshold;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const getDismissDistance = (
|
|
22
|
+
translationY: number,
|
|
23
|
+
direction: GestureViewerDismissDirection,
|
|
24
|
+
): number => {
|
|
25
|
+
'worklet';
|
|
26
|
+
|
|
27
|
+
if (direction === 'up') {
|
|
28
|
+
return Math.max(-translationY, 0);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (direction === 'both') {
|
|
32
|
+
return Math.abs(translationY);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return Math.max(translationY, 0);
|
|
36
|
+
};
|
package/src/utils/tapZoom.ts
CHANGED
|
@@ -22,7 +22,7 @@ export const applyTapZoomAtPoint = ({
|
|
|
22
22
|
}) => {
|
|
23
23
|
'worklet';
|
|
24
24
|
|
|
25
|
-
const nextScale = scale.
|
|
25
|
+
const nextScale = scale.get() > 1 ? 1 : maxZoomScale;
|
|
26
26
|
const timingConfig = {
|
|
27
27
|
duration: 300,
|
|
28
28
|
easing: Easing.bezier(0.25, 0.1, 0.25, 1),
|
|
@@ -33,12 +33,12 @@ export const applyTapZoomAtPoint = ({
|
|
|
33
33
|
const centerY = y - height / 2;
|
|
34
34
|
|
|
35
35
|
// NOTE 확대로 밀려난 거리만큼 반대로 이동해서 탭 지점을 제자리에 유지
|
|
36
|
-
translateX.
|
|
37
|
-
translateY.
|
|
36
|
+
translateX.set(withTiming(-centerX * (nextScale - 1), timingConfig));
|
|
37
|
+
translateY.set(withTiming(-centerY * (nextScale - 1), timingConfig));
|
|
38
38
|
} else {
|
|
39
|
-
translateX.
|
|
40
|
-
translateY.
|
|
39
|
+
translateX.set(withTiming(0, timingConfig));
|
|
40
|
+
translateY.set(withTiming(0, timingConfig));
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
scale.
|
|
43
|
+
scale.set(withTiming(nextScale, timingConfig));
|
|
44
44
|
};
|