2013-06-01 82 views
8

問題的標題表達了我認爲是我的特殊情況背後的最終問題。強制DOM按照需求重繪javascript

我的情況: 在點擊處理程序中,我想在忙功能啓動之前使圖像可見(「加載」動畫)。然後我想在功能完成後再次隱藏它。 而不是我所期望的,我意識到圖像永遠不會變得可見。我猜這是由於瀏覽器等待處理程序結束,因爲它可以進行任何重繪(我相信這有很好的性能原因)。

代碼(在本小提琴:http://jsfiddle.net/JLmh4/2/

HTML:

<img id="kitty" src="http://placekitten.com/50/50" style="display:none"> 
<div><a href="#" id="enlace">click to see the cat</a> </div> 

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'); 
    }); 
}); 

我已經加入了alert調用右後sleepStupidly功能表明,在那個休息的時刻,瀏覽器會重繪,但不會在之前。我無意中想到在將'display'設置爲'block'之後,它會重新繪製;

爲了記錄,我也嘗試追加html標記或交換css類,而不是顯示和隱藏在此代碼中的圖像。同樣的結果。

畢竟我的研究我認爲我需要的是能力強制瀏覽器重繪並停止其他所有事情,直到那時。

可能嗎?是否可以採用交叉瀏覽器的方式?有些插件我無法找到...?

我想,也許像'jQuery的css回調'(如在這個問題:In JQuery, Is it possible to get callback function after setting new css rule?)會做的伎倆......但不存在。

我也嘗試在同一事件的不同處理程序中分隔顯示,函數調用和隱藏...但沒有任何結果。還要加入一個setTimeout來延遲功能的執行(這裏推薦:Force DOM refresh in JavaScript)。

謝謝,我希望它也能幫助別人。

哈維爾

EDIT(設置我的首選答案後):

只是爲了進一步解釋爲什麼我選擇了window.setTimeout策略。 在我的真實使用案例中,我意識到爲了給瀏覽器足夠的時間來重新繪製頁面,我必須給它大約1000毫秒(遠遠超過小提琴示例中的50)。我相信這是由於更深的DOM樹(事實上,不必要的深度)。 setTimeout讓方法讓你這樣做。

+1

'window.setTimeout()'沒有幫助嗎? –

+0

不應該需要使用更長的超時延遲。您需要的可能只是預加載圖像以便能夠立即顯示。 –

+0

我明白了。但我明白,如果圖像不是從瀏覽器開始加載的(這是合理的,因爲它是'display:none',我猜)。事實並非如此,至少在chrome開始時會加載圖像(用開發人員工具查看)。我仍然認爲是由於我正在使用的遺留標記(很多嵌入表,真的......不依賴於我!)。實際上firefox會更好(需要更少的時間)......它有道理嗎?再次感謝。問候 – javigzz

回答

5

使用window.setTimeout()一些短不易察覺的延遲運行緩慢功能:

$(document).ready(function() { 
    $('#enlace').click(function() { 
     showImage(); 

     window.setTimeout(function() { 
      sleepStupidly(4000); 
      alert('now you do see it'); 
      hideImage(); 
     }, 50); 
    }); 
}); 

Live demo

7

使用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(); 
     }); 
    }); 
}); 
+0

感謝您的答案,這也適用於我建議的情況。這就是爲什麼我也贊成你(希望不違反規則!)。我選擇了Marat的答案,因爲它更適合我的'真實案例',這有點複雜。因此我認爲更一般。問候 – javigzz

0

我不知道這是否在你的情況(因爲我有沒有對它進行測試),但是當使用JavaScript/jQuery操作CSS時,有時需要強制重畫一個特定的元素來製作更改生效。

這是通過簡單地請求一個CSS屬性來完成的。

在你的情況下,我會嘗試在調用setTimeout之前函數調用之前放kitty.position().left;

1

要強制重繪,可以使用offsetHeight或getComputedStyle()。

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

var bar = el.offsetHeight; 

「厄爾尼諾」 是一個DOM元素

0

什麼工作對我來說是設置如下:

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

之後,你可以做任何你想做,並最終你想要這樣做:

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