import { Able, Bounds, params, payload, PositionSchema, RotationData, TransformData } from '../../common'; import { Angle, Matrix } from '@gedit/math'; import { DragablePayload } from './dragable'; export const RotatePayload = Symbol('RotatePayload'); export interface RotatePayload extends DragablePayload { } function applyInverse(pos: PositionSchema, matrix: Matrix, scale: number): PositionSchema { pos = matrix.applyInverse({ x: pos.x / scale, y: pos.y / scale }); return { x: pos.x, y: pos.y, }; } interface RotateStart { rotationStart: number, origin: PositionSchema, startPos: PositionSchema matrix: Matrix } export class Rotatable extends Able { // 用于吸附计算 // static globalBefore = Dragable.globalBefore; static type = 'Rotatable'; protected startCacheMap: Map = new Map(); @payload(RotatePayload) payload: RotatePayload; @params(RotationData, TransformData) handle(rotation: RotationData, transform: TransformData): void { const {scale = 1, isStart, isMoving} = this.payload; if (isStart && !isMoving) { const matrix = transform.worldTransform.clone(); const origin = Bounds.getCenter(transform); const startPos = applyInverse(this.payload.startPos, matrix, scale); this.startCacheMap.set(transform, {rotationStart: rotation.data, origin, startPos, matrix}); } else if (isMoving) { const {rotationStart, origin, startPos, matrix} = this.startCacheMap.get(transform)!; const endPos = applyInverse(this.payload.endPos, matrix, scale); const angle = Angle.betweenPoints(startPos, endPos, origin); rotation.update(Angle.wrap(rotationStart + angle)); } else { this.startCacheMap.clear(); } } }