Untitled
unknown
plain_text
a year ago
3.7 kB
5
Indexable
const hasPositionChanged = ({ pos, prevPos }) => pos !== prevPos const valueInRange = ({ minScale, maxScale, scale }) => scale <= maxScale && scale >= minScale // Function to calculate a new translate value based on the current and previous positions and the scale const getTranslate = ({ minScale, maxScale, scale }) => ({ pos, prevPos, translate }) => valueInRange({ minScale, maxScale, scale }) && hasPositionChanged({ pos, prevPos }) ? translate + (pos - prevPos * scale) * (1 - 1 / scale) : translate // Function to construct a CSS transform matrix string const getMatrix = ({ scale, translateX, translateY }: Transform) => `matrix(${scale}, 0, 0, ${scale}, ${translateX}, ${translateY})` // Function to calculate a new scale value const getScale = ({ scale, minScale, maxScale, scaleSensitivity, deltaScale }) => { let newScale = scale + deltaScale / (scaleSensitivity / scale) newScale = Math.max(minScale, Math.min(newScale, maxScale)) return [scale, newScale] } // Function to update the transformation's translation values and apply the new transformation to the element const pan = ({ state, originX, originY }) => { state.transformation.translateX += originX state.transformation.translateY += originY state.element.style.transform = getMatrix({ scale: state.transformation.scale, translateX: state.transformation.translateX, translateY: state.transformation.translateY }) } // Function to return an object with methods for panning the element const canPan = (state) => ({ panBy: ({ originX, originY }) => pan({ state, originX, originY }), panTo: ({ originX, originY, scale }) => { state.transformation.scale = scale pan({ state, originX: originX - state.transformation.translateX, originY: originY - state.transformation.translateY }) } }) // Function to return an object with a method for zooming the element const canZoom = (state) => ({ zoom: ({ x, y, deltaScale }) => { // Calculate new scale and translation values based on the mouse position and delta scale // Update the element's transform origin and style with the new values // Update the state with the new transformation values const { left, top } = state.element.getBoundingClientRect() const { minScale, maxScale, scaleSensitivity } = state const [scale, newScale] = getScale({ scale: state.transformation.scale, deltaScale, minScale, maxScale, scaleSensitivity }) const originX = x - left const originY = y - top const newOriginX = originX / scale const newOriginY = originY / scale const translate = getTranslate({ scale, minScale, maxScale }) const translateX = translate({ pos: originX, prevPos: state.transformation.originX, translate: state.transformation.translateX }) const translateY = translate({ pos: originY, prevPos: state.transformation.originY, translate: state.transformation.translateY }) state.element.style.transformOrigin = `${newOriginX}px ${newOriginY}px` state.element.style.transform = getMatrix({ scale: newScale, translateX, translateY }) state.transformation = { originX: newOriginX, originY: newOriginY, translateX, translateY, scale: newScale } } }) // Function to initialize the state and return an object combining panning and zooming capabilities export const renderer = ({ minScale, maxScale, element, scaleSensitivity = 10 }) => { const state: State = { element, minScale, maxScale, scaleSensitivity, transformation: { originX: 0, originY: 0, translateX: 0, translateY: 0, scale: 1 } } return Object.assign(canZoom(state), canPan(state)) }
Editor is loading...
Leave a Comment