2013-11-02 37 views
0

我是一個非常初學的網頁設計師,我對這段代碼有兩個疑問。clearRect不工作?

<!DOCTYPE html> 
<html> 
<head> 
<style type="text/css"> 
#canvas1{border: #666 3px solid;} 
</style> 
<script type="application/javascript" language="javascript"> 
function draw (x,y){ 
var canvas = document.getElementById('canvas1'); 
var ctx = canvas.getContext('2d'); 
ctx.save(); 
ctx.clearRect(0, 0, canvas.width, canvas.height); 
ctx.fillstyle = "rgb (0,200, 0)"; 
ctx.fillRect(x, 20, 50, 50); 
ctx.restore(); 
x += 5; 
var loop = setTimeout('draw('+x+', '+y+')', 100); 
} 
</script> 
</head> 
<body> 
<button onclick="draw(0,0)">Start</button> 
<canvas id="canvas1" width="400" height="400"</canvas> 
</body> 
</html> 

爲什麼塊總是變黑?爲什麼如果我嘗試再次按下啓動鍵,clearRect功能不起作用?

+1

**永不**將字符串傳遞給'setInterval()'或'setTimeout()'。這樣做與使用'eval()'一樣糟糕,並且只要使用變量,就會導致不可讀和可能不安全的代碼,因爲您需要將它們插入到字符串中,而不是傳遞實際變量。正確的解決方案是'setInterval(function(){/ * your code *)},msecs);'。 'setTimeout()'同樣適用。如果你只想調用一個沒有任何參數的函數,你也可以直接傳遞函數名:'setInterval(someFunction,msecs);'(注意函數名後面有** no **'()') – ThiefMaster

+0

它調用一個函數,函數繪製。 – matt729

+1

你沒有明白我的觀點。而不是通過使用字符串連接嵌入變量的醜陋字符串,而應該傳遞一個實際函數:'setTimeout(function(){draw(x,y);},100);'或者如果您只需要支持現代瀏覽器: 'setTimeout(draw.bind(this,x,y),100);' – ThiefMaster

回答

0

當您單擊開始,你開始以平行於已經開始,這取決於一個哪一個先執行你的畫布將被清除,並填寫兩次新的環路(或你開始循環的次數越多 - 閃爍越明顯)。

您需要一種機制來防止循環多次啓動。一種方法是使用標誌。我也建議你重構代碼有點分離循環和繪圖:

Live demo here

/// put these outside, no need to re-allocate them each time 
var canvas = document.getElementById('canvas1'); 
var ctx = canvas.getContext('2d'); 
var w = canvas.width; 
var h = canvas.height; 
var x = 0; 
var isRunning = false; 

/// all loop-related here: 
function loop() { 

    /// call draw from inside the loop instead 
    draw(x, 0); /// you are never using y so I just set 0 here... 

    x += 5; 

    if (isRunning && x <= w) { 
     requestAnimationFrame(loop); /// this is a better alternative 
     //setTimeout(loop, 100);  /// optionally, but not recommended 
    } else { 
     isRunning = false; /// box is outside visible area so we'll stop.. 
    } 
} 

/// keep draw() "clean", no loop code in here: 
function draw(x, y) { 
    /// no need for save/restore here... 
    ctx.clearRect(0, 0, w, h); 
    ctx.fillStyle = "rgb(0, 200, 0)"; 
    ctx.fillRect(x, 20, 50, 50); 
} 

fillStyle被輸入錯了,你rgb(...必須是沒有空間(在其他答覆中提到 - 但這隻會導致填充樣式在這種情況下爲黑色),此外,您在HTML中缺少canvas標籤的右括號。

要檢查按鈕點擊,這是一個比較推薦的方式,而不是在HTML內聯JS:

/// check for button clicks (start): 
document.getElementById('start').addEventListener('click', function() { 

    if (!isRunning) {  /// are we running? if not start loop 
     isRunning = true; /// set flag so we can prevent multiple clicks 
     x = 0;   /// reset x 
     loop();   /// now we start the *loop* 
    } 

}, false); 

而在你的HTML:

<button id="start">Start</button> 

現在你可以很容易地做出暫停按鈕:

<button id="stop">Stop</button> 

,這增加了腳本:

document.getElementById('stop').addEventListener('click', function() { 

    isRunning = false; 

}, false); 
+0

謝謝!你的方式是非常有幫助的,但我不得不搜索一些東西,因爲我是一個非常新的HTML(一般的代碼)。 – matt729

0

因爲你需要使用:

ctx.fillStyle = "rgb(0,200,0)"; 

一個大寫的「S」和「RGB」和左括號之間沒有空格:http://jsfiddle.net/dtHjf/

然後,爲什麼按「開始」的條款多次會導致方塊閃爍,這是因爲每次按下它,您都會開始另一個動畫循環,但不會取消舊的循環,以便您有多個循環相互對抗。如果你確保你開始一個新的前取消任何預先存在的循環,你應該罰款:

http://jsfiddle.net/dtHjf/2/

HTML

<button id="startAnim">Start</button><br /> 
<canvas id="canvas1" width="400" height="400"></canvas> 

JS

var canvas = document.getElementById('canvas1'), 
    ctx = canvas.getContext('2d'), 
    loop; 

function draw(x, y) { 

    ctx.save(); 
    ctx.clearRect(0, 0, canvas.width, canvas.height); 
    ctx.fillStyle = "rgb(0,200,0)"; 
    ctx.fillRect(x, 20, 50, 50); 
    ctx.restore(); 

    x += 5; 
    loop = setTimeout(function(){draw(x,y)}, 100); 
} 

document.getElementById('startAnim').onclick = function(){ 
    clearTimeout(loop); 
    draw(0,0); 
}; 

另外,這與您的問題無關,但您可能需要OOK在​​:

https://developer.mozilla.org/en-US/docs/Web/API/window.requestAnimationFrame http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/

+0

你能告訴我爲什麼如果我再次按開始,廣場(矩形)閃爍?我認爲這是因爲clearRect不起作用,但你能告訴我如何解決它嗎? – matt729

+0

@ matt729是的,我已經添加到我的回答 – BYossarian

+0

謝謝!這也非常有幫助,而且更簡潔明瞭! – matt729