“onscroll”在重绘之后还是之前触发?

Posted

技术标签:

【中文标题】“onscroll”在重绘之后还是之前触发?【英文标题】:"onscroll" fired after or before repaint? 【发布时间】:2014-03-16 19:21:33 【问题描述】:

我在 div 元素上有一个滚动条。

在许多浏览器上(我在 MacOS 和 Linux 上的最新版本的 Chrome 和 Firefox 上对此进行了测试),似乎浏览器确保在滚动重绘触发之前调用绑定到 onscroll 的代码。

换句话说,以下小提琴在滚动http://jsfiddle.net/m2E65/1/时不会闪烁也不闪烁:

var onscroll = function() 
    var y = $("#container").scrollTop() + 30;
    var z = 0
    for (var c=0; c<y*10000; c++) 
        z+=c;
    
    $("#label").text("bocal : "+z);
    $("#label").css("top", y);
;
$('#container').scroll(onscroll);

但是在 Ubuntu 上的 Linux Chromium v​​28 上,它确实会闪烁。几乎就像我们使用 setTimeout (http://jsfiddle.net/m2E65/2/) 推迟 onscroll 一样糟糕:

$('#container').scroll(function() 
    window.setTimeout(onscroll, 0);
);

在同一个浏览器上,即使使用http://jsfiddle.net/m2E65/4/ 中的 requestAnimationFrame 也会同样严重闪烁(见下文)

var onscroll = function() 
    var y = $("#container").scrollTop() + 30;
    var z = 0
    for (var c=0; c<y*10000; c++) 
        z+=c;
    
    $("#label").text("bocal : "+z);
    $("#label").css("top", y);
    window.requestAnimationFrame(onscroll);
;
window.requestAnimationFrame(onscroll);

我的问题是:

有这方面的规范吗? 有没有办法确保在所有浏览器上,代码都会在重绘之前运行? 奖励点:这种行为有多罕见?

【问题讨论】:

在ubuntu下其他网站看到这个闪烁了吗?这可能是您的显卡的垂直同步问题? 通过闪烁,我的意思是我有时会看到文本在不同的地方出现 1 帧(如果我上升,则会降低)。我不认为显卡在这里有问题。也许是 Wayland + 铬的组合? 如果有人给我一个指向任何类型规范的指针,我很高兴...我找不到任何说明 onscroll / paint 应该如何交互的内容。 【参考方案1】:

1。出自Document Object Model (DOM) Level 3 Events SpecificationW3C 文档:

用户代理必须在文档视图或 元素已滚动。此事件类型在 之后调度 发生滚动。

我对这两句话的解释是,浏览器必须在滚动过程完成包容性重绘后调度scroll事件。

2。我认为没有办法确保在所有浏览器上,代码都会在重绘之前触发。也许您可以尝试捕捉用户可以滚动的所有方式,我想到的是自发的:

鼠标滚轮 -> wheel 事件 通过选择文本-> mousedown 使用滚动条 -> 你可以只希望mousedown 会触发。

3。你的第一把小提琴在我面前闪烁:

Safari 7.0.1 ios 7 上的 Safari 正如你在 Ubuntu 上的 Chrominum 中所说的

它不闪烁:

Firefox 27.0 Mac 和 Ubuntu Opera 19.0 Mac 铬

现在它认为特别是 WebKit 浏览器(Chrome 除外)在调用 scrollevent 之前不会重新绘制,并且没有防止这种情况的好方法。

【讨论】:

非常感谢您在这些浏览器上进行测试! 对于遇到此问题的其他人:我发现解决此问题的唯一可靠方法是在容器上使用溢出隐藏,并使用另一组滚动条。最后,javascript 做了必要的粘合来滚动原始容器的内容。

以上是关于“onscroll”在重绘之后还是之前触发?的主要内容,如果未能解决你的问题,请参考以下文章

UITableViewCell 子视图在重绘之前不显示

Today Extension 视图在重绘时闪烁

TabView 在重绘时是不是会错过导航点击?

SwiftUI:ObservableObject 在重绘时不会保持其状态

重命名时Oracle 12C审核触发器

React ChartJS 防止新数据在重绘后被添加到状态中?