penguin/narou-android

Simple 縦書き reader for narou

app/src/main/assets/reader/motion.js

raw · 1423 bytes

/* Port of the user's AccelerScroll / ReaderContent model: acceleration, speed cap,
 * neutral-zone exponential braking. Units are CSS px/s and CSS px/s².
 * No sensor integration or DOM dependencies, so the physics can be tested directly. */
(function (root) {
  'use strict';
  class Motion {
    constructor() { this.reset(); }
    reset() { this.velocity = 0; }
    step(x, seconds, config) {
      if (!Number.isFinite(x) || !Number.isFinite(seconds) || seconds <= 0 || seconds > .15) {
        this.reset(); return 0;
      }
      const delta = x - config.neutral;
      const acceleration = Math.abs(delta) <= config.deadzone ? 0 : delta * (config.reverse ? -1 : 1);
      // Subdivide to keep acceleration/braking consistent at 60/90/120 Hz.
      let distance = 0;
      while (seconds > .000001) {
        const dt = Math.min(seconds, .005), previous = this.velocity;
        if (acceleration === 0) this.velocity *= Math.pow(1 - config.brake, dt / .02);
        else this.velocity = Math.max(-config.speed, Math.min(config.speed,
          this.velocity + config.acceleration * acceleration * dt));
        if (Math.abs(this.velocity) < .01) this.velocity = 0;
        distance += (previous + this.velocity) * .5 * dt;
        seconds -= dt;
      }
      return distance;
    }
  }
  if (typeof module === 'object' && module.exports) module.exports = Motion;
  else root.NarouMotion = Motion;
})(globalThis);