private updateDeceleration()

in client/src/components/scroll-list/scroll-list.ts [380:424]


  private updateDeceleration(decelerationInfo: {velocity: number, prevTime: number}) {
    // get target velocity
    let targetVelocity = 0;
    const scrollPos = this.getScrollPosition();
    let outsideBounds = false;
    const contentWidth = this.getScrollContentWidth();
    const containerWidth = this.getScrollContainerWidth();
    if(scrollPos > 0) {
      // too far right - accelerate left
      targetVelocity = -this.config.snapMaxSpeed * Math.min(1, scrollPos / this.config.snapDecelerationDistance);
      outsideBounds = true;
    } else {
      const minScroll = Math.min(0, containerWidth - contentWidth);
      if(scrollPos < minScroll) {
        // too far left - accelerate right
        targetVelocity = this.config.snapMaxSpeed * Math.min(1, (minScroll - scrollPos) / this.config.snapDecelerationDistance);
        outsideBounds = true;
      }
    }
    // accelerate towards target velocity
    let velocity = decelerationInfo.velocity;
    const t = ScrollListComponent.getTime();
    const dt = t - decelerationInfo.prevTime;
    const maxDV = this.config.snapDeceleration * dt;
    if(Math.abs(velocity - targetVelocity) > maxDV) {
      velocity = velocity > targetVelocity ? velocity - maxDV : velocity + maxDV;
    } else {
      velocity = targetVelocity;
    }
    // stop content from scrolling completely offscreen
    if(scrollPos < -contentWidth) {
      velocity = Math.max(0, velocity);
    } else if(scrollPos > containerWidth) {
      velocity = Math.min(0, velocity);
    }
    // update position
    if(velocity != 0 || outsideBounds) {
      decelerationInfo.prevTime = t;
      decelerationInfo.velocity = velocity;
      this.setScrollPosition(scrollPos + velocity * dt);
    } else {
      clearInterval(this.animationInterval);
      this.animationInterval = 0;
    }
  }