From 4e991472b0a6fc1e79b6b747746e9d94b102be15 Mon Sep 17 00:00:00 2001 From: linxianxi <904492381@qq.com> Date: Wed, 7 Jun 2023 16:18:47 +0800 Subject: [PATCH 1/4] feat: onTransform support action param --- README.md | 10 ++++++-- src/Preview.tsx | 43 +++++++++++++++++++-------------- src/hooks/useImageTransform.ts | 44 +++++++++++++++++++++++++--------- 3 files changed, 66 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index 85e25c1a..5c46f75d 100644 --- a/README.md +++ b/README.md @@ -79,7 +79,10 @@ export default () => ( visible?: boolean; scaleStep?: number; onVisibleChange?: (visible: boolean, prevVisible: boolean) => void; - onTransform: (transform: { x: number, y: number, rotate: number, scale: number, flipX: boolean, flipY: boolean }) => void } + onTransform: ( + transform: { x: number, y: number, rotate: number, scale: number, flipX: boolean, flipY: boolean }, + action: 'flipY' | 'flipX' | 'rotateLeft' | 'rotateRight' | 'zoomIn' | 'zoomOut' | 'close' | 'switch' | 'wheel' | 'doubleClick' | 'move' | 'dragRebound' + ) => void; getContainer?: string | HTMLElement | (() => HTMLElement) | false; toolbarRender?: (params: { originalNode: React.ReactNode; @@ -135,7 +138,10 @@ export default () => ( visible?: boolean; scaleStep?: number; onVisibleChange?: (visible, prevVisible, current: number) => void; - onTransform: (transform: { x: number, y: number, rotate: number, scale: number, flipX: boolean, flipY: boolean }) => void } + onTransform: ( + transform: { x: number, y: number, rotate: number, scale: number, flipX: boolean, flipY: boolean }, + action: 'flipY' | 'flipX' | 'rotateLeft' | 'rotateRight' | 'zoomIn' | 'zoomOut' | 'close' | 'switch' | 'wheel' | 'doubleClick' | 'move' | 'dragRebound' + ) => void; getContainer?: string | HTMLElement | (() => HTMLElement) | false; countRender?: (current: number, total: number) => string; current?: number; diff --git a/src/Preview.tsx b/src/Preview.tsx index b0de2d48..b12282f9 100644 --- a/src/Preview.tsx +++ b/src/Preview.tsx @@ -111,31 +111,31 @@ const Preview: React.FC = props => { }, [enableTransition]); const onAfterClose = () => { - resetTransform(); + resetTransform('close'); }; const onZoomIn = () => { - dispatchZoomChange(BASE_SCALE_RATIO + scaleStep); + dispatchZoomChange(BASE_SCALE_RATIO + scaleStep, 'zoomIn'); }; const onZoomOut = () => { - dispatchZoomChange(BASE_SCALE_RATIO / (BASE_SCALE_RATIO + scaleStep)); + dispatchZoomChange(BASE_SCALE_RATIO / (BASE_SCALE_RATIO + scaleStep), 'zoomOut'); }; const onRotateRight = () => { - updateTransform({ rotate: rotate + 90 }); + updateTransform({ rotate: rotate + 90 }, 'rotateRight'); }; const onRotateLeft = () => { - updateTransform({ rotate: rotate - 90 }); + updateTransform({ rotate: rotate - 90 }, 'rotateLeft'); }; const onFlipX = () => { - updateTransform({ flipX: !transform.flipX }); + updateTransform({ flipX: !transform.flipX }, 'flipY'); }; const onFlipY = () => { - updateTransform({ flipY: !transform.flipY }); + updateTransform({ flipY: !transform.flipY }, 'flipX'); }; const onSwitchLeft: React.MouseEventHandler = event => { @@ -143,7 +143,7 @@ const Preview: React.FC = props => { event.stopPropagation(); if (currentPreviewIndex > 0) { setEnableTransition(false); - resetTransform(); + resetTransform('switch'); setCurrent(previewDataKeys[currentPreviewIndex - 1]); } }; @@ -153,7 +153,7 @@ const Preview: React.FC = props => { event.stopPropagation(); if (currentPreviewIndex < previewGroupCount - 1) { setEnableTransition(false); - resetTransform(); + resetTransform('switch'); setCurrent(previewDataKeys[currentPreviewIndex + 1]); } }; @@ -161,7 +161,6 @@ const Preview: React.FC = props => { const onMouseUp: React.MouseEventHandler = () => { if (visible && isMoving) { setMoving(false); - /** No need to restore the position when the picture is not moved, So as not to interfere with the click */ const { transformX, transformY } = downPositionRef.current; const hasChangedPosition = transform.x !== transformX && transform.y !== transformY; @@ -183,7 +182,7 @@ const Preview: React.FC = props => { ); if (fixState) { - updateTransform({ ...fixState }); + updateTransform({ ...fixState }, 'dragRebound'); } } }; @@ -204,10 +203,13 @@ const Preview: React.FC = props => { const onMouseMove: React.MouseEventHandler = event => { if (visible && isMoving) { - updateTransform({ - x: event.pageX - downPositionRef.current.deltaX, - y: event.pageY - downPositionRef.current.deltaY, - }); + updateTransform( + { + x: event.pageX - downPositionRef.current.deltaX, + y: event.pageY - downPositionRef.current.deltaY, + }, + 'move', + ); } }; @@ -222,7 +224,7 @@ const Preview: React.FC = props => { if (event.deltaY > 0) { ratio = BASE_SCALE_RATIO / ratio; } - dispatchZoomChange(ratio, event.clientX, event.clientY); + dispatchZoomChange(ratio, 'wheel', event.clientX, event.clientY); }; const onKeyDown = useCallback( @@ -252,9 +254,14 @@ const Preview: React.FC = props => { const onDoubleClick = (event: React.MouseEvent) => { if (visible) { if (scale !== 1) { - updateTransform({ x: 0, y: 0, scale: 1 }); + updateTransform({ x: 0, y: 0, scale: 1 }, 'doubleClick'); } else { - dispatchZoomChange(BASE_SCALE_RATIO + scaleStep, event.clientX, event.clientY); + dispatchZoomChange( + BASE_SCALE_RATIO + scaleStep, + 'doubleClick', + event.clientX, + event.clientY, + ); } } }; diff --git a/src/hooks/useImageTransform.ts b/src/hooks/useImageTransform.ts index 53ad7ae2..43e955d9 100644 --- a/src/hooks/useImageTransform.ts +++ b/src/hooks/useImageTransform.ts @@ -13,6 +13,20 @@ export type TransformType = { flipY: boolean; }; +export type TransformAction = + | 'flipY' + | 'flipX' + | 'rotateLeft' + | 'rotateRight' + | 'zoomIn' + | 'zoomOut' + | 'close' + | 'switch' + | 'wheel' + | 'doubleClick' + | 'move' + | 'dragRebound'; + const initialTransform = { x: 0, y: 0, @@ -24,21 +38,21 @@ const initialTransform = { export default function useImageTransform( imgRef: React.MutableRefObject, - onTransform: (transform: TransformType) => void, + onTransform: (transform: TransformType, action: TransformAction) => void, ) { const frame = useRef(null); const queue = useRef([]); const [transform, setTransform] = useState(initialTransform); - const resetTransform = () => { + const resetTransform = (action: TransformAction) => { setTransform(initialTransform); if (onTransform && !isEqual(initialTransform, transform)) { - onTransform(initialTransform); + onTransform(initialTransform, action); } }; /** Direct update transform */ - const updateTransform = (newTransform: Partial) => { + const updateTransform = (newTransform: Partial, action: TransformAction) => { if (frame.current === null) { queue.current = []; frame.current = raf(() => { @@ -49,7 +63,7 @@ export default function useImageTransform( }); frame.current = null; - onTransform?.(memoState); + onTransform?.(memoState, action); return memoState; }); }); @@ -61,7 +75,12 @@ export default function useImageTransform( }; /** Scale according to the position of clientX and clientY */ - const dispatchZoomChange = (ratio: number, clientX?: number, clientY?: number) => { + const dispatchZoomChange = ( + ratio: number, + action: TransformAction, + clientX?: number, + clientY?: number, + ) => { const { width, height, offsetWidth, offsetHeight, offsetLeft, offsetTop } = imgRef.current; let newRatio = ratio; @@ -103,11 +122,14 @@ export default function useImageTransform( } } - updateTransform({ - x: newX, - y: newY, - scale: newScale, - }); + updateTransform( + { + x: newX, + y: newY, + scale: newScale, + }, + action, + ); }; return { From d827b175d57613cb88d3c82198edf2e31c87edb5 Mon Sep 17 00:00:00 2001 From: linxianxi <904492381@qq.com> Date: Wed, 7 Jun 2023 16:33:09 +0800 Subject: [PATCH 2/4] test: test --- src/Preview.tsx | 4 ++-- tests/preview.test.tsx | 19 +++++++++++-------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/Preview.tsx b/src/Preview.tsx index b12282f9..f074f228 100644 --- a/src/Preview.tsx +++ b/src/Preview.tsx @@ -131,11 +131,11 @@ const Preview: React.FC = props => { }; const onFlipX = () => { - updateTransform({ flipX: !transform.flipX }, 'flipY'); + updateTransform({ flipX: !transform.flipX }, 'flipX'); }; const onFlipY = () => { - updateTransform({ flipY: !transform.flipY }, 'flipX'); + updateTransform({ flipY: !transform.flipY }, 'flipY'); }; const onSwitchLeft: React.MouseEventHandler = event => { diff --git a/tests/preview.test.tsx b/tests/preview.test.tsx index db3a0cf9..a5fb2ab6 100644 --- a/tests/preview.test.tsx +++ b/tests/preview.test.tsx @@ -832,13 +832,16 @@ describe('Preview', () => { }); expect(onTransform).toBeCalledTimes(1); - expect(onTransform).toBeCalledWith({ - flipX: false, - flipY: true, - rotate: 0, - scale: 1, - x: 0, - y: 0, - }); + expect(onTransform).toBeCalledWith( + { + flipY: true, + flipX: false, + rotate: 0, + scale: 1, + x: 0, + y: 0, + }, + 'flipY', + ); }); }); From 9acc3c264f3a06505b99098889aa305a8addf9b8 Mon Sep 17 00:00:00 2001 From: linxianxi <904492381@qq.com> Date: Wed, 7 Jun 2023 16:44:41 +0800 Subject: [PATCH 3/4] fix: type --- src/Preview.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Preview.tsx b/src/Preview.tsx index f074f228..30207abb 100644 --- a/src/Preview.tsx +++ b/src/Preview.tsx @@ -6,7 +6,7 @@ import KeyCode from 'rc-util/lib/KeyCode'; import { warning } from 'rc-util/lib/warning'; import React, { useCallback, useContext, useEffect, useRef, useState } from 'react'; import getFixScaleEleTransPosition from './getFixScaleEleTransPosition'; -import type { TransformType } from './hooks/useImageTransform'; +import type { TransformAction, TransformType } from './hooks/useImageTransform'; import useImageTransform from './hooks/useImageTransform'; import Operations from './Operations'; import { BASE_SCALE_RATIO, WHEEL_MAX_SCALE_RATIO } from './previewConfig'; @@ -55,7 +55,7 @@ export interface PreviewProps extends Omit { countRender?: (current: number, total: number) => string; scaleStep?: number; onClose?: (e: React.SyntheticEvent) => void; - onTransform?: (transform: TransformType) => void; + onTransform?: (transform: TransformType, action: TransformAction) => void; toolbarRender?: (params: toolbarRenderType) => React.ReactNode; } From 25d9c0444272341fcd47083859f1121f852e03ef Mon Sep 17 00:00:00 2001 From: linxianxi <904492381@qq.com> Date: Wed, 7 Jun 2023 17:12:04 +0800 Subject: [PATCH 4/4] fix: change onTransform type --- README.md | 8 ++++---- src/Preview.tsx | 2 +- src/hooks/useImageTransform.ts | 6 +++--- tests/preview.test.tsx | 8 ++++---- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 5c46f75d..c4cf8d74 100644 --- a/README.md +++ b/README.md @@ -79,10 +79,10 @@ export default () => ( visible?: boolean; scaleStep?: number; onVisibleChange?: (visible: boolean, prevVisible: boolean) => void; - onTransform: ( + onTransform: (params: { transform: { x: number, y: number, rotate: number, scale: number, flipX: boolean, flipY: boolean }, action: 'flipY' | 'flipX' | 'rotateLeft' | 'rotateRight' | 'zoomIn' | 'zoomOut' | 'close' | 'switch' | 'wheel' | 'doubleClick' | 'move' | 'dragRebound' - ) => void; + )} => void; getContainer?: string | HTMLElement | (() => HTMLElement) | false; toolbarRender?: (params: { originalNode: React.ReactNode; @@ -138,10 +138,10 @@ export default () => ( visible?: boolean; scaleStep?: number; onVisibleChange?: (visible, prevVisible, current: number) => void; - onTransform: ( + onTransform: (params: { transform: { x: number, y: number, rotate: number, scale: number, flipX: boolean, flipY: boolean }, action: 'flipY' | 'flipX' | 'rotateLeft' | 'rotateRight' | 'zoomIn' | 'zoomOut' | 'close' | 'switch' | 'wheel' | 'doubleClick' | 'move' | 'dragRebound' - ) => void; + )} => void; getContainer?: string | HTMLElement | (() => HTMLElement) | false; countRender?: (current: number, total: number) => string; current?: number; diff --git a/src/Preview.tsx b/src/Preview.tsx index 30207abb..ffc1089c 100644 --- a/src/Preview.tsx +++ b/src/Preview.tsx @@ -55,7 +55,7 @@ export interface PreviewProps extends Omit { countRender?: (current: number, total: number) => string; scaleStep?: number; onClose?: (e: React.SyntheticEvent) => void; - onTransform?: (transform: TransformType, action: TransformAction) => void; + onTransform?: (params: { transform: TransformType; action: TransformAction }) => void; toolbarRender?: (params: toolbarRenderType) => React.ReactNode; } diff --git a/src/hooks/useImageTransform.ts b/src/hooks/useImageTransform.ts index 43e955d9..abe07842 100644 --- a/src/hooks/useImageTransform.ts +++ b/src/hooks/useImageTransform.ts @@ -38,7 +38,7 @@ const initialTransform = { export default function useImageTransform( imgRef: React.MutableRefObject, - onTransform: (transform: TransformType, action: TransformAction) => void, + onTransform: (params: { transform: TransformType; action: TransformAction }) => void, ) { const frame = useRef(null); const queue = useRef([]); @@ -47,7 +47,7 @@ export default function useImageTransform( const resetTransform = (action: TransformAction) => { setTransform(initialTransform); if (onTransform && !isEqual(initialTransform, transform)) { - onTransform(initialTransform, action); + onTransform({ transform: initialTransform, action }); } }; @@ -63,7 +63,7 @@ export default function useImageTransform( }); frame.current = null; - onTransform?.(memoState, action); + onTransform?.({ transform: memoState, action }); return memoState; }); }); diff --git a/tests/preview.test.tsx b/tests/preview.test.tsx index a5fb2ab6..77747fc2 100644 --- a/tests/preview.test.tsx +++ b/tests/preview.test.tsx @@ -832,8 +832,8 @@ describe('Preview', () => { }); expect(onTransform).toBeCalledTimes(1); - expect(onTransform).toBeCalledWith( - { + expect(onTransform).toBeCalledWith({ + transform: { flipY: true, flipX: false, rotate: 0, @@ -841,7 +841,7 @@ describe('Preview', () => { x: 0, y: 0, }, - 'flipY', - ); + action: 'flipY', + }); }); });