1
0
Fork 0

fix pan-zoom infinite loop

This commit is contained in:
Enoch Riese 2023-06-22 14:57:47 -05:00
parent 535d6b7426
commit aaa19f213c
2 changed files with 33 additions and 44 deletions

View file

@ -3,10 +3,7 @@ import { forwardRef, useContext } from 'react'
// Hooks // Hooks
import { useTranslation } from 'next-i18next' import { useTranslation } from 'next-i18next'
// Context // Context
import { import { PanZoomContext } from 'shared/components/workbench/pattern/pan-zoom-context.mjs'
PanZoomContext,
PanZoomCapture,
} from 'shared/components/workbench/pattern/pan-zoom-context.mjs'
// Components // Components
import { SizeMe } from 'react-sizeme' import { SizeMe } from 'react-sizeme'
import { TransformWrapper, TransformComponent } from 'react-zoom-pan-pinch' import { TransformWrapper, TransformComponent } from 'react-zoom-pan-pinch'
@ -40,8 +37,6 @@ export const PanZoomPattern = forwardRef((props, ref) => {
const { renderProps = false, components = {} } = props const { renderProps = false, components = {} } = props
const { onTransformed, setZoomFunctions } = useContext(PanZoomContext) const { onTransformed, setZoomFunctions } = useContext(PanZoomContext)
if (!renderProps) return null
return ( return (
<SizeMe refreshRate={64}> <SizeMe refreshRate={64}>
{({ size }) => ( {({ size }) => (
@ -51,17 +46,13 @@ export const PanZoomPattern = forwardRef((props, ref) => {
wheel={{ activationKeys: ['Control'] }} wheel={{ activationKeys: ['Control'] }}
doubleClick={{ mode: 'reset' }} doubleClick={{ mode: 'reset' }}
onTransformed={onTransformed} onTransformed={onTransformed}
onInit={setZoomFunctions}
> >
{({ resetTransform, zoomIn, zoomOut }) => ( <TransformComponent>
<> <div style={{ width: size.width + 'px' }} className="max-h-screen">
<PanZoomCapture {...{ setZoomFunctions, resetTransform, zoomIn, zoomOut }} /> <Pattern {...{ t, components, renderProps }} ref={ref} />
<TransformComponent> </div>
<div style={{ width: size.width + 'px' }} className="max-h-screen"> </TransformComponent>
<Pattern {...{ t, components, renderProps }} ref={ref} />
</div>
</TransformComponent>
</>
)}
</TransformWrapper> </TransformWrapper>
)} )}
</SizeMe> </SizeMe>

View file

@ -1,4 +1,4 @@
import React, { useState, useMemo, useEffect } from 'react' import React, { useState, useMemo, useCallback } from 'react'
/** /**
* A context for managing zoom state of a {@see PanZoomPattern} * A context for managing zoom state of a {@see PanZoomPattern}
@ -9,40 +9,38 @@ export const PanZoomContext = React.createContext({})
/** Provider for the {@see PanZoomContext} */ /** Provider for the {@see PanZoomContext} */
export const PanZoomContextProvider = ({ children }) => { export const PanZoomContextProvider = ({ children }) => {
const [zoomed, setZoomed] = useState(false) const [zoomed, setZoomed] = useState(false)
const [_zoomFunctions, setZoomFunctions] = useState(false) const [zoomFunctions, _setZoomFunctions] = useState(false)
const setZoomFunctions = useCallback(
(zoomInstance) => {
const reset = () => {
setZoomed(false)
zoomInstance.resetTransform()
}
if (zoomInstance) {
const { zoomIn, zoomOut, resetTransform } = zoomInstance
_setZoomFunctions({ zoomIn, zoomOut, resetTransform, reset })
}
},
[_setZoomFunctions, setZoomed]
)
const onTransformed = useCallback(
(_ref, state) => {
setZoomed(state.scale !== 1)
},
[setZoomed]
)
const value = useMemo(() => { const value = useMemo(() => {
const onTransformed = (_ref, state) => {
setZoomed(state.scale !== 1)
}
const reset = () => {
setZoomed(false)
_zoomFunctions.resetTransform()
}
return { return {
zoomed, zoomed,
zoomFunctions: _zoomFunctions ? { ..._zoomFunctions, reset } : false, zoomFunctions,
setZoomFunctions, setZoomFunctions,
onTransformed, onTransformed,
} }
}, [zoomed, setZoomed, _zoomFunctions, setZoomFunctions]) }, [zoomed, zoomFunctions, setZoomFunctions, onTransformed])
return <PanZoomContext.Provider value={value}>{children}</PanZoomContext.Provider> return <PanZoomContext.Provider value={value}>{children}</PanZoomContext.Provider>
} }
/**
* A component to capture the zoom functions and set them on the zoom context
* Place this inside of a TransformWrapper child function.
* See {@see PanZoomPattern} for an example
* */
export const PanZoomCapture = ({ resetTransform, zoomIn, zoomOut, setZoomFunctions }) => {
useEffect(() => {
if (typeof setZoomFunctions === 'function') {
setZoomFunctions({ resetTransform, zoomIn, zoomOut })
}
})
return <></>
}