如何在 WebKit 1.2.5 中使用 JavaScript 强制重新布局?

4
我尝试了所有应该触发重排的方法,但没有效果。我调用我的测试函数10次,在我的屏幕上绘制一些元素并将该元素移动到每个迭代中。该循环被立即执行,最后我只得到一张图片,而不是在屏幕上看到元素的移动。

好像在所有的工作完成后才触发重排和屏幕绘制。但是我想要看到每一个绘画过程。

我尝试的所有方法都没有效果。唯一有效的方法是alert(),但我不需要与用户进行交互。

如果有必要,我正在使用webkit 1.2.5。

如果我表述不清楚,我会尽力解释。

这是我正在强制重排的代码:

 var i = 0;
 for(;i<500;i+=50){
fTestInfo(i);
console.log("Test loop!!! "+i);
 }

每次执行fTestInfo(i)时,我需要在屏幕上看到一张图片,但实际上,我只能看到最终结果。fTestInfo函数的执行结果受变量i影响,它会将i向左移动。

你确定你不是在眨眼间就把所有东西都动画化了吗?此外,如果没有一些示例代码,我们有点摸不着头脑。 - TheZ
2个回答

1

我看到你正在使用for循环,这通常意味着你误解了计时器的工作原理。for循环是同步执行的,你可能会一次性设置所有的计时器。

试试这个:

(function loop(i) {
    if (i >= 500) {
        return;
    }
    document.querySelector("div").style.left = i + "px";
    setTimeout(function() {
        loop(i + 1);
    }, 16);
})(0);

演示 http://jsfiddle.net/UCfmF/


我想你是指获取像.offsetWidth这样的值吗?这并不能保证在屏幕上进行可见的回流,即使您正在执行触发回流的操作,浏览器可能会等待一段时间(即:直到JavaScript执行停止)才实际尝试在屏幕上绘制任何内容。

这意味着,如果您将1000个元素附加到文档中,它不会触发1000次回流。即使您在每次迭代之间获取.offsetWidth。它只会为您计算,但不一定会被绘制。

您需要使用计时器移动元素,因为JavaScript执行结束时,浏览器会清除任何排队的回流。

请参见http://dev.opera.com/articles/view/efficient-javascript/?page=3#reflow

如前所述,浏览器可能会为您缓存多个更改,并在所有更改完成后仅重新布局一次。但是,请注意,对元素进行测量将强制其重新布局,以便测量结果正确。这些更改可能或可能不会被可见地重绘,但是重新布局本身仍然必须在幕后发生。

我编辑了原始帖子。我知道重排是如何工作的,我知道我可能会有1000个元素,但只能执行一次重排。我尝试使用计时器,在该日志和函数之间放置它,但最终只是等待更长时间,结果相同。是否有一些不可见的事件可以引发,强制重新排列和绘制? - Shakal187
@Shakal187请展示你的代码,目前你只是在循环而不是使用时间间隔。 - Esailija
我在将这个实现到我的代码中遇到了问题。在函数loop(i)之前需要那个括号吗?我在JavaScript方面真的是个新手。 - Shakal187
@Shakal187 是的,你需要我所有的东西,除了返回条件可能不同、超时值和div的操作。 - Esailija
@Shakal187 不确定你的意思是什么。更快怎么做? - Esailija
显示剩余4条评论

0
你需要在每次迭代之间给浏览器进入其事件循环的机会。
使用setTimeout来安排绘图的每个迭代:
function scheduledTestInfo(i) {
    setTimeout(function() {
        fTestInfo(i);
    }, i);  // calls each function 50ms apart
}

var i = 0;
for ( ; i < 500 ; i += 50) {
    scheduledTestInfo(i);
}

请注意,如果i的值每次增加少于13,则此方法将无法正常工作。而且,同时创建多个超时而不是链接它们仍然很丑陋,这是我的个人看法:P - Esailija
是的,我知道。最好不要在时差8小时的情况下尝试编码 :( - Alnitak

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接