Home Reference Source

src/deceleration.js

import {
  performanceNow,
} from './dom'
import tick from './tick'
/**
 * @class Deceleration - simple animation
 *    - an animation that mimic natrual slow down during scrolling
 * @example
 * new Deceleration({
 *  velocity: 1,
 *  onStep: (movement) => {
 *    console.log(movement)
 *  },
 *  onEnd: () => {
 *    console.log('deceleration end')
 *  }
 * })
 */
export class Deceleration {
  constructor(options) {
    this.step = this.step.bind(this)
    this.setOptions(options)
  }
  setOptions(options = {}) {
    let {
      velocity,
      resistance = 0.001
    } = options
    if (velocity) {
      this.velocity = velocity
    }
    this.resistance = resistance
    this.options = Object.assign({}, this.options, options)
    return this
  }
  start() {
    this.prevTime = this.currentTime = performanceNow()
    this.sign = this.velocity > 0 ? 1 : -1
    this.prevV = Math.abs(this.velocity)
    this.clockId = tick.add(this.step)

    return this
  }
  stop() {
    tick.remove(this.clockId)
    this.clockId = null
    //console.log('deceleration stop')
    if (this.options.onEnd) {
      this.options.onEnd()
    }

    return this
  }
  step(time) {
    this.currentTime = time
    let span = time - this.prevTime
    let v = this.prevV
    if (v <= 0) {
      //console.log('will stop dec', v)
      this.stop()
    } else {

      //console.log(span)
      let displacement = v * span - (this.resistance * Math.pow(span, 2)) / 2

      //console.log(this.sign * displacement, v)
      if (this.options.onStep) {
        this.options.onStep(this.sign * displacement)
      }

      this.prevTime = this.currentTime
      this.prevV = this.prevV - this.resistance * span
    }
  }
}

export default Deceleration