Skip to content

Commit 29c0ccd

Browse files
committed
feat(image-viewer): 优化preview
1 parent e068d1e commit 29c0ccd

File tree

3 files changed

+15
-152
lines changed

3 files changed

+15
-152
lines changed

src/image-viewer/image-viewer.tsx

Lines changed: 6 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { MouseEvent, useRef, useState, useEffect } from 'react';
1+
import React, { MouseEvent, useRef, useEffect } from 'react';
22
import { CloseIcon, DeleteIcon } from 'tdesign-icons-react';
33
import { CSSTransition } from 'react-transition-group';
44
import { CSSTransitionClassNames } from 'react-transition-group/CSSTransition';
@@ -29,29 +29,12 @@ const ImageViewer: React.FC<ImageViewerProps> = (props) => {
2929

3030
const [show, setShow] = useDefault<boolean, any>(visible, defaultVisible, noop);
3131
const [currentIndex, setCurrentIndex] = useDefault(index, defaultIndex, onIndexChange);
32-
const [innerState, setInnerState] = useState({
33-
dblTapZooming: false, // double tap zooming
34-
zooming: false, // pinch zooming
35-
scale: 1,
36-
touchIndex: 0,
37-
dragging: false,
38-
draggedX: 0,
39-
draggedY: 0,
40-
extraDraggedX: 0,
41-
});
4232

4333
const swiperRootRef = useRef<HTMLDivElement>(null);
4434
const rootRef = useRef<HTMLDivElement>(null);
4535
const imgRefs = useRef<HTMLImageElement[]>([]);
4636
const duration = 300;
47-
const { transform, resetTransform, updateTransform, dispatchZoomChange } = useImageTransform(
48-
imgRefs,
49-
MIN_SCALE,
50-
MAX_SCALE,
51-
undefined,
52-
// onTransform,
53-
// currentIndex,
54-
);
37+
const { transform, resetTransform, updateTransform, dispatchZoomChange } = useImageTransform(MIN_SCALE, MAX_SCALE);
5538
const { isTouching, onTouchStart, onTouchMove, onTouchEnd } = useTouchEvent(
5639
imgRefs,
5740
movable,
@@ -70,23 +53,9 @@ const ImageViewer: React.FC<ImageViewerProps> = (props) => {
7053
// eslint-disable-next-line react-hooks/exhaustive-deps
7154
}, [show]);
7255

73-
const beforeClose = () => {
74-
setInnerState({
75-
...innerState,
76-
dblTapZooming: false,
77-
zooming: false,
78-
scale: 1,
79-
dragging: false,
80-
draggedX: 0,
81-
draggedY: 0,
82-
extraDraggedX: 0,
83-
});
84-
};
85-
8656
const imageViewerClass = usePrefixClass('image-viewer');
8757
const handleClose = (e: MouseEvent, trigger: 'overlay' | 'close-btn') => {
8858
e.stopPropagation();
89-
beforeClose();
9059
setShow(false);
9160
onClose?.({ trigger, visible: false, index });
9261
};
@@ -124,24 +93,15 @@ const ImageViewer: React.FC<ImageViewerProps> = (props) => {
12493
preload: preloadImageIndex.includes(index),
12594
};
12695
});
127-
// const [imageInfoList, setImageInfoList] = useState(rawImageInfoList)
12896

