all files / src/ animate-scroll.js

100% Statements 143/143
95.31% Branches 61/64
100% Functions 33/33
100% Lines 39/39
28 statements, 11 functions, 24 branches Ignored     
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80                                                                                   
/**
 * Class for executing and maintaining a smooth scroll-animation using TweenFunctions for easing
 */
import requestAnimationFrame from './request-animation-frame';
import TweenFunctions from 'tween-functions';
 
class AnimateScroll {
    constructor(options) {
        this._setup(options);
    }
 
    _setup(opt) {
        const options = opt || this._options;
 
        this._start = null;
        this._cancel = false;
        this._duration = options.duration || 500;
        this._container = options.container || document.body || document.documentElement;
        this._startPosition = this._getCurrentPosition(this._container);
        this._options = options;
        this._id = null;
        this._component = null;
    }
 
    _getCurrentPosition(container) {
        return container.scrollTop;
    }
 
    _setupListeners() {
        this._listener = this.cancel.bind(this);
        AnimateScroll.cancelEvent.forEach((e) => this._container.addEventListener(e, this._listener));
    }
 
    _teardownListeners() {
        AnimateScroll.cancelEvent.forEach((e) => this._container.removeEventListener(e, this._listener));
    }
 
    start(id, component, targetPosition) {
        this._targetPosition = targetPosition;
        this._id = id;
        this._component = component;
        this._setupListeners();
        requestAnimationFrame(this.animate.bind(this));
    }
 
    animate(time) {
        if (this._start === null) {
            this._start = time;
        }
        if (this._cancel) {
            return;
        }
 
        const deltaT = time - this._start;
 
        let currentPosition = this._targetPosition;
        if (deltaT < this._duration) {
            currentPosition = AnimateScroll.easing(deltaT, this._startPosition, this._targetPosition, this._duration);
        }
 
        this._container.scrollTop = currentPosition;
 
        if (deltaT < this._duration) {
            requestAnimationFrame(this.animate.bind(this));
        } else {
            this._teardownListeners();
            this._options.events.end(this._id, this._component);
        }
    }
 
    cancel() {
        this._cancel = true;
    }
}
 
AnimateScroll.easing = TweenFunctions.easeInOutQuad;
AnimateScroll.cancelEvent = ['mousedown', 'mousewheel', 'touchmove', 'keydown'];
 
export default AnimateScroll;