@@ -159,6 +159,7 @@ export const ZoomableImage = forwardRef<ZoomableImageRef, ZoomableImageProps>(
159159 const imageRef = useRef < HTMLImageElement > ( null ) ;
160160 const isFitInitializedRef = useRef ( false ) ;
161161 const hasUserInteractedRef = useRef ( false ) ;
162+ const hasPendingFitRef = useRef ( true ) ;
162163 const fitTransformRef = useRef < FitTransform | null > ( null ) ;
163164 const fitFrameRef = useRef < number | null > ( null ) ;
164165 const [ isOverflowing , setIsOverflowing ] = useState ( false ) ;
@@ -246,6 +247,13 @@ export const ZoomableImage = forwardRef<ZoomableImageRef, ZoomableImageProps>(
246247 fitFrameRef . current = null ;
247248 } , [ ] ) ;
248249
250+ const markFitPending = useCallback ( ( ) => {
251+ isFitInitializedRef . current = false ;
252+ hasUserInteractedRef . current = false ;
253+ hasPendingFitRef . current = true ;
254+ fitTransformRef . current = null ;
255+ } , [ ] ) ;
256+
249257 const applyFitTransform = useCallback (
250258 ( duration = 200 , animationType : AnimationType = 'easeOut' ) => {
251259 const viewportElement = getViewportElement ( ) ;
@@ -268,6 +276,7 @@ export const ZoomableImage = forwardRef<ZoomableImageRef, ZoomableImageProps>(
268276 fitTransformRef . current = fitTransform ;
269277 isFitInitializedRef . current = true ;
270278 hasUserInteractedRef . current = false ;
279+ hasPendingFitRef . current = false ;
271280 setMinimumScale ( fitTransform . scale ) ;
272281 transformRef . current . setTransform (
273282 fitTransform . positionX ,
@@ -301,11 +310,10 @@ export const ZoomableImage = forwardRef<ZoomableImageRef, ZoomableImageProps>(
301310
302311 const handleReset = useCallback (
303312 ( duration = 200 , animationType : AnimationType = 'easeOut' ) => {
304- isFitInitializedRef . current = false ;
305- hasUserInteractedRef . current = false ;
313+ markFitPending ( ) ;
306314 scheduleFitTransform ( duration , animationType ) ;
307315 } ,
308- [ scheduleFitTransform ] ,
316+ [ markFitPending , scheduleFitTransform ] ,
309317 ) ;
310318
311319 useImperativeHandle ( ref , ( ) => ( {
@@ -326,10 +334,9 @@ export const ZoomableImage = forwardRef<ZoomableImageRef, ZoomableImageProps>(
326334
327335 useEffect ( ( ) => {
328336 rotationRef . current = rotation ;
329- isFitInitializedRef . current = false ;
330- hasUserInteractedRef . current = false ;
337+ markFitPending ( ) ;
331338 scheduleFitTransform ( 0 ) ;
332- } , [ rotation , scheduleFitTransform ] ) ;
339+ } , [ rotation , markFitPending , scheduleFitTransform ] ) ;
333340
334341 useEffect ( ( ) => {
335342 const viewportElement = getViewportElement ( ) ;
@@ -358,24 +365,20 @@ export const ZoomableImage = forwardRef<ZoomableImageRef, ZoomableImageProps>(
358365
359366 useEffect ( ( ) => {
360367 setIsOverflowing ( false ) ;
361- isFitInitializedRef . current = false ;
362- hasUserInteractedRef . current = false ;
363- fitTransformRef . current = null ;
368+ markFitPending ( ) ;
364369
365370 const img = imageRef . current ;
366371 if ( ! img ) return ;
367372
368- const handleImageLoad = ( ) => {
369- scheduleFitTransform ( 0 ) ;
370- } ;
371-
372373 if ( img . complete && img . naturalWidth > 0 ) {
373- handleImageLoad ( ) ;
374- } else {
375- img . addEventListener ( 'load' , handleImageLoad ) ;
376- return ( ) => img . removeEventListener ( 'load' , handleImageLoad ) ;
374+ scheduleFitTransform ( 0 ) ;
377375 }
378- } , [ imagePath , scheduleFitTransform ] ) ;
376+ } , [ imagePath , markFitPending , scheduleFitTransform ] ) ;
377+
378+ const handleImageLoad = useCallback ( ( ) => {
379+ markFitPending ( ) ;
380+ scheduleFitTransform ( 0 ) ;
381+ } , [ markFitPending , scheduleFitTransform ] ) ;
379382
380383 useEffect ( ( ) => {
381384 const wheelElement = wheelAreaRef . current ;
@@ -458,11 +461,7 @@ export const ZoomableImage = forwardRef<ZoomableImageRef, ZoomableImageProps>(
458461 fitTransformRef . current = fitTransform ;
459462
460463 const shouldUseFitTransform =
461- ! isFitInitializedRef . current &&
462- fitTransform . scale < MIN_SCALE - SCALE_EPSILON &&
463- transformState . scale > fitTransform . scale + SCALE_EPSILON &&
464- Math . abs ( transformState . positionX ) < SCALE_EPSILON &&
465- Math . abs ( transformState . positionY ) < SCALE_EPSILON ;
464+ hasPendingFitRef . current || ! isFitInitializedRef . current ;
466465 const currentScale = shouldUseFitTransform
467466 ? fitTransform . scale
468467 : transformState . scale ;
@@ -560,6 +559,7 @@ export const ZoomableImage = forwardRef<ZoomableImageRef, ZoomableImageProps>(
560559
561560 setIsOverflowing ( newOverflow . width || newOverflow . height ) ;
562561 isFitInitializedRef . current = true ;
562+ hasPendingFitRef . current = false ;
563563 hasUserInteractedRef . current = true ;
564564 transformRef . current . setTransform ( targetX , targetY , newScale , 0 ) ;
565565 } ;
@@ -587,6 +587,7 @@ export const ZoomableImage = forwardRef<ZoomableImageRef, ZoomableImageProps>(
587587 return (
588588 < div ref = { wheelAreaRef } className = "h-full w-full" >
589589 < TransformWrapper
590+ key = { imagePath }
590591 ref = { transformRef }
591592 initialScale = { minScale }
592593 minScale = { minScale }
@@ -673,11 +674,13 @@ export const ZoomableImage = forwardRef<ZoomableImageRef, ZoomableImageProps>(
673674 } }
674675 >
675676 < img
677+ key = { imagePath }
676678 ref = { imageRef }
677679 src = { convertFileSrc ( imagePath ) || '/placeholder.svg' }
678680 alt = { alt }
679681 draggable = { false }
680682 className = "select-none"
683+ onLoad = { handleImageLoad }
681684 onError = { ( e ) => {
682685 const img = e . target as HTMLImageElement ;
683686 img . onerror = null ;
0 commit comments