129-
// useEffect(() => {
130-
// if (transform.scale === 1 && rawImageInfoList.length !== imageInfoList.length) {
131-
//
132-
// setImageInfoList(rawImageInfoList);
133-
// }
134-
// }, [transform, rawImageInfoList, imageInfoList])
135-
136-
const onDoubleClick = (event: MouseEvent) => {
97+
const onDoubleClick = () => {
13798
if (show) {
13899
if (transform.scale !== 1) {
139100
updateTransform({ x: 0, y: 0, scale: 1 }, 'doubleClick');
140101
} else {
141-
dispatchZoomChange(BASE_SCALE_RATIO + scaleStep, 'doubleClick', event.clientX, event.clientY);
102+
dispatchZoomChange(BASE_SCALE_RATIO + scaleStep, 'doubleClick');
142103
}
143104
}
144-
// setImageInfoList([info]);
145105
};
146106

147107
const onSwiperChange = (index: number) => {
@@ -154,15 +114,6 @@ const ImageViewer: React.FC<ImageViewerProps> = (props) => {
154114
}
155115
};
156116

157-
// const getImageTransform = () => {
158-
// const { scale, draggedX, draggedY } = innerState;
159-
// return `matrix(${scale}, 0, 0, ${scale}, ${draggedX}, ${draggedY})`;
160-
// };
161-
// const getImageTransitionDuration = () => {
162-
// const { zooming, dragging } = innerState;
163-
// return zooming || dragging ? { transitionDuration: '0s' } : { transitionDuration: '0.3s' };
164-
// };
165-
166117
const animationClassNames: CSSTransitionClassNames = {
167118
enterActive: 'fade-enter-active',
168119
exitActive: 'fade-leave-active',
@@ -202,26 +153,21 @@ const ImageViewer: React.FC<ImageViewerProps> = (props) => {
202153
}}
203154
hostStyle={{ overflow: 'visible' }}
204155
>
205-
{/* style={{
206-
transform: index === innerState.touchIndex ? getImageTransform() : 'matrix(1, 0, 0, 1, 0, 0)',
207-
...getImageTransitionDuration(),
208-
height: '100%',
209-
}} */}
210156
<img
211157
src={info.image.url}
212158
ref={(node) => {
213159
imgRefs.current[index] = node;
214160
}}
215161
style={{
216-
transform: `matrix(${transform.scale}, 0, 0, ${transform.scale}, ${transform.x}, ${transform.y})`,
162+
transform: `matrix(${transform.scale}, 0, 0, ${transform.scale}, ${transform.x}, 0)`,
217163
transitionDuration: isTouching ? '0s' : '.3s',
218164
}}
219165
className={`${imageViewerClass}__img`}
220166
onTouchStart={onTouchStart}
221167
onTouchMove={onTouchMove}
222168
onTouchEnd={onTouchEnd}
223169
onTouchCancel={onTouchEnd}
224-
onDoubleClick={(e) => onDoubleClick(e)}
170+
onDoubleClick={onDoubleClick}
225171
/>
226172
</TSwiperItem>
227173
))}

src/image-viewer/transform.ts

Lines changed: 2 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { useRef, useState } from 'react';
22
import raf from './raf';
3-
// import { getClientSize } from './util';
43

