2011-04-24 95 views
0

我有一個腳本,它在畫布上繪製了一堆線條,但是它非常強烈,所以渲染會在幾秒內凍結瀏覽器。我添加了setTimeout(),以便瀏覽器不會凍結,並且它有效地混淆了我的腳本。這是很難解釋如何,所以我有兩個在線的例子:遞歸函數和setTimeout()問題

沒有的setTimeout():http://www.modwebsolutions.com/test1

用的setTimeout():http://www.modwebsolutions.com/test2

注意,我只在整個腳本改變單一的線即線69:
而不的setTimeout():vLoop();
用的setTimeout():setTimeout(vLoop,1);

+0

你能告訴我們'vLoop'的實際代碼嗎 – Raynos 2011-04-24 13:31:05

回答

3

正如其他人暗示的那樣,這裏的問題在於,您一次只畫出一個象限。一旦SetTimeout方法被調用並且第一個vLoop返回,代碼將繼續運行到下一個將更改所有全局變量等的drawVertical

你需要做的是同步你如何調用vLoop以及你如何改變全局變量。

這是基本的解決方案:

 

替換...

drawVertical(c,-1*step,-1*stepInt,-1*bigStep,xStart,xEnd,y/2+50,y); 
drawVertical(c,step,stepInt,bigStep,xStart,xEnd,y/2+50,y); 
drawVertical(c,-1*step,-1*stepInt,-1*bigStep,xStart,xEnd,y/2-50,0); 
drawVertical(c,step,stepInt,bigStep,xStart,xEnd,y/2-50,0); 

...與...

var q = new Array(); 
q[0] = [c,-1*step,-1*stepInt,-1*bigStep,xStart,xEnd,y/2+50,y]; 
q[1] = [c,step,stepInt,bigStep,xStart,xEnd,y/2+50,y]; 
q[2] = [c,-1*step,-1*stepInt,-1*bigStep,xStart,xEnd,y/2-50,0]; 
q[3] = [c,step,stepInt,bigStep,xStart,xEnd,y/2-50,0]; 

drawQuadrant(q, 0); 

 

將您的drawVertical功能替換爲...

function drawQuadrant(q, i) 
{ 
    var r = q[i]; 

    c__ = r[0]; 
    step__ = r[1]; 
    stepInt__ = r[2]; 
    bigStep__ = r[3]; 
    xStart__ = r[4]; 
    xEnd__ = r[5]; 
    yStart__ = r[6]; 
    yEnd__ = r[7]; 


    vLoop(q,i); 
} 

 

變化vLoop函數原型看起來像這樣...

function vLoop(q,i) 

 

,最後用替換您的遞歸調用vLoop(從內VLOOP)。 ..

if ((xStart__ > 0) && (xStart__ < window.innerWidth)) 
{ 
    setTimeout(function(){vLoop(q,i)}, 1); 
} 
else if (++i < 4) 
{ 
    setTimeout(function(){drawQuadrant(q,i)}, 1); 
} 

最後一塊是確保象限沒有跨越彼此的地方。

0
drawVertical(c,-1*step,-1*stepInt,-1*bigStep,xStart,xEnd,y/2+50,y); 
drawVertical(c,step,stepInt,bigStep,xStart,xEnd,y/2+50,y); 
drawVertical(c,-1*step,-1*stepInt,-1*bigStep,xStart,xEnd,y/2-50,0); 
drawVertical(c,step,stepInt,bigStep,xStart,xEnd,y/2-50,0); 

您一次調用vLoop的4個遞歸函數。這裏的問題是setTimeout是非阻塞的,因爲遞歸被阻塞。所以基本上,你現在可以將所有4個drawVertical函數並行運行,而不是按順序運行。

另一個問題是,所有4引用和混亂的全局狀態,你的整個程序中斷。

+0

他們仍然是單線程的,所以說他們並行運行並不是很準確。 – 2011-04-24 13:37:40

+0

@NickCraver時間拼接執行是它們實際上並行運行。如何使用setTimeout與時間拼接不同? – Raynos 2011-04-24 13:56:20

+0

@Raynos - 你永遠不會在同一時間內多次使用該方法,這是平行的定義:) – 2011-04-24 14:19:05

0

發生了什麼是setTimeout()延遲全部該執行,直到後來。不幸的是,到那時,你的全局變量已經從初始循環移到了它們的結束位置,因爲它在繪製第一行之前完成了。

如果你動了你的超時進一步上漲,你可以實現你以後(讓你在使用不會受到影響,直到抽籤時間共享變量),例如:

setTimeout(function() { 
    drawVertical(c,-1*step,-1*stepInt,-1*bigStep,xStart,xEnd,y/2+50,y); 
    drawVertical(c,step,stepInt,bigStep,xStart,xEnd,y/2+50,y); 
    drawVertical(c,-1*step,-1*stepInt,-1*bigStep,xStart,xEnd,y/2-50,0); 
    drawVertical(c,step,stepInt,bigStep,xStart,xEnd,y/2-50,0); 
}); 

那麼這將工作(但它是危險的,訂單不是絕對的!)

You can see a working example here

+0

這只是延遲整個繪圖過程,直到後來。只要塊開始運行,您仍然有凍結瀏覽器的原始問題。 – musaul 2011-04-26 00:36:29

+0

@Musaul - 它會在一個定時回調中,但是你可以通過一個非0值的超時持續時間來減輕它的影響,例如把它乘以'i'。 – 2011-04-26 00:43:55