@@ -3,15 +3,15 @@ import type { DialogProps as IDialogPropTypes } from 'rc-dialog';
33import Dialog from 'rc-dialog' ;
44import addEventListener from 'rc-util/lib/Dom/addEventListener' ;
55import KeyCode from 'rc-util/lib/KeyCode' ;
6- import { warning } from 'rc-util/lib/warning' ;
76import React , { useContext , useEffect , useRef , useState } from 'react' ;
87import { PreviewGroupContext } from './context' ;
9- import getFixScaleEleTransPosition from './getFixScaleEleTransPosition' ;
108import type { TransformAction , TransformType } from './hooks/useImageTransform' ;
119import useImageTransform from './hooks/useImageTransform' ;
10+ import useMouseEvent from './hooks/useMouseEvent' ;
11+ import useTouchEvent from './hooks/useTouchEvent' ;
1212import useStatus from './hooks/useStatus' ;
1313import Operations from './Operations' ;
14- import { BASE_SCALE_RATIO , WHEEL_MAX_SCALE_RATIO } from './previewConfig' ;
14+ import { BASE_SCALE_RATIO } from './previewConfig' ;
1515
1616export type ToolbarRenderInfoType = {
1717 icons : {
@@ -126,24 +126,35 @@ const Preview: React.FC<PreviewProps> = props => {
126126 } = props ;
127127
128128 const imgRef = useRef < HTMLImageElement > ( ) ;
129- const downPositionRef = useRef ( {
130- deltaX : 0 ,
131- deltaY : 0 ,
132- transformX : 0 ,
133- transformY : 0 ,
134- } ) ;
135- const [ isMoving , setMoving ] = useState ( false ) ;
136129 const groupContext = useContext ( PreviewGroupContext ) ;
137130 const showLeftOrRightSwitches = groupContext && count > 1 ;
138131 const showOperationsProgress = groupContext && count >= 1 ;
132+ const [ enableTransition , setEnableTransition ] = useState ( true ) ;
139133 const { transform, resetTransform, updateTransform, dispatchZoomChange } = useImageTransform (
140134 imgRef ,
141135 minScale ,
142136 maxScale ,
143137 onTransform ,
144138 ) ;
145- const [ enableTransition , setEnableTransition ] = useState ( true ) ;
146- const { rotate, scale, x, y } = transform ;
139+ const { isMoving, onMouseDown, onWheel } = useMouseEvent (
140+ imgRef ,
141+ movable ,
142+ visible ,
143+ scaleStep ,
144+ transform ,
145+ updateTransform ,
146+ dispatchZoomChange ,
147+ ) ;
148+ const { isTouching, onTouchStart, onTouchMove, onTouchEnd } = useTouchEvent (
149+ imgRef ,
150+ movable ,
151+ visible ,
152+ minScale ,
153+ transform ,
154+ updateTransform ,
155+ dispatchZoomChange ,
156+ ) ;
157+ const { rotate, scale } = transform ;
147158
148159 const wrapClassName = classnames ( {
149160 [ `${ prefixCls } -moving` ] : isMoving ,
@@ -203,75 +214,6 @@ const Preview: React.FC<PreviewProps> = props => {
203214 }
204215 } ;
205216
206- const onMouseUp : React . MouseEventHandler < HTMLBodyElement > = ( ) => {
207- if ( visible && isMoving ) {
208- setMoving ( false ) ;
209- /** No need to restore the position when the picture is not moved, So as not to interfere with the click */
210- const { transformX, transformY } = downPositionRef . current ;
211- const hasChangedPosition = x !== transformX && y !== transformY ;
212- if ( ! hasChangedPosition ) {
213- return ;
214- }
215-
216- const width = imgRef . current . offsetWidth * scale ;
217- const height = imgRef . current . offsetHeight * scale ;
218- // eslint-disable-next-line @typescript-eslint/no-shadow
219- const { left, top } = imgRef . current . getBoundingClientRect ( ) ;
220- const isRotate = rotate % 180 !== 0 ;
221-
222- const fixState = getFixScaleEleTransPosition (
223- isRotate ? height : width ,
224- isRotate ? width : height ,
225- left ,
226- top ,
227- ) ;
228-
229- if ( fixState ) {
230- updateTransform ( { ...fixState } , 'dragRebound' ) ;
231- }
232- }
233- } ;
234-
235- const onMouseDown : React . MouseEventHandler < HTMLDivElement > = event => {
236- // Only allow main button
237- if ( ! movable || event . button !== 0 ) return ;
238- event . preventDefault ( ) ;
239- event . stopPropagation ( ) ;
240- downPositionRef . current = {
241- deltaX : event . pageX - transform . x ,
242- deltaY : event . pageY - transform . y ,
243- transformX : transform . x ,
244- transformY : transform . y ,
245- } ;
246- setMoving ( true ) ;
247- } ;
248-
249- const onMouseMove : React . MouseEventHandler < HTMLBodyElement > = event => {
250- if ( visible && isMoving ) {
251- updateTransform (
252- {
253- x : event . pageX - downPositionRef . current . deltaX ,
254- y : event . pageY - downPositionRef . current . deltaY ,
255- } ,
256- 'move' ,
257- ) ;
258- }
259- } ;
260-
261- const onWheel = ( event : React . WheelEvent < HTMLImageElement > ) => {
262- if ( ! visible || event . deltaY == 0 ) return ;
263- // Scale ratio depends on the deltaY size
264- const scaleRatio = Math . abs ( event . deltaY / 100 ) ;
265- // Limit the maximum scale ratio
266- const mergedScaleRatio = Math . min ( scaleRatio , WHEEL_MAX_SCALE_RATIO ) ;
267- // Scale the ratio each time
268- let ratio = BASE_SCALE_RATIO + mergedScaleRatio * scaleStep ;
269- if ( event . deltaY > 0 ) {
270- ratio = BASE_SCALE_RATIO / ratio ;
271- }
272- dispatchZoomChange ( ratio , 'wheel' , event . clientX , event . clientY ) ;
273- } ;
274-
275217 const onKeyDown = ( event : KeyboardEvent ) => {
276218 if ( ! visible || ! showLeftOrRightSwitches ) return ;
277219
@@ -297,39 +239,6 @@ const Preview: React.FC<PreviewProps> = props => {
297239 }
298240 } ;
299241
300- useEffect ( ( ) => {
301- let onTopMouseUpListener ;
302- let onTopMouseMoveListener ;
303- let onMouseUpListener ;
304- let onMouseMoveListener ;
305-
306- if ( movable ) {
307- onMouseUpListener = addEventListener ( window , 'mouseup' , onMouseUp , false ) ;
308- onMouseMoveListener = addEventListener ( window , 'mousemove' , onMouseMove , false ) ;
309-
310- try {
311- // Resolve if in iframe lost event
312- /* istanbul ignore next */
313- if ( window . top !== window . self ) {
314- onTopMouseUpListener = addEventListener ( window . top , 'mouseup' , onMouseUp , false ) ;
315- onTopMouseMoveListener = addEventListener ( window . top , 'mousemove' , onMouseMove , false ) ;
316- }
317- } catch ( error ) {
318- /* istanbul ignore next */
319- warning ( false , `[rc-image] ${ error } ` ) ;
320- }
321- }
322-
323- return ( ) => {
324- onMouseUpListener ?. remove ( ) ;
325- onMouseMoveListener ?. remove ( ) ;
326- /* istanbul ignore next */
327- onTopMouseUpListener ?. remove ( ) ;
328- /* istanbul ignore next */
329- onTopMouseMoveListener ?. remove ( ) ;
330- } ;
331- } , [ visible , isMoving , x , y , rotate , movable ] ) ;
332-
333242 useEffect ( ( ) => {
334243 const onKeyDownListener = addEventListener ( window , 'keydown' , onKeyDown , false ) ;
335244
@@ -350,13 +259,17 @@ const Preview: React.FC<PreviewProps> = props => {
350259 transform : `translate3d(${ transform . x } px, ${ transform . y } px, 0) scale3d(${
351260 transform . flipX ? '-' : ''
352261 } ${ scale } , ${ transform . flipY ? '-' : '' } ${ scale } , 1) rotate(${ rotate } deg)`,
353- transitionDuration : ! enableTransition && '0s' ,
262+ transitionDuration : ( ! enableTransition || isTouching ) && '0s' ,
354263 } }
355264 fallback = { fallback }
356265 src = { src }
357266 onWheel = { onWheel }
358267 onMouseDown = { onMouseDown }
359268 onDoubleClick = { onDoubleClick }
269+ onTouchStart = { onTouchStart }
270+ onTouchMove = { onTouchMove }
271+ onTouchEnd = { onTouchEnd }
272+ onTouchCancel = { onTouchEnd }
360273 />
361274 ) ;
362275
0 commit comments