我尝试不重复造轮子,使用现有的滚动脚本,但是我发现所有的脚本都使用jQuery(我不想将代码弄乱),而且没有支持按键和滚动div的功能……都不够好。
我使用的操作系统是Windows 7:Opera和Chrome的滚动不够顺畅,所以我写了代码来提供顺畅的滚动体验。然而,在默认已经具备顺滑滚动功能的Explorer 11中,我的脚本会导致过度敏感。我的朋友在Mac OS上运行Chrome时告诉我那里的滚动也很流畅。
我想我的问题可以通过浏览器x操作系统列表来回答,这些浏览器需要JavaScript滚动增强(我不能访问所有浏览器),或者通过改进我的代码来避免在不需要增强的浏览器下出现丑陋的行为。
所需功能包括:
- 无需jQuery
- 平滑的上/下键滚动
- 滚动div,不仅限于主窗口
- 无需jQuery(这对我很重要,因此我提到了两次)
- 无MooTools、无框架,只使用原生JS(也许可以接受Modernizr或其他简洁的工具)
任何关于代码的建议也将不胜感激(我知道我应该尽快使用requestAnimationFrame)
目前,我的代码如下:
// easeOutQuad by Robert Penner
Math.easeOut = 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
keyDelta = 0;
function KeyWheelHandler(e) {
if(e.which!=38 && e.which!=40) return;
keyDelta = e.which==38 ? -1 : 1;
mult = 4;
MouseWheelHandler(e);
}
function MouseWheelHandler(e) {
e.preventDefault(); // prevent default browser scroll
clearInterval(interval); // cancel previous animation
++mult; // we are going to scroll faster
var delta = keyDelta || -Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail)));
if(dir!=delta) { // scroll direction changed
if(!keyDelta) mult = 1; // start slowly
dir = delta;
}
// get the closest scrollable parent
for(var tgt=e.target; tgt!=document.documentElement; tgt=tgt.parentNode) {
var oldScroll = tgt.scrollTop;
tgt.scrollTop+= delta;
if(oldScroll!=tgt.scrollTop) break;
}
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 = 2; // current step, not less than 2, see the (t-2) in EaseOut
interval = setInterval(function() {
var pos = Math.easeOut(step++,start,change,steps);
tgt.scrollTop = pos;
if(step>=steps) { // scroll finished without speed up - stop
mult = keyDelta = 0;
clearInterval(interval);
}
},15);
}
if(window.chrome) { // Opera and Chrome
window.addEventListener("mousewheel", MouseWheelHandler);
//window.addEventListener("DOMMouseScroll", MouseWheelHandler); // FF
document.documentElement.addEventListener("keydown", KeyWheelHandler);
}
})();
wheel
事件用作默认事件,因为它是现代跨浏览器版本。顺便说一下,看起来你没有在监听器中传递事件,因此使用该部分的函数将无法工作。 - Shikkedielwindow.addEventListener("mousewheel", MouseWheelHandler);
- ShikkedielMouseWheelHandler
函数本身像其他函数一样需要将e
作为参数传入... - Shikkediele
是通过系统调用传递的(除了旧版的 Explorer)。如果我漏掉了什么,请在代码中用注释回答。如果您有更好的解决方案,可以在这里回答,最好附上权威参考链接。 - Jan Turoň