UNPKG

devexpress-gantt

Version:

DevExpress Gantt Control

99 lines (91 loc) 4.36 kB
import { Point } from "@devexpress/utils/lib/geometry/point"; import { EvtUtils } from "@devexpress/utils/lib/utils/evt"; import { Metrics } from "@devexpress/utils/lib/geometry/metrics"; import { TaskAreaStateBase } from "./TaskAreaStateBase"; import { TaskAreaStateEventNames } from "./TaskAreaStateEventNames"; const PINCH_CHANGE_DISTANCE = 3; const MOUSE_ZOOM_LOCK_TIMEOUT = 50; const TOUCH_ZOOM_LOCK_TIMEOUT = 1000; export class TaskAreaZoomState extends TaskAreaStateBase { private _isInZooming = false; private prevDistance: number; public onMouseWheel(evt: WheelEvent): void { if(evt.ctrlKey) { evt.preventDefault(); evt.stopPropagation(); if(!this._isInZooming) this.processZoom(evt, EvtUtils.getWheelDelta(evt) > 0, MOUSE_ZOOM_LOCK_TIMEOUT); } } protected onDocumentPointerUpInternal(evt: PointerEvent): void { this.onEndZoom(evt); } protected onDocumentPointerMoveInternal(evt: PointerEvent): void { this.onTouchZoom(evt); } protected onTouchEndInternal(evt: TouchEvent): void { this.onEndZoom(evt); } protected onTouchMoveInternal(evt: TouchEvent): void { this.onTouchZoom(evt); } protected onTouchZoom(evt: TouchEvent | PointerEvent): void { evt.stopPropagation(); evt.preventDefault(); if(!this._isInZooming) { const distance = this.getTouchDistance(evt); this.prevDistance ??= distance; const diff = this.prevDistance - distance; if(Math.abs(diff) > PINCH_CHANGE_DISTANCE) { this.processZoom(evt, diff > 0, TOUCH_ZOOM_LOCK_TIMEOUT); this.prevDistance = distance; } } } protected processZoom(evt: Event, increase: boolean, lockTimeout: number): void { this._isInZooming = true; setTimeout(() => { this._isInZooming = false; }, lockTimeout); const eventKey = increase ? TaskAreaStateEventNames.TASK_AREA_ZOOM_IN : TaskAreaStateEventNames.TASK_AREA_ZOOM_OUT; this.raiseEvent(eventKey, evt, null, { leftPos: this.getLeftPosition(evt) }); } protected onEndZoom(evt: Event): void { this.prevDistance = null; this.raiseEvent(TaskAreaStateEventNames.STATE_EXIT, evt); } private getTouchDistance(evt: TouchEvent | PointerEvent) { const points = this.GetTouchPoints(evt); return this.getDistance(points[0], points[1]); } private GetTouchPoints(evt: Event): Point[] { if(this.isTouchEvent(evt)) { const touches = (evt as TouchEvent).touches; return [ new Point(touches[0].pageX, touches[0].pageY), new Point(touches[1].pageX, touches[1].pageY) ]; } const pointers = this.raiseEvent(TaskAreaStateEventNames.GET_POINTERS_INFO, evt); return [ new Point(pointers[0]?.pageX, pointers[0]?.pageY), new Point(pointers[1]?.pageX, pointers[1]?.pageY) ]; } private getDistance(a: Point, b: Point): number { return Metrics.euclideanDistance(a, b); } protected getLeftPosition(evt: Event): number { let leftPos = 0; if(this.isTouchEvent(evt) || this.isPointerEvent(evt)) leftPos = this.getZoomMiddlePoint(evt).x; else if(this.isMouseEvent(evt)) leftPos = this.getMouseZoomLeftPos(<MouseEvent>evt); return leftPos; } private getMouseZoomLeftPos(evt: MouseEvent): number { const ref = this.raiseEvent(TaskAreaStateEventNames.GET_COORDINATES_REF_POINT) as Point; return EvtUtils.getEventX(evt) - ref.x; } private getZoomMiddlePoint(evt: Event): Point { const ref = this.raiseEvent(TaskAreaStateEventNames.GET_COORDINATES_REF_POINT) as Point; const points = this.GetTouchPoints(evt); const point1 = this.convertScreenToChartCoordinates(points[0], ref); const point2 = this.convertScreenToChartCoordinates(points[1], ref); return new Point( (point1.x + point2.x) / 2, (point1.y + point2.y) / 2 ); } private convertScreenToChartCoordinates(p: Point, ref: Point): Point { return new Point(p.x - ref.x, p.y - ref.y); } }