motion-scroll
Version:
scroll to an element or a position with easing
85 lines (65 loc) • 3.08 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global = global || self, global.MotionScroll = factory());
}(this, function () { 'use strict';
const MotionScroll = {
scroll( config = {} ) {
let {
element = window,
axis = 'y',
scrollTo = 0, // number or dom element
speed = 2000, // speed in pixels per second
easing = null,
callBack = null,
delay = 0, // in seconds
force = false, // prevent mousewheel interaction from cancelling scroll
minScrollTime = 0, // in seconds
maxScrollTime = 10, // in seconds
} = config;
const isYAxis = axis === 'y';
const dir = isYAxis ? 'top' : 'left';
scrollTo = typeof scrollTo === 'number'
? scrollTo
: scrollTo.getBoundingClientRect()[ dir ] - element.getBoundingClientRect()[ dir ] + element[ `scroll${ dir[ 0 ].toUpperCase() + dir.slice( 1 ) }` ];
let scrollCancelled = false;
const scrollPositions = element === window ? [element.scrollX, element.scrollY] : [element.scrollLeft, element.scrollTop];
const [scrollFrom, altAxisPos] = isYAxis ? scrollPositions.reverse() : scrollPositions;
let currentTime = 0;
const time = Math.max( minScrollTime, Math.min( Math.abs( scrollFrom - scrollTo ) / speed, maxScrollTime ) );
// animation loop
function tick() {
currentTime += 1 / 60;
const pos = currentTime / time; // values from 0 to 1
const easingPos = easing !== null ? easing( pos ) : pos; // altered pos value
const finished = pos >= 1;
const scrollPos = [
altAxisPos,
finished
? scrollTo
: scrollFrom + ( ( scrollTo - scrollFrom ) * easingPos ),
];
const [ scrollX, scrollY ] = isYAxis ? scrollPos : scrollPos.reverse();
element.scrollTo( scrollX, scrollY );
if ( finished ) {
cancelScroll();
if ( callBack !== null ) {
callBack();
}
} else if ( !scrollCancelled || force ) {
window.requestAnimationFrame( tick );
}
}
window.setTimeout( () => {
// call it once to get started
tick();
}, delay * 1000 );
function cancelScroll() {
scrollCancelled = true;
window.removeEventListener( 'mousewheel', cancelScroll );
}
window.addEventListener( 'mousewheel', cancelScroll );
}
};
return MotionScroll;
}));