import { Gesture } from '@use-gesture/vanilla'; import { Disposable, DisposableImpl } from '@gedit/utils'; import { PlaygroundConfigEntity } from '../layer/config/playground-config-entity'; export class PlaygroundGesture extends DisposableImpl { private _pinching = false; constructor( public readonly target: HTMLElement, protected readonly config: PlaygroundConfigEntity, ) { super(); this.preventDefault(); const gesture = new Gesture(target, { // onDrag: ({pinching, cancel, offset: [x, y], ...rest}) => { // if (pinching) return cancel(); // onChange({ ...style, x, y }) // api.start({ x, y }) // }, onPinch: ({origin: [originX, originY], first, last, movement: [ms], offset: [newScale, a] }) => { if (first) { this._pinching = true; } if (last) { this._pinching = false; } const oldScale = this.config.finalScale; const origin = this.config.getPosFromMouseEvent({ clientX: originX, clientY: originY }, false); // 放大后的位置 const finalPos = { x: origin.x / oldScale * newScale, y: origin.y / oldScale * newScale, }; this.config.updateConfig({ scrollX: this.config.config.scrollX + finalPos.x - origin.x, scrollY: this.config.config.scrollY + finalPos.y - origin.y, zoom: newScale * this.config.config.resolution, }); }, }, { // drag: { from: () => [startState.x, startState.y] }, pinch: { scaleBounds: () => this.getScaleBounds(), from: () => ([this.config.finalScale, 0]), // rubberband: true } }); this.toDispose.push(Disposable.create(() => { gesture.destroy(); })); } getScaleBounds(): { min: number, max: number } { return { min: this.config.config.minZoom / this.config.config.resolution, max: this.config.config.maxZoom / this.config.config.resolution, }; } protected preventDefault(): void { // 阻止默认手势 const handler = (e: MouseEvent) => e.preventDefault(); document.addEventListener('gesturestart', handler); document.addEventListener('gesturechange', handler); this.toDispose.push(Disposable.create(() => { document.removeEventListener('gesturestart', handler); document.removeEventListener('gesturechange', handler); })); } get pinching(): boolean { return this._pinching; } }