// @flow import Point from '@mapbox/point-geometry'; import {indexTouches} from './handler_util'; export default class TouchPanHandler { _enabled: boolean; _active: boolean; _touches: { [string | number]: Point }; _minTouches: number; _clickTolerance: number; _sum: Point; constructor(options: { clickTolerance: number }) { this._minTouches = 1; this._clickTolerance = options.clickTolerance || 1; this.reset(); } reset() { this._active = false; this._touches = {}; this._sum = new Point(0, 0); } touchstart(e: TouchEvent, points: Array, mapTouches: Array) { return this._calculateTransform(e, points, mapTouches); } touchmove(e: TouchEvent, points: Array, mapTouches: Array) { if (!this._active || mapTouches.length < this._minTouches) return; e.preventDefault(); return this._calculateTransform(e, points, mapTouches); } touchend(e: TouchEvent, points: Array, mapTouches: Array) { this._calculateTransform(e, points, mapTouches); if (this._active && mapTouches.length < this._minTouches) { this.reset(); } } touchcancel() { this.reset(); } _calculateTransform(e: TouchEvent, points: Array, mapTouches: Array) { if (mapTouches.length > 0) this._active = true; const touches = indexTouches(mapTouches, points); const touchPointSum = new Point(0, 0); const touchDeltaSum = new Point(0, 0); let touchDeltaCount = 0; for (const identifier in touches) { const point = touches[identifier]; const prevPoint = this._touches[identifier]; if (prevPoint) { touchPointSum._add(point); touchDeltaSum._add(point.sub(prevPoint)); touchDeltaCount++; touches[identifier] = point; } } this._touches = touches; if (touchDeltaCount < this._minTouches || !touchDeltaSum.mag()) return; const panDelta = touchDeltaSum.div(touchDeltaCount); this._sum._add(panDelta); if (this._sum.mag() < this._clickTolerance) return; const around = touchPointSum.div(touchDeltaCount); return { around, panDelta }; } enable() { this._enabled = true; } disable() { this._enabled = false; this.reset(); } isEnabled() { return this._enabled; } isActive() { return this._active; } }