我正在寻找一个简单的,跨浏览器“滚动到顶部”的动画,我可以应用到一个链接。我不想需要一个JS库,如jQuery/Moo等。
// jQuery Equivilant to convert to pure JS...
$('html, body').animate({scrollTop:0}, 400);
对于那些在跳进图书馆之前应该100%学习JS的人来说,我是一个完美的例子。:(
我正在寻找一个简单的,跨浏览器“滚动到顶部”的动画,我可以应用到一个链接。我不想需要一个JS库,如jQuery/Moo等。
// jQuery Equivilant to convert to pure JS...
$('html, body').animate({scrollTop:0}, 400);
对于那些在跳进图书馆之前应该100%学习JS的人来说,我是一个完美的例子。:(
当前回答
一件容易的事。
var scrollIt = function(time) {
// time = scroll time in ms
var start = new Date().getTime(),
scroll = document.documentElement.scrollTop + document.body.scrollTop,
timer = setInterval(function() {
var now = Math.min(time,(new Date().getTime())-start)/time;
document.documentElement.scrollTop
= document.body.scrollTop = (1-time)/start*scroll;
if( now == 1) clearTimeout(timer);
},25);
}
其他回答
这是一种基于上述答案的跨浏览器方法
function scrollTo(to, duration) {
if (duration < 0) return;
var scrollTop = document.body.scrollTop + document.documentElement.scrollTop;
var difference = to - scrollTop;
var perTick = difference / duration * 10;
setTimeout(function() {
scrollTop = scrollTop + perTick;
document.body.scrollTop = scrollTop;
document.documentElement.scrollTop = scrollTop;
if (scrollTop === to) return;
scrollTo(to, duration - 10);
}, 10);
}
实际上有一个纯javascript的方式来完成这个不使用setTimeout或requestAnimationFrame或jQuery。
简而言之,在scrollView中找到要滚动到的元素,并使用scrollIntoView
el.scrollIntoView({行为:“平滑”});
这是一个普朗克。
基于这里的一些答案,但使用了一些简单的数学,使用正弦曲线进行平稳过渡:
scrollTo(element, from, to, duration, currentTime) {
if (from <= 0) { from = 0;}
if (to <= 0) { to = 0;}
if (currentTime>=duration) return;
let delta = to-from;
let progress = currentTime / duration * Math.PI / 2;
let position = delta * (Math.sin(progress));
setTimeout(() => {
element.scrollTop = from + position;
this.scrollTo(element, from, to, duration, currentTime + 10);
}, 10);
}
用法:
// Smoothly scroll from current position to new position in 1/2 second.
scrollTo(element, element.scrollTop, element.scrollTop + 400, 500, 0);
注:注意ES6风格
我已经选择了@timwolla answer的@akai版本,并添加了stopAnimation函数作为返回,所以在开始新的动画之前,旧的动画可以停止。
if ( this.stopAnimation )
this.stopAnimation()
this.stopAnimation = scrollTo( el, scrollDestination, 300 )
// definitions
function scrollTo(element, to, duration) {
var start = element.scrollTop,
change = to - start,
increment = 20,
timeOut;
var animateScroll = function(elapsedTime) {
elapsedTime += increment;
var position = easeInOut(elapsedTime, start, change, duration);
element.scrollTop = position;
if (elapsedTime < duration) {
timeOut = setTimeout(function() {
animateScroll(elapsedTime);
}, increment);
}
};
animateScroll(0);
return stopAnimation
function stopAnimation() {
clearTimeout( timeOut )
}
}
function easeInOut(currentTime, start, change, duration) {
currentTime /= duration / 2;
if (currentTime < 1) {
return change / 2 * currentTime * currentTime + start;
}
currentTime -= 1;
return -change / 2 * (currentTime * (currentTime - 2) - 1) + start;
}
看来已经有很多解决方案了。不管怎样,这是另一个,使用简化方程。
// first add raf shim
// http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/
window.requestAnimFrame = (function(){
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
function( callback ){
window.setTimeout(callback, 1000 / 60);
};
})();
// main function
function scrollToY(scrollTargetY, speed, easing) {
// scrollTargetY: the target scrollY property of the window
// speed: time in pixels per second
// easing: easing equation to use
var scrollY = window.scrollY || document.documentElement.scrollTop,
scrollTargetY = scrollTargetY || 0,
speed = speed || 2000,
easing = easing || 'easeOutSine',
currentTime = 0;
// min time .1, max time .8 seconds
var time = Math.max(.1, Math.min(Math.abs(scrollY - scrollTargetY) / speed, .8));
// easing equations from https://github.com/danro/easing-js/blob/master/easing.js
var easingEquations = {
easeOutSine: function (pos) {
return Math.sin(pos * (Math.PI / 2));
},
easeInOutSine: function (pos) {
return (-0.5 * (Math.cos(Math.PI * pos) - 1));
},
easeInOutQuint: function (pos) {
if ((pos /= 0.5) < 1) {
return 0.5 * Math.pow(pos, 5);
}
return 0.5 * (Math.pow((pos - 2), 5) + 2);
}
};
// add animation loop
function tick() {
currentTime += 1 / 60;
var p = currentTime / time;
var t = easingEquations[easing](p);
if (p < 1) {
requestAnimFrame(tick);
window.scrollTo(0, scrollY + ((scrollTargetY - scrollY) * t));
} else {
console.log('scroll done');
window.scrollTo(0, scrollTargetY);
}
}
// call it once to get started
tick();
}
// scroll it!
scrollToY(0, 1500, 'easeInOutQuint');