import { requestAnimationFrame } from './utils';
|
|
function scrollTo(...args) {
|
let [left, top, duration, easing, callback] = args;
|
if (args.length === 4 && typeof easing === 'function') {
|
callback = easing;
|
[left, top, duration, callback, easing] = args;
|
}
|
if (typeof easing === 'undefined') easing = 'swing';
|
|
return this.each(function animate() {
|
const el = this;
|
let currentTop;
|
let currentLeft;
|
let maxTop;
|
let maxLeft;
|
let newTop;
|
let newLeft;
|
let scrollTop; // eslint-disable-line
|
let scrollLeft; // eslint-disable-line
|
let animateTop = top > 0 || top === 0;
|
let animateLeft = left > 0 || left === 0;
|
if (typeof easing === 'undefined') {
|
easing = 'swing';
|
}
|
if (animateTop) {
|
currentTop = el.scrollTop;
|
if (!duration) {
|
el.scrollTop = top;
|
}
|
}
|
if (animateLeft) {
|
currentLeft = el.scrollLeft;
|
if (!duration) {
|
el.scrollLeft = left;
|
}
|
}
|
if (!duration) return;
|
if (animateTop) {
|
maxTop = el.scrollHeight - el.offsetHeight;
|
newTop = Math.max(Math.min(top, maxTop), 0);
|
}
|
if (animateLeft) {
|
maxLeft = el.scrollWidth - el.offsetWidth;
|
newLeft = Math.max(Math.min(left, maxLeft), 0);
|
}
|
let startTime = null;
|
if (animateTop && newTop === currentTop) animateTop = false;
|
if (animateLeft && newLeft === currentLeft) animateLeft = false;
|
function render(time = new Date().getTime()) {
|
if (startTime === null) {
|
startTime = time;
|
}
|
const progress = Math.max(Math.min((time - startTime) / duration, 1), 0);
|
const easeProgress = easing === 'linear' ? progress : (0.5 - (Math.cos(progress * Math.PI) / 2));
|
let done;
|
if (animateTop) scrollTop = currentTop + (easeProgress * (newTop - currentTop));
|
if (animateLeft) scrollLeft = currentLeft + (easeProgress * (newLeft - currentLeft));
|
if (animateTop && newTop > currentTop && scrollTop >= newTop) {
|
el.scrollTop = newTop;
|
done = true;
|
}
|
if (animateTop && newTop < currentTop && scrollTop <= newTop) {
|
el.scrollTop = newTop;
|
done = true;
|
}
|
if (animateLeft && newLeft > currentLeft && scrollLeft >= newLeft) {
|
el.scrollLeft = newLeft;
|
done = true;
|
}
|
if (animateLeft && newLeft < currentLeft && scrollLeft <= newLeft) {
|
el.scrollLeft = newLeft;
|
done = true;
|
}
|
|
if (done) {
|
if (callback) callback();
|
return;
|
}
|
if (animateTop) el.scrollTop = scrollTop;
|
if (animateLeft) el.scrollLeft = scrollLeft;
|
requestAnimationFrame(render);
|
}
|
requestAnimationFrame(render);
|
});
|
}
|
// scrollTop(top, duration, easing, callback) {
|
function scrollTop(...args) {
|
let [top, duration, easing, callback] = args;
|
if (args.length === 3 && typeof easing === 'function') {
|
[top, duration, callback, easing] = args;
|
}
|
const dom = this;
|
if (typeof top === 'undefined') {
|
if (dom.length > 0) return dom[0].scrollTop;
|
return null;
|
}
|
return dom.scrollTo(undefined, top, duration, easing, callback);
|
}
|
function scrollLeft(...args) {
|
let [left, duration, easing, callback] = args;
|
if (args.length === 3 && typeof easing === 'function') {
|
[left, duration, callback, easing] = args;
|
}
|
const dom = this;
|
if (typeof left === 'undefined') {
|
if (dom.length > 0) return dom[0].scrollLeft;
|
return null;
|
}
|
return dom.scrollTo(left, undefined, duration, easing, callback);
|
}
|
|
export { scrollTo, scrollTop, scrollLeft };
|