[英]How to force repaint in JS?
我想要達到的目標:
這是剝離的代碼:
<div id ="di" onclick="calc()">initial</div>
<script>
function calc()
{
var n,a=0;
document.getElementById('di').textContent="calculation in progress";
for(n=0;n<1000000000;n++) // Here's the time consuming calculation
{
a=a+n; // for clarity's sake, I removed a complicated math formula here
}
document.getElementById('di').textContent="done "+a;
}
</script>
當我運行它並單擊div時,它需要一段時間,然后將文本更改為“完成”,因此用戶根本看不到“計算進行中”消息-這是我的問題。
為了強制屏幕重新繪制以在計算開始之前顯示消息,其他線程建議修改CSS,隱藏並立即取消隱藏元素或使用setTimeout,但是沒有任何效果。
這將是一個繪制復雜數學對象(分形)的程序,我將使用canvas而不是div,但是我簡化了上面的示例。 由於將來會有圖形界面,因此不能選擇使用“ alert()”-計算完成后,“計算進行中”屏幕應立即變為“完成”。
IMO處理此問題的簡單方法是通過計時器函數以“較小”的塊執行計算,例如:
function calcFractal(x0, y0, x1, y1) {
... compute the fractal for the tile (x0, y0)-(x1, y1) ...
}
var x = 0, y = 0;
function nextTile() {
calcFractal(x, y, x+tw, y+th);
x += tw;
if (x >= width) {
x = 0;
y += th;
}
if (y < height) setTimeout(nextTile, 0);
}
nextTile();
這使您可以顯示進度(例如,包括分形的低分辨率,計算的百分比)並允許中斷(例如,帶有停止按鈕的onclick
事件)。
如果磁貼不是很小,那么開銷是可以接受的,仍然可以合理地響應重新繪制和用戶交互來保持頁面。
您需要等待一毫秒或與Worker進行計算。
第一個示例可能是最簡單的,而不是直接調用calc
,而是創建一個新函數
function caller() {
// insert "calculation in progress" in the body
setTimeout(calc, 1);
}
然后呼叫caller
。
由於現代瀏覽器可能會延遲重新繪制以獲得更好的幀速率,因此帶有setTimeout
版本可能無法在太低的超時時間內工作。
如果可能,您需要使用requestAnimationFrame 。 如果它不可能,那么@Bálint答案應該可以工作,但是超時時間要大得多(在Firefox中我的測試中,它的工作時間是20-30附近)。 實際超時值取決於瀏覽器(可能也取決於系統)
function very_long_func(){
el= document.getElementById('di');
requestAnimationFrame( function(){
//edit dom for new frame;
el.textContent = 'calculation in progress'
//browser will wait for this functions end, before start redraw.
//So actual calucation must run outside of it
setTimeout( function_with_actual_calculation, 1 );
})
}
function function_with_actual_calculation(){
//..your math here + updating textContent to "done" in the end.
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.