不带 jquery 的动画

我正在尝试不使用 jQuery 制作一个动画“滚动到顶部”效果。

在 jQuery 中,我通常使用以下代码:

$('#go-to-top').click(function(){
$('html,body').animate({ scrollTop: 0 }, 400);
return false;
});

如何在不使用 jQuery 的情况下使 scrollTop 动画化?

143243 次浏览

HTML:

<button onclick="scrollToTop(1000);"></button>

1# JavaScript (linear):

function scrollToTop (duration) {
// cancel if already on top
if (document.scrollingElement.scrollTop === 0) return;


const totalScrollDistance = document.scrollingElement.scrollTop;
let scrollY = totalScrollDistance, oldTimestamp = null;


function step (newTimestamp) {
if (oldTimestamp !== null) {
// if duration is 0 scrollY will be -Infinity
scrollY -= totalScrollDistance * (newTimestamp - oldTimestamp) / duration;
if (scrollY <= 0) return document.scrollingElement.scrollTop = 0;
document.scrollingElement.scrollTop = scrollY;
}
oldTimestamp = newTimestamp;
window.requestAnimationFrame(step);
}
window.requestAnimationFrame(step);
}

2# JavaScript (ease in and out):

function scrollToTop (duration) {
// cancel if already on top
if (document.scrollingElement.scrollTop === 0) return;


const cosParameter = document.scrollingElement.scrollTop / 2;
let scrollCount = 0, oldTimestamp = null;


function step (newTimestamp) {
if (oldTimestamp !== null) {
// if duration is 0 scrollCount will be Infinity
scrollCount += Math.PI * (newTimestamp - oldTimestamp) / duration;
if (scrollCount >= Math.PI) return document.scrollingElement.scrollTop = 0;
document.scrollingElement.scrollTop = cosParameter + cosParameter * Math.cos(scrollCount);
}
oldTimestamp = newTimestamp;
window.requestAnimationFrame(step);
}
window.requestAnimationFrame(step);
}
/*
Explanation:
- pi is the length/end point of the cosinus intervall (see below)
- newTimestamp indicates the current time when callbacks queued by requestAnimationFrame begin to fire.
(for more information see https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame)
- newTimestamp - oldTimestamp equals the delta time


a * cos (bx + c) + d                        | c translates along the x axis = 0
= a * cos (bx) + d                            | d translates along the y axis = 1 -> only positive y values
= a * cos (bx) + 1                            | a stretches along the y axis = cosParameter = window.scrollY / 2
= cosParameter + cosParameter * (cos bx)  | b stretches along the x axis = scrollCount = Math.PI / (scrollDuration / (newTimestamp - oldTimestamp))
= cosParameter + cosParameter * (cos scrollCount * x)
*/

Note:

  • Duration in milliseconds (1000ms = 1s)
  • Second script uses the cos function. Example curve:

enter image description here

3# Simple scrolling library on Github