UNPKG

@antv/s2

Version:

effective spreadsheet render core lib

118 lines 5.48 kB
import EE from '@antv/event-emitter'; import { easeCubicIn as easeFunc } from '@antv/vendor/d3-ease'; import { OriginEventType } from '../../common'; /** 获取执行时间戳 */ const now = () => { var _a; return (_a = performance === null || performance === void 0 ? void 0 : performance.now()) !== null && _a !== void 0 ? _a : Date.now(); }; /** 动画总时间 */ const TOTAL_MS = 800; /** swipe 手势判断阈值 */ const SWIPE_TIME_GAP = 100; /** * 判断是否是多点触控 (用于检测缩放手势) * @param evt FederatedPointerEvent * @returns boolean - true 表示是多点触控 (>= 2 个触摸点) */ const isMultiTouch = (evt) => { var _a; const nativeEvent = evt.nativeEvent; // 检查是否是触摸事件且有多个触摸点 return ((_a = nativeEvent === null || nativeEvent === void 0 ? void 0 : nativeEvent.touches) === null || _a === void 0 ? void 0 : _a.length) >= 2; }; /** * 移动端滚动事件 * @see https://github.com/antvis/g-gesture/blob/next/src/event/wheel.ts */ export class WheelEvent extends EE { constructor(canvas, shouldPreventDefault) { super(); this.bindPointerDown = (evt) => { // 多点触控时 (如缩放手势), 不开始滚动, 让浏览器处理原生缩放行为 // When multi-touch is detected (e.g., pinch-to-zoom), don't start panning // to allow native browser zoom behavior if (isMultiTouch(evt)) { return; } window.cancelAnimationFrame(this.raf); this.panning = true; this.preX = evt.x; this.preY = evt.y; this.speedX = 0; this.speedY = 0; this.lastMoveMS = now(); }; this.bindPointerMove = (evt) => { var _a, _b, _c, _d; // 多点触控时 (如缩放手势), 停止滚动, 让浏览器处理原生缩放行为 // When multi-touch is detected (e.g., pinch-to-zoom), stop panning // to allow native browser zoom behavior if (isMultiTouch(evt)) { this.panning = false; window.cancelAnimationFrame(this.raf); return; } if (this.panning) { const nativeEvent = evt.nativeEvent; const ms = now(); const deltaMS = ms - this.lastMoveMS; const deltaX = this.preX - evt.x; const deltaY = this.preY - evt.y; // https://github.com/antvis/S2/issues/3249 // 根据回调判断是否阻止默认滚动行为 // 必须在事件链早期调用,否则浏览器的 passive 事件监听器会接管滚动 if (nativeEvent === null || nativeEvent === void 0 ? void 0 : nativeEvent.cancelable) { const shouldPrevent = (_b = (_a = this.shouldPreventDefault) === null || _a === void 0 ? void 0 : _a.call(this, deltaX, deltaY, evt.x, evt.y)) !== null && _b !== void 0 ? _b : true; if (shouldPrevent) { (_d = (_c = nativeEvent).preventDefault) === null || _d === void 0 ? void 0 : _d.call(_c); } } this.speedX = deltaX / deltaMS; this.speedY = deltaY / deltaMS; this.preX = evt.x; this.preY = evt.y; this.lastMoveMS = ms; this.emit('wheel', Object.assign(Object.assign({}, evt.clone()), { x: evt.x, y: evt.y, deltaX, deltaY, // 传递原生事件用于移动端 preventDefault nativeEvent })); } }; this.bindPointerUp = (evt) => { this.panning = false; const pointerUpMS = now(); if (!this.speedX || !this.speedY || pointerUpMS - this.lastMoveMS >= SWIPE_TIME_GAP) { return; } const moveLoop = () => { const loopStartMS = now(); this.raf = window.requestAnimationFrame(() => { const ms = now(); const ratio = (ms - pointerUpMS) / TOTAL_MS; if (ratio < 1) { const currentRatio = easeFunc(1 - ratio); const t = ms - loopStartMS; this.emit('wheel', Object.assign(Object.assign({}, evt.clone()), { x: evt.x, y: evt.y, deltaX: this.speedX * currentRatio * t, deltaY: this.speedY * currentRatio * t })); moveLoop(); } }); }; moveLoop(); }; this.canvas = canvas; this.panning = false; this.shouldPreventDefault = shouldPreventDefault; this.init(); } init() { this.canvas.addEventListener(OriginEventType.POINTER_DOWN, this.bindPointerDown); this.canvas.addEventListener(OriginEventType.POINTER_MOVE, this.bindPointerMove); this.canvas.addEventListener(OriginEventType.POINTER_UP, this.bindPointerUp); } destroy() { this.canvas.removeEventListener(OriginEventType.POINTER_DOWN, this.bindPointerDown); this.canvas.removeEventListener(OriginEventType.POINTER_MOVE, this.bindPointerMove); this.canvas.removeEventListener(OriginEventType.POINTER_UP, this.bindPointerUp); } } //# sourceMappingURL=wheelEvent.js.map