Untitled
unknown
plain_text
2 years ago
3.7 kB
8
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