UNPKG

react-moveable

Version:

A React Component that create Moveable, Draggable, Resizable, Scalable, Rotatable, Warpable, Pinchable, Groupable.

139 lines (125 loc) 5.2 kB
import { plus, getOrigin, multiply, minus } from "@scena/matrix"; import { getCachedClientRect, getCachedStyle } from "../store/Store"; import { MoveableClientRect, Writable } from "../types"; import { calculateInversePosition, getClientRect, getClientRectByPosition, getOffsetInfo, resetClientRect, getTransformOriginArray, } from "../utils"; import { calculateElementInfo, MoveableElementInfo } from "./getElementInfo"; import { calculateElementPosition } from "./calculateElementPosition"; export interface MoveableTargetInfo extends MoveableElementInfo { targetClientRect: MoveableClientRect; containerClientRect: MoveableClientRect; moveableClientRect: MoveableClientRect; rootContainerClientRect: MoveableClientRect; beforeDirection: 1 | -1; beforeOrigin: number[]; offsetDelta: number[], originalBeforeOrigin: number[]; target: HTMLElement | SVGElement | null | undefined; style: Partial<Writable<CSSStyleDeclaration>>; } export function getMoveableTargetInfo( moveableElement?: HTMLElement | null, target?: HTMLElement | SVGElement | null, container?: HTMLElement | SVGElement | null, parentContainer?: HTMLElement | SVGElement | null, rootContainer?: HTMLElement | SVGElement | null, requestStyles: Array<keyof CSSStyleDeclaration> = [], ): MoveableTargetInfo { let beforeDirection: 1 | -1 = 1; let beforeOrigin = [0, 0]; let targetClientRect = resetClientRect(); let moveableClientRect = resetClientRect(); let containerClientRect = resetClientRect(); let rootContainerClientRect = resetClientRect(); let offsetDelta = [0, 0]; const style: Partial<Writable<CSSStyleDeclaration>> = {}; const result = calculateElementInfo( target, container!, rootContainer!, true, ); if (target) { const getStyle = getCachedStyle(target); requestStyles.forEach(name => { (style as any)[name] = getStyle(name as any); }); const n = result.is3d ? 4 : 3; const beforePosition = calculateElementPosition( result.offsetMatrix, plus(result.transformOrigin, getOrigin(result.targetMatrix, n)), result.width, result.height, ); beforeDirection = beforePosition.direction; beforeOrigin = plus( beforePosition.origin, [beforePosition.left - result.left, beforePosition.top - result.top], ); rootContainerClientRect = getClientRect(result.offsetRootContainer!); const offsetContainer = getOffsetInfo(parentContainer, parentContainer, true).offsetParent || result.offsetRootContainer!; if (result.hasZoom) { const absoluteTargetPosition = calculateElementPosition( multiply(result.originalRootMatrix, result.allMatrix), result.transformOrigin, result.width, result.height, ); const absoluteContainerPosition = calculateElementPosition( result.originalRootMatrix, getTransformOriginArray(getCachedStyle(offsetContainer)("transformOrigin")).map(pos => parseFloat(pos)), offsetContainer.offsetWidth, offsetContainer.offsetHeight, ); targetClientRect = getClientRectByPosition(absoluteTargetPosition, rootContainerClientRect); containerClientRect = getClientRectByPosition( absoluteContainerPosition, rootContainerClientRect, offsetContainer, true, ); if (moveableElement) { const left = absoluteTargetPosition.left; const top = absoluteTargetPosition.top; moveableClientRect = getClientRectByPosition({ left, top, bottom: top, right: top, }, rootContainerClientRect); } } else { targetClientRect = getClientRect(target); containerClientRect = getCachedClientRect(offsetContainer); if (moveableElement) { moveableClientRect = getClientRect(moveableElement); } const { left: containerClientRectLeft, top: containerClientRectTop, clientLeft: containterClientLeft, clientTop: containerClientTop, } = containerClientRect; const clientDelta = [ targetClientRect.left - containerClientRectLeft, targetClientRect.top - containerClientRectTop, ]; offsetDelta = minus( calculateInversePosition(result.rootMatrix, clientDelta, 4), [containterClientLeft! + result.left, containerClientTop! + result.top], ); } } return { targetClientRect, containerClientRect, moveableClientRect, rootContainerClientRect, beforeDirection, beforeOrigin, originalBeforeOrigin: beforeOrigin, target, style, offsetDelta, ...result, }; }