DOM 元素在滚动时位置缓慢 + 滚动条滚动和鼠标/触摸板滚动之间的差异 [英] DOM element position slow while scrolling + difference between scrollbar-scrolling and mouse/touchpad-scrolling

查看:44
本文介绍了DOM 元素在滚动时位置缓慢 + 滚动条滚动和鼠标/触摸板滚动之间的差异的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在使用 Safari 时遇到了一个小问题 - 当我想在滚动事件上更新 DOM 元素的位置时,Safari 似乎没有跟上变化(导致跳跃延迟效果).我在其他浏览器(Chrome、FF、IE8+)上检查过,这似乎是 Safari 特有的.

I'm having a little problem with Safari - When i want to update a DOM element's position on scroll event, Safari seems not to catch up with the changes (resulting in a jumpy lag effect). I checked it on other browsers (Chrome, FF, IE8+) and this seems to be specific to Safari.

我做了一个 jsfiddle 来说明我的问题:

$("#container").on("scroll", function() {
    $("#slide").css({
        left: $("#container").scrollLeft() + "px"
    });
    
    var leftPos = 0;
    for(var i = 0; i < 2000 ; i++) {
        leftPos = $("#slide").css("left");
    }  
    $("#info").text(leftPos); 
});

http://jsfiddle.net/a4b86et3/2/

如您所见,我在每个滚动条上添加了一个额外的 DOM 读取循环,以模拟正在进行的更多操作".在每个事件发生时,因为此机制是包含许多其他 DOM 操作的更大项目的一部分.(请注意,此示例在除 Safari 之外的所有地方都运行顺畅)

As you can see, I added an additional loop of DOM reading on each scroll to simulate "more operations going on" on each event occurrence, as this mechanism is a part of a bigger project, which contains many other DOM operations. (Notice, that this example works smooth everywhere except Safari)

另外,我使用jQuery只是为了方便,实际项目使用纯js.

Also, i used jQuery just for the convenience, the actual project uses pure js.

通过将 left = x 属性更改为 transform = translate3d(x,0,0),浏览器将使用 GPU.

by changing the left = x property to transform = translate3d(x,0,0), so the browser would use the GPU.

$("#container").on("scroll", function() {
    $("#slide").css({
        '-webkit-transform': 'translate3d(' + $("#container").scrollLeft() + 'px, 0, 0)'
    });
    
    var leftPos = 0;
    for(var i = 0; i < 1900 ; i++) {
        leftPos = $("#slide").css("left");
    }  
    $("#info").text(leftPos);
    
});

http://jsfiddle.net/a4b86et3/3/

但是,有时我在滚动时仍然会遇到轻微的延迟/故障.

However, sometimes I'm still experiencing a slight lag/glitching while scrolling.

但是,更重要的是,当我使用鼠标滚动或触摸板时,此修复不会影响滚动!虽然拖动滚动条效果更好,但使用上述任何一种方法都会让我回到最初的问题.

But, what's more important, this fix doesn't affect the scrolling, when I'm using a mouse scroll or touchpad! While dragging the scrollbar works way better, using any of the above brings me back to my initial problem.

任何想法为什么会发生这种情况以及如何解决它?

Any ideas why this happens and how to fix it?

tl;dr;- Safari 在滚动时更改元素位置时速度很慢;使用鼠标滚动/触摸板时,translate3d 似乎无法正常工作.

推荐答案

我遇到了完全相同的问题,我花了一些时间才找到解决办法.这是一个更新的 jsfiddle,向您展示了如何解决 Safari 中的问题:http://jsfiddle.net/a4b86et3/4/

I had the exact same issue, and it took me some time to figure out the fix. Here is an updated jsfiddle showing you how to resolve the issue in Safari: http://jsfiddle.net/a4b86et3/4/

function handle_scroll() {
  $("#slide").css({
    '-webkit-transform': 'translate3d(' + $("#container").scrollLeft() + 'px, 0, 0)'
  });

  var leftPos = 0;
  for(var i = 0; i < 1900 ; i++) {
    leftPos = $("#slide").css("left");
  }  
  $("#info").text(leftPos);
}

$("#container").on("scroll", handle_scroll);
$("#container").on('mousewheel', function(e) {
  e.preventDefault()

  var maxX = this.scrollWidth  - this.offsetWidth
  var maxY = this.scrollHeight - this.offsetHeight
  this.scrollTop  = Math.max(0, Math.min(maxY, this.scrollTop  - e.originalEvent.wheelDeltaY))
  this.scrollLeft = Math.max(0, Math.min(maxX, this.scrollLeft + e.originalEvent.wheelDeltaX))

  handle_scroll(e)
})

简而言之:如果您自己处理 mousewheel 事件,在那里计算正确的滚动值,然后调用您的处理程序代码,事情就会开始工作.

In brief: if you handle the mousewheel event yourself, calculate the correct scroll values there, and then call your handler code, things start working.

我不知道为什么 Safari 会让你跳过这个圈套,但幸运的是修复并没有太复杂.

I'm not sure why Safari makes you jump through this hoop, but luckily the fix isn't too involved.

希望这会有所帮助.

这篇关于DOM 元素在滚动时位置缓慢 + 滚动条滚动和鼠标/触摸板滚动之间的差异的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