UNPKG

@leafer/helper

Version:
216 lines (177 loc) 8.66 kB
import { IAlign, ILeaf, IMatrixData, IPointData, IAxis, ITransition } from '@leafer/interface' import { MathHelper, MatrixHelper, PointHelper, AroundHelper, getMatrixData, BoundsHelper } from '@leafer/math' const { copy, toInnerPoint, toOuterPoint, scaleOfOuter, rotateOfOuter, skewOfOuter, multiplyParent, divideParent, getLayout } = MatrixHelper const matrix = {} as IMatrixData, { round } = Math export const LeafHelper = { updateAllMatrix(leaf: ILeaf, checkAutoLayout?: boolean, waitAutoLayout?: boolean): void { if (checkAutoLayout && leaf.__hasAutoLayout && leaf.__layout.matrixChanged) waitAutoLayout = true updateMatrix(leaf, checkAutoLayout, waitAutoLayout) if (leaf.isBranch) { const { children } = leaf for (let i = 0, len = children.length; i < len; i++) { updateAllMatrix(children[i], checkAutoLayout, waitAutoLayout) } } }, updateMatrix(leaf: ILeaf, checkAutoLayout?: boolean, waitAutoLayout?: boolean): void { const layout = leaf.__layout if (checkAutoLayout) { if (waitAutoLayout) { layout.waitAutoLayout = true if (leaf.__hasAutoLayout) layout.matrixChanged = false // wait updateAutoLayout } } else if (layout.waitAutoLayout) { layout.waitAutoLayout = false } if (layout.matrixChanged) leaf.__updateLocalMatrix() if (!layout.waitAutoLayout) leaf.__updateWorldMatrix() }, updateBounds(leaf: ILeaf): void { const layout = leaf.__layout if (layout.boundsChanged) leaf.__updateLocalBounds() if (!layout.waitAutoLayout) leaf.__updateWorldBounds() }, updateAllWorldOpacity(leaf: ILeaf): void { leaf.__updateWorldOpacity() if (leaf.isBranch) { const { children } = leaf for (let i = 0, len = children.length; i < len; i++) { updateAllWorldOpacity(children[i]) } } }, updateChange(leaf: ILeaf): void { const layout = leaf.__layout if (layout.stateStyleChanged) leaf.updateState() if (layout.opacityChanged) updateAllWorldOpacity(leaf) leaf.__updateChange() }, updateAllChange(leaf: ILeaf): void { updateChange(leaf) if (leaf.isBranch) { const { children } = leaf for (let i = 0, len = children.length; i < len; i++) { updateAllChange(children[i]) } } }, worldHittable(t: ILeaf): boolean { while (t) { if (!t.__.hittable) return false t = t.parent } return true }, // transform moveWorld(t: ILeaf, x: number | IPointData, y = 0, isInnerPoint?: boolean, transition?: ITransition): void { const local = typeof x === 'object' ? { ...x } : { x, y } isInnerPoint ? toOuterPoint(t.localTransform, local, local, true) : (t.parent && toInnerPoint(t.parent.worldTransform, local, local, true)) L.moveLocal(t, local.x, local.y, transition) }, moveLocal(t: ILeaf, x: number | IPointData, y = 0, transition?: ITransition): void { if (typeof x === 'object') y = x.y, x = x.x x += t.x y += t.y if (t.leafer && t.leafer.config.pointSnap) x = round(x), y = round(y) transition ? t.animate({ x, y }, transition) : (t.x = x, t.y = y) }, zoomOfWorld(t: ILeaf, origin: IPointData, scaleX: number, scaleY?: number | ITransition, resize?: boolean, transition?: ITransition): void { L.zoomOfLocal(t, getTempLocal(t, origin), scaleX, scaleY, resize, transition) }, zoomOfLocal(t: ILeaf, origin: IPointData, scaleX: number, scaleY: number | ITransition = scaleX, resize?: boolean, transition?: ITransition): void { const o = t.__localMatrix if (typeof scaleY !== 'number') { if (scaleY) transition = scaleY scaleY = scaleX } copy(matrix, o) scaleOfOuter(matrix, origin, scaleX, scaleY) if (t.origin || t.around) { L.setTransform(t, matrix, resize, transition) } else { const x = t.x + matrix.e - o.e, y = t.y + matrix.f - o.f if (transition && !resize) t.animate({ x, y, scaleX: t.scaleX * scaleX, scaleY: t.scaleY * scaleY }, transition) else t.x = x, t.y = y, t.scaleResize(scaleX, scaleY, resize !== true) } }, rotateOfWorld(t: ILeaf, origin: IPointData, angle: number, transition?: ITransition): void { L.rotateOfLocal(t, getTempLocal(t, origin), angle, transition) }, rotateOfLocal(t: ILeaf, origin: IPointData, angle: number, transition?: ITransition): void { const o = t.__localMatrix copy(matrix, o) rotateOfOuter(matrix, origin, angle) if (t.origin || t.around) L.setTransform(t, matrix, false, transition) else t.set({ x: t.x + matrix.e - o.e, y: t.y + matrix.f - o.f, rotation: MathHelper.formatRotation(t.rotation + angle) }, transition) }, skewOfWorld(t: ILeaf, origin: IPointData, skewX: number, skewY?: number, resize?: boolean, transition?: ITransition): void { L.skewOfLocal(t, getTempLocal(t, origin), skewX, skewY, resize, transition) }, skewOfLocal(t: ILeaf, origin: IPointData, skewX: number, skewY: number = 0, resize?: boolean, transition?: ITransition): void { copy(matrix, t.__localMatrix) skewOfOuter(matrix, origin, skewX, skewY) L.setTransform(t, matrix, resize, transition) }, transformWorld(t: ILeaf, transform: IMatrixData, resize?: boolean, transition?: ITransition): void { copy(matrix, t.worldTransform) multiplyParent(matrix, transform) if (t.parent) divideParent(matrix, t.parent.worldTransform) L.setTransform(t, matrix, resize, transition) }, transform(t: ILeaf, transform: IMatrixData, resize?: boolean, transition?: ITransition): void { copy(matrix, t.localTransform) multiplyParent(matrix, transform) L.setTransform(t, matrix, resize, transition) }, setTransform(t: ILeaf, transform: IMatrixData, resize?: boolean, transition?: ITransition): void { const data = t.__, originPoint = data.origin && L.getInnerOrigin(t, data.origin) const layout = getLayout(transform, originPoint, data.around && L.getInnerOrigin(t, data.around)) if (resize) { const scaleX = layout.scaleX / t.scaleX, scaleY = layout.scaleY / t.scaleY delete layout.scaleX, delete layout.scaleY if (originPoint) { // fix origin: resize 方式下 boxBounds 会变化,导致 originPoint 不准确,需偏移至正确的位置 BoundsHelper.scale(t.boxBounds, Math.abs(scaleX), Math.abs(scaleY)) const changedPoint = L.getInnerOrigin(t, data.origin) PointHelper.move(layout, originPoint.x - changedPoint.x, originPoint.y - changedPoint.y) } t.set(layout) t.scaleResize(scaleX, scaleY, false) } else t.set(layout, transition) }, getFlipTransform(t: ILeaf, axis: IAxis): IMatrixData { const m = getMatrixData() const sign = axis === 'x' ? 1 : -1 scaleOfOuter(m, L.getLocalOrigin(t, 'center'), -1 * sign, 1 * sign) return m }, getLocalOrigin(t: ILeaf, origin: IPointData | IAlign): IPointData { return PointHelper.tempToOuterOf(L.getInnerOrigin(t, origin), t.localTransform) }, getInnerOrigin(t: ILeaf, origin: IPointData | IAlign): IPointData { const innerOrigin = {} as IPointData AroundHelper.toPoint(origin, t.boxBounds, innerOrigin) return innerOrigin }, getRelativeWorld(t: ILeaf, relative: ILeaf, temp?: boolean): IMatrixData { copy(matrix, t.worldTransform) divideParent(matrix, relative.worldTransform) return temp ? matrix : { ...matrix } }, drop(t: ILeaf, parent: ILeaf, index?: number, resize?: boolean): void { t.setTransform(L.getRelativeWorld(t, parent, true), resize) parent.add(t, index) }, hasParent(p: ILeaf, parent: ILeaf): boolean | void { if (!parent) return false while (p) { if (parent === p) return true p = p.parent } } } const L = LeafHelper const { updateAllMatrix, updateMatrix, updateAllWorldOpacity, updateAllChange, updateChange } = L function getTempLocal(t: ILeaf, world: IPointData): IPointData { t.__layout.update() return t.parent ? PointHelper.tempToInnerOf(world, t.parent.__world) : world }