【问题标题】:Smooth scrolling cross-browser平滑滚动跨浏览器
【发布时间】:2015-12-07 21:45:01
【问题描述】:

我尝试不通过编写自己的 scolling 脚本来重新发明轮子,但我发现的所有内容都使用了 jQuery(我不想用它弄乱我的代码),不工作,不支持键滚动或 div滚动...什么都不够好。

我在 Windows 7 上运行:Opera 和 Chrome 滚动不流畅,因此我编写了可提供流畅滚动体验的代码。然而,在默认情况下具有平滑滚动的 Explorer 11 中,我的脚本使它变得非常敏感。我在 Mac OS 上运行 Chrome 的朋友告诉我,那里的滚动也很流畅。

我想我的问题可以通过需要 javascript 滚动增强的浏览器 x 操作系统列表来回答(我无法访问所有内容),或者通过改进我的代码以避免在不需要增强的浏览器下出现丑陋的行为。

必需的功能是

  • 没有 jQuery
  • 平滑向上/向下键滚动
  • 滚动 div,不仅仅是主窗口
  • 没有 jQuery(这对我很重要,所以我提到了两次)
  • 没有 MooTools,没有框架,只有原生 JS(perharps 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 事件作为默认值,它是现代跨浏览器版本。顺便说一句,您似乎没有在侦听器中传递事件,因此使用该事件的部分函数将不起作用。
  • 没有通过活动?你能具体说一下在哪里吗?
  • window.addEventListener("mousewheel", MouseWheelHandler);
  • MouseWheelHandler 函数本身将 e 作为参数,与其他函数一样...
  • 当然,e 是通过系统调用传递的(旧的 Explorer 除外)。如果我遗漏了什么,请在代码中用 cmets 回答。如果您有更好的解决方案,您可能想回答here,最好带有权威参考的链接。

标签: javascript scroll


【解决方案1】:

看起来在未来(截至 2015 年)css smooth-scroll 会解决这个问题:

滚动框使用用户代理定义的计时功能在用户代理定义的时间段内平滑滚动。用户代理应遵循平台约定(如果有)。

用户代理可能会忽略此属性。 (???)

关于忽略的注释可能是浏览器mostly ignore this,但Chrome work's on it 的原因,所以我希望Opera 稍后也会实现它。

最新版本的IE、FF和Safari好像默认到处都是流畅滚动的,所以这个问题可以等待解决。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    • 1970-01-01
    相关资源
    最近更新 更多