54
function isEqual(objA, objB) {
65
const keys = Object.keys(objA);
@@ -41,13 +40,7 @@ export type TransformAction =
4140

4241
export type UpdateTransformFunc = (newTransform: Partial<TransformType>, action: TransformAction) => void;
4342

44-
export type DispatchZoomChangeFunc = (
45-
ratio: number,
46-
action: TransformAction,
47-
centerX?: number,
48-
centerY?: number,
49-
isTouch?: boolean,
50-
) => void;
43+
export type DispatchZoomChangeFunc = (ratio: number, action: TransformAction, isTouch?: boolean) => void;
5144

5245
const initialTransform = {
5346
x: 0,
@@ -59,11 +52,9 @@ const initialTransform = {
5952
};
6053

6154
export function useImageTransform(
62-
imgRef: React.MutableRefObject<HTMLImageElement[]>,
6355
minScale: number,
6456
maxScale: number,
6557
onTransform?: (info: { transform: TransformType; action: TransformAction }) => void,
66-
// currentIndex?: number,
6758
) {
6859
const frame = useRef(null);
6960
const queue = useRef<TransformType[]>([]);
@@ -76,7 +67,6 @@ export function useImageTransform(
7667
}
7768
};
7869

79-
/** Direct update transform */
8070
const updateTransform: UpdateTransformFunc = (newTransform, action) => {
8171
if (frame.current === null) {
8272
queue.current = [];
@@ -99,59 +89,17 @@ export function useImageTransform(
9989
});
10090
};
10191

102-
/** Scale according to the position of centerX and centerY */
10392
const dispatchZoomChange: DispatchZoomChangeFunc = (ratio, action, centerX?, centerY?, isTouch?) => {
104-
// const { width, height, offsetWidth, offsetHeight, offsetLeft, offsetTop } = imgRef.current[currentIndex];
105-
106-
// let newRatio = ratio;
10793
let newScale = transform.scale * ratio;
94+
10895
if (newScale > maxScale) {
10996
newScale = maxScale;
110-
// newRatio = maxScale / transform.scale;
11197
} else if (newScale < minScale) {
112-
// For mobile interactions, allow scaling down to the minimum scale.
11398
newScale = isTouch ? newScale : minScale;
114-
// newRatio = newScale / transform.scale;
115-
}
116-
117-
/** Default center point scaling */
118-
// const mergedCenterX = centerX ?? innerWidth / 2;
119-
// const mergedCenterY = centerY ?? innerHeight / 2;
120-
121-
// const diffRatio = newRatio - 1;
122-
// /** Deviation calculated from image size */
123-
// const diffImgX = diffRatio * width * 0.5;
124-
// const diffImgY = diffRatio * height * 0.5;
125-
// /** The difference between the click position and the edge of the document */
126-
// const diffOffsetLeft = diffRatio * (mergedCenterX - transform.x - offsetLeft);
127-
// const diffOffsetTop = diffRatio * (mergedCenterY - transform.y - offsetTop);
128-
// /** Final positioning */
129-
// let newX = transform.x - (diffOffsetLeft - diffImgX);
130-
// let newY = transform.y - (diffOffsetTop - diffImgY);
131-
132-
/**
133-
* When zooming the image
134-
* When the image size is smaller than the width and height of the window, the position is initialized
135-
*/
136-
// if (ratio < 1 && newScale === 1) {
137-
// const mergedWidth = offsetWidth * newScale;
138-
// const mergedHeight = offsetHeight * newScale;
139-
// const { width: clientWidth, height: clientHeight } = getClientSize();
140-
// if (mergedWidth <= clientWidth && mergedHeight <= clientHeight) {
141-
// newX = 0;
142-
// newY = 0;
143-
// }
144-
// }
145-
146-
if (action === 'doubleClick') {
147-
// newX = 0;
148-
// newY = 0;
14999
}
150100

151101
updateTransform(
152102
{
153-
// x: newX,
154-
// y: newY,
155103
scale: newScale,
156104
},
157105
action,

src/image-viewer/useTouchEvent.ts

Lines changed: 7 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -20,26 +20,6 @@ function getDistance(a: Point, b: Point) {
2020
return Math.hypot(x, y);
2121
}
2222

23-
function getCenter(oldPoint1: Point, oldPoint2: Point, newPoint1: Point, newPoint2: Point) {
24-
// Calculate the distance each point has moved
25-
const distance1 = getDistance(oldPoint1, newPoint1);
26-
const distance2 = getDistance(oldPoint2, newPoint2);
27-
28-
// If both distances are 0, return the original points
29-
if (distance1 === 0 && distance2 === 0) {
30-
return [oldPoint1.x, oldPoint1.y];
31-
}
32-
33-
// Calculate the ratio of the distances
34-
const ratio = distance1 / (distance1 + distance2);
35-
36-
// Calculate the new center point based on the ratio
37-
const x = oldPoint1.x + ratio * (oldPoint2.x - oldPoint1.x);
38-
const y = oldPoint1.y + ratio * (oldPoint2.y - oldPoint1.y);
39-
40-
return [x, y];
41-
}
42-
4323
export function useTouchEvent(
4424
imgRef: React.MutableRefObject<HTMLImageElement[]>,
4525
movable: boolean,
@@ -72,15 +52,7 @@ export function useTouchEvent(
7252
isTouching.current = true;
7353

7454
const { touches = [] } = event;
75-
if (touches.length > 1) {
76-
// touch zoom
77-
// updateTouchPointInfo({
78-
// point1: { x: touches[0].clientX, y: touches[0].clientY },
79-
// point2: { x: touches[1].clientX, y: touches[1].clientY },
80-
// eventType: 'touchZoom',
81-
// });
82-
} else {
83-
// touch move
55+
if (touches.length === 1) {
8456
updateTouchPointInfo({
8557
point1: {
8658
x: touches[0].clientX - x,
@@ -107,21 +79,18 @@ export function useTouchEvent(
10779
x: touches[1].clientX,
10880
y: touches[1].clientY,
10981
};
110-
const [centerX, centerY] = getCenter(point1, point2, newPoint1, newPoint2);
11182
const ratio = getDistance(newPoint1, newPoint2) / getDistance(point1, point2);
11283

113-
dispatchZoomChange(ratio, 'touchZoom', centerX, centerY, true);
114-
// updateTouchPointInfo({
115-
// point1: newPoint1,
116-
// point2: newPoint2,
117-
// eventType: 'touchZoom',
118-
// });
84+
dispatchZoomChange(ratio, 'touchZoom', true);
11985
} else if (eventType === 'move') {
86+
const newX = touches[0].clientX - point1.x;
87+
const newY = touches[0].clientY - point1.y;
88+
12089
// touch move
12190
updateTransform(
12291
{
123-
x: touches[0].clientX - point1.x,
124-
y: touches[0].clientY - point1.y,
92+
x: newX,
93+
y: newY,
12594
},
12695
'move',
12796
);

0 commit comments

Comments
 (0)