我正在使用Stellar和Skrollr库开发一个视差滚动网站。由于 Firefox 的平滑滚动功能,该网站在 Firefox 中表现完美,但在 Chrome 中,使用鼠标滚轮滚动很生涩,视差效果几乎被破坏。有什么方法可以在所有浏览器中使用鼠标滚轮平滑滚动,同时保持性能?
6 回答
我找到了两个 jQuery 插件,它们可以做你想做的事。
Simplr-SmoothScroll // 来源:SE Question
编辑:因为评论而删除了 SmoothWheel - 它已经很久没有更新了,而且 SmoothScroll 似乎维护得很好。
如果您是Cargo 狂热的程序员,请使用 jQuery。仅当您是真正的程序员时才继续。
拧jQuery.animate(),了解背后的数学并选择一种算法。Robert Penner有一个很好的演示,我选择了 EaseOutQuad。
在这段代码中,我选择不支持 IE 8 和更早版本。这个想法是连接轮子事件,防止它(因为默认行为是生涩的跳跃)并执行自己的平滑跳跃
Math.easeOutQuad = function (t, b, c, d) { t /= d; return -c * t*(t-2) + b; };
(function() { // do not mess global space
var
interval, // scroll is being eased
mult = 0, // how fast do we scroll
dir = 0, // 1 = scroll down, -1 = scroll up
steps = 50, // how many steps in animation
length = 30; // how long to animate
function MouseWheelHandler(e) {
e.preventDefault(); // prevent default browser scroll
clearInterval(interval); // cancel previous animation
++mult; // we are going to scroll faster
var delta = -Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail))); // cross-browser
if(dir!=delta) { // scroll direction changed
mult = 1; // start slowly
dir = delta;
}
// in this cycle, we determine which element to scroll
for(var tgt=e.target; tgt!=document.documentElement; tgt=tgt.parentNode) {
var oldScroll = tgt.scrollTop;
tgt.scrollTop+= delta;
if(oldScroll!=tgt.scrollTop) break;
// else the element can't be scrolled, try its parent in next iteration
}
var start = tgt.scrollTop;
var end = start + length*mult*delta; // where to end the scroll
var change = end - start; // base change in one step
var step = 0; // current step
interval = setInterval(function() {
var pos = Math.easeOutQuad(step++,start,change,steps); // calculate next step
tgt.scrollTop = pos; // scroll the target to next step
if(step>=steps) { // scroll finished without speed up - stop animation
mult = 0; // next scroll will start slowly
clearInterval(interval);
}
},10);
}
// nonstandard: Chrome, IE, Opera, Safari
window.addEventListener("mousewheel", MouseWheelHandler, false);
// nonstandard: Firefox
window.addEventListener("DOMMouseScroll", MouseWheelHandler, false);
})();
正如你在这个演示中看到的那样,我更喜欢尽可能少的缓动,只是为了避免生涩的滚动。阅读上面的评论并设计适合您项目的自己的滚动。
注意:鼠标滚轮也可以连接到触摸板,但不能连接到向上/向下键。您也应该考虑挂钩关键事件。
我没有太多时间,但我尝试动态编写(跨浏览器和脏)平滑滚动功能。当您停止滚动时,它会平稳减速。您可以稍微重写一下,使其符合您的需求。
在这里试一试:
平滑滚动:
function getScrollTop(){
if(typeof pageYOffset!= 'undefined'){
//most browsers except IE before #9
return pageYOffset;
} else {
var B = document.body; //IE 'quirks'
var D = document.documentElement; //IE with doctype
D = (D.clientHeight) ? D : B;
return D.scrollTop;
}
}
var timeouts = [];
var scrolling = false;
var scroller;
var scrollTop = getScrollTop();
var timeMs;
var alter = false;
var speed = 5;
window.onscroll = function() {
if(alter) {
var timeDif = new Date().getMilliseconds() - timeMs;
speed = 5 - (timeDif / 50);
console.log(speed);
}
timeMs = new Date().getMilliseconds();
alter = !alter;
var scrollDirection = getScrollTop() - scrollTop;
scrollDirection = scrollDirection / Math.abs(scrollDirection);
scrollTop = getScrollTop();
clearTimeout(scroller);
scroller = setTimeout(function(){
console.log('smooth scrolling active');
if(!scrolling) {
timeouts.length = 0;
scrolling = true;
var steps = 50;
var delay = 6;
for(var i = 0; i < steps; i++) {
(function(i){
var timeout = setTimeout(function(){
var perc = i / steps;
var val = (perc == 1) ? 1 : (-Math.pow(2, -10 * perc) + 1);
var scrollY = val * speed * scrollDirection;
window.scrollTo(0, getScrollTop() + scrollY);
setTimeout(function(){
if(i == (steps - 1)) scrolling = false;
}, steps * delay);
}, (i * delay));
timeouts.push(timeout);
})(i);
}
}
}, 50);
};
仅适用于 chrome 试试这个 - https://github.com/im4aLL/chromeSmoothScroll仅 1 KB
Simplr-SmoothScroll 有一个错误 - 当身体高度不是自动时,它不适用于身体。
我找到了另一个插件,它对我来说是完美的解决方案。 https://github.com/inuyaksa/jquery.nicescroll
下载库(演示)并添加到开头
// 1. Simple mode, it styles document scrollbar:
$(document).ready(function() {
$("body").niceScroll();
});
由于重绘和回流,基本上滚动会导致生涩。如果您可以检查并减少这些回流,您可能会获得滚动性能。
并检查 onScroll 事件回调函数是否执行任何昂贵的逻辑。并且是否有任何内存泄漏。
Chrome 开发者工具栏堆快照对于检测内存泄漏和查看重绘和重排非常有用。