使用javascript按需强制DOM重绘

问题的标题表达了我认为是我的具体案例背后的最终问题。

我的情况:在一个点击处理程序中,我想在繁忙的函数开始之前使图像可见(一个’加载’动画)。 然后我想在函数完成后再次使它不可见。 而不是我所期望的,我意识到图像永远不会变得可见。 我猜这是由于浏览器等待处理程序结束,然后才能进行任何重绘(我确信有很好的性能原因)。

代码(也在这个小提琴: http : //jsfiddle.net/JLmh4/2/ )

HTML:

  

JS:

 $(document).ready(function(){ $('#enlace').click(function(){ var kitty = $('#kitty'); kitty.css('display','block'); // see: http://unixpapa.com/js/sleep.html function sleepStupidly(usec) { var endtime= new Date().getTime() + usec; while (new Date().getTime() < endtime) ; } // simulates bussy proccess, calling some function... sleepStupidly(4000); // when this triggers the img style do refresh! // but not before alert('now you do see it'); kitty.css('display','none'); }); }); 

我已经在sleepStupidly函数之后添加了alert调用,以显示在那个rest时刻,浏览器会重绘,但之前不会重绘。 我无辜地期望在将’display’设置为’block’后重新绘制;

为了记录,我还尝试附加html标签,或交换css类,而不是显示和隐藏在此代码中的图像。 结果相同。

经过我所有的研究后,我认为我需要的是能够强制浏览器重绘并停止其他所有事情。

可能吗? 是否有可能以交叉浏览器的方式进行? 有些插件我找不到也许……?

我认为这可能类似’jquery css callback’(在这个问题中: 在JQuery中,是否有可能在设置新的css规则后获得回调函数? )会做到这一点……但这不存在。

我也尝试分离显示,函数调用和隐藏在同一事件的不同处理程序中……但没有。 还添加了一个setTimeout来延迟函数的执行(这里推荐: 在JavaScript中强制DOM刷新 )。

谢谢,我希望它也能帮助别人。

哈维尔

编辑(设置我的首选答案后):

只是为了进一步解释为什么我选择了window.setTimeout策略。 在我的实际用例中,我已经意识到为了给浏览器足够的时间来重绘页面,我不得不给它大约1000毫秒(比小提琴示例的50多)。 我相信这是由于更深层次的DOM树(实际上是不必要的深层)。 setTimeout let方法允许您这样做。

使用window.setTimeout()以及一些短暂无法察觉的延迟来运行慢速函数:

 $(document).ready(function() { $('#enlace').click(function() { showImage(); window.setTimeout(function() { sleepStupidly(4000); alert('now you do see it'); hideImage(); }, 50); }); }); 

现场演示

使用JQuery showhide回调(或以其他方式显示fadeIn / fadeOut之类的东西)。

http://jsfiddle.net/JLmh4/3/

 $(document).ready(function () { $('#enlace').click(function () { var kitty = $('#kitty'); // see: http://unixpapa.com/js/sleep.html function sleepStupidly(usec) { var endtime = new Date().getTime() + usec; while (new Date().getTime() < endtime); } kitty.show(function () { // simulates bussy proccess, calling some function... sleepStupidly(4000); // when this triggers the img style do refresh! // but not before alert('now you do see it'); kitty.hide(); }); }); }); 

要强制重绘,可以使用offsetHeight或getComputedStyle()。

 var foo = window.getComputedStyle(el, null); 

要么

 var bar = el.offsetHeight; 

“el”是DOM元素

我不知道这是否适用于您的情况(因为我没有测试过),但是当使用JavaScript / jQuery操作CSS时,有时需要强制重绘特定元素以使更改生效。

这是通过简单地请求CSS属性来完成的。

在你的情况下,我会尝试放一个kitty.position().left; 在搞乱setTimeout之前的函数调用之前。

对我有用的是设置以下内容:

 $(element).css('display','none'); 

之后你可以做任何你想做的事,最终你想做:

 $(element).css('display','block');