UNPKG

react-native-gesture-handler

Version:

Declarative API exposing native platform touch and gesture system to React Native

99 lines (79 loc) 2.54 kB
import { AdaptedEvent } from '../interfaces'; import CircularBuffer from './CircularBuffer'; import LeastSquareSolver from './LeastSquareSolver'; export default class VelocityTracker { private assumePointerMoveStoppedMilliseconds = 40; private historySize = 20; private horizonMilliseconds = 300; private minSampleSize = 3; private samples: CircularBuffer<AdaptedEvent>; constructor() { this.samples = new CircularBuffer<AdaptedEvent>(this.historySize); } public add(event: AdaptedEvent): void { this.samples.push(event); } // Returns an estimate of the velocity of the object being tracked by the // tracker given the current information available to the tracker. // // Information is added using [addPosition]. // // Returns null if there is no data on which to base an estimate. private getVelocityEstimate(): [number, number] | null { const x = []; const y = []; const w = []; const time = []; let sampleCount = 0; let index = this.samples.size - 1; const newestSample = this.samples.get(index); if (!newestSample) { return null; } let previousSample = newestSample; // Starting with the most recent PointAtTime sample, iterate backwards while // the samples represent continuous motion. while (sampleCount < this.samples.size) { const sample = this.samples.get(index); const age = newestSample.time - sample.time; const delta = Math.abs(sample.time - previousSample.time); previousSample = sample; if ( age > this.horizonMilliseconds || delta > this.assumePointerMoveStoppedMilliseconds ) { break; } x.push(sample.x); y.push(sample.y); w.push(1); time.push(-age); sampleCount++; index--; } if (sampleCount >= this.minSampleSize) { const xSolver = new LeastSquareSolver(time, x, w); const xFit = xSolver.solve(2); if (xFit !== null) { const ySolver = new LeastSquareSolver(time, y, w); const yFit = ySolver.solve(2); if (yFit !== null) { const xVelocity = xFit.coefficients[1] * 1000; const yVelocity = yFit.coefficients[1] * 1000; return [xVelocity, yVelocity]; } } } return null; } public getVelocity(): [number, number] { const estimate = this.getVelocityEstimate(); if (estimate !== null) { return estimate; } return [0, 0]; } public reset(): void { this.samples.clear(); } }