UNPKG

motion-v

Version:

<p align="center"> <img width="100" height="100" alt="Motion logo" src="https://user-images.githubusercontent.com/7850794/164965523-3eced4c4-6020-467e-acde-f11b7900ad62.png" /> </p> <h1 align="center">Motion for Vue</h1>

152 lines (151 loc) 5.29 kB
import { addPointerEvent } from "../../../events/add-pointer-event.mjs"; import { extractEventInfo } from "../../../events/event-info.mjs"; import { distance2D } from "../../../external/.pnpm/framer-motion@12.5.0/external/framer-motion/dist/es/utils/distance.mjs"; import { frame, cancelFrame, frameData } from "../../../external/.pnpm/motion-dom@12.5.0/external/motion-dom/dist/es/frameloop/frame.mjs"; import "../../../external/.pnpm/motion-utils@12.5.0/external/motion-utils/dist/es/errors.mjs"; import { pipe } from "../../../external/.pnpm/framer-motion@12.5.0/external/framer-motion/dist/es/utils/pipe.mjs"; import { secondsToMilliseconds, millisecondsToSeconds } from "../../../utils/time-conversion.mjs"; import { isPrimaryPointer } from "../../../events/utils/is-primary-pointer.mjs"; class PanSession { constructor(event, handlers, { transformPagePoint, contextWindow, dragSnapToOrigin = false } = {}) { this.startEvent = null; this.lastMoveEvent = null; this.lastMoveEventInfo = null; this.handlers = {}; this.contextWindow = window; this.updatePoint = () => { if (!(this.lastMoveEvent && this.lastMoveEventInfo)) return; const info2 = getPanInfo(this.lastMoveEventInfo, this.history); const isPanStarted = this.startEvent !== null; const isDistancePastThreshold = distance2D(info2.offset, { x: 0, y: 0 }) >= 3; if (!isPanStarted && !isDistancePastThreshold) return; const { point: point2 } = info2; const { timestamp: timestamp2 } = frameData; this.history.push({ ...point2, timestamp: timestamp2 }); const { onStart, onMove } = this.handlers; if (!isPanStarted) { onStart && onStart(this.lastMoveEvent, info2); this.startEvent = this.lastMoveEvent; } onMove && onMove(this.lastMoveEvent, info2); }; this.handlePointerMove = (event2, info2) => { this.lastMoveEvent = event2; this.lastMoveEventInfo = transformPoint(info2, this.transformPagePoint); frame.update(this.updatePoint, true); }; this.handlePointerUp = (event2, info2) => { this.end(); const { onEnd, onSessionEnd, resumeAnimation } = this.handlers; if (this.dragSnapToOrigin) resumeAnimation && resumeAnimation(); if (!(this.lastMoveEvent && this.lastMoveEventInfo)) return; const panInfo = getPanInfo( event2.type === "pointercancel" ? this.lastMoveEventInfo : transformPoint(info2, this.transformPagePoint), this.history ); if (this.startEvent && onEnd) { onEnd(event2, panInfo); } onSessionEnd && onSessionEnd(event2, panInfo); }; if (!isPrimaryPointer(event)) return; this.dragSnapToOrigin = dragSnapToOrigin; this.handlers = handlers; this.transformPagePoint = transformPagePoint; this.contextWindow = contextWindow || window; const info = extractEventInfo(event); const initialInfo = transformPoint(info, this.transformPagePoint); const { point } = initialInfo; const { timestamp } = frameData; this.history = [{ ...point, timestamp }]; const { onSessionStart } = handlers; onSessionStart && onSessionStart(event, getPanInfo(initialInfo, this.history)); this.removeListeners = pipe( addPointerEvent( this.contextWindow, "pointermove", this.handlePointerMove ), addPointerEvent( this.contextWindow, "pointerup", this.handlePointerUp ), addPointerEvent( this.contextWindow, "pointercancel", this.handlePointerUp ) ); } updateHandlers(handlers) { this.handlers = handlers; } end() { this.removeListeners && this.removeListeners(); cancelFrame(this.updatePoint); } } function transformPoint(info, transformPagePoint) { return transformPagePoint ? { point: transformPagePoint(info.point) } : info; } function subtractPoint(a, b) { return { x: a.x - b.x, y: a.y - b.y }; } function getPanInfo({ point }, history) { return { point, delta: subtractPoint(point, lastDevicePoint(history)), offset: subtractPoint(point, startDevicePoint(history)), velocity: getVelocity(history, 0.1) }; } function startDevicePoint(history) { return history[0]; } function lastDevicePoint(history) { return history[history.length - 1]; } function getVelocity(history, timeDelta) { if (history.length < 2) { return { x: 0, y: 0 }; } let i = history.length - 1; let timestampedPoint = null; const lastPoint = lastDevicePoint(history); while (i >= 0) { timestampedPoint = history[i]; if (lastPoint.timestamp - timestampedPoint.timestamp > secondsToMilliseconds(timeDelta)) { break; } i--; } if (!timestampedPoint) { return { x: 0, y: 0 }; } const time = millisecondsToSeconds( lastPoint.timestamp - timestampedPoint.timestamp ); if (time === 0) { return { x: 0, y: 0 }; } const currentVelocity = { x: (lastPoint.x - timestampedPoint.x) / time, y: (lastPoint.y - timestampedPoint.y) / time }; if (currentVelocity.x === Infinity) { currentVelocity.x = 0; } if (currentVelocity.y === Infinity) { currentVelocity.y = 0; } return currentVelocity; } export { PanSession };