2016-05-31 100 views
1

我畫了一些矩形,然後擦除並重畫它們以模擬右邊的移動 。然而,畫布抗鋸齒使他們留下痕跡,我不想重畫整個畫布。 Here's what I'm talking about如何撤消畫布反鋸齒?

這裏是該代碼:

var canvas = document.getElementById("canvas"); 
canvas.width = 800; 
canvas.height = 600; 
var context = canvas.getContext("2d"); 
maxFps = 15; 


function loop(x) { 
    setTimeout(function() { 
     undoRect(x); 
     drawRect(x + 30); 
     loop(x + 30); 
    }, 1000/maxFps); 
}; 


function undoRect(x) { 
    context.clearRect(x, 0, 30, 30); 
}; 


function drawRect(x) { 
    context.fillStyle = 'black'; 
    context.fillRect(x, 0, 30, 30); 
}; 

loop(0); 

到目前爲止,我試圖清除比我畫一個更大的矩形,但似乎並沒有工作。

+0

我沒試過你的代碼,但是從只有快速閱讀,你似乎只是清楚你在最後一幀畫的位置。你爲什麼不清除整個畫布? – Kaiido

+0

@Kaiido,有時候,畫布教程過分強調清除畫布最小「髒」部分的性能優勢。 – markE

+0

@markE,因爲清除整個畫布並不意味着(同樣多)反鋸齒計算,我不知道是否有任何性能優勢,而且我也不確定是否應該讓提問者在這裏遵循這些方法,我的意思是,大多數教程都是由讀過SO Q/A的人編寫的;-) – Kaiido

回答

0

Here's why that's happening.

以下是如何解決這個問題:

var canvas = document.getElementById("canvas"); 
 
canvas.width = 800; 
 
canvas.height = 600; 
 

 
var context = canvas.getContext("2d"); 
 
maxFps = 15; 
 

 

 
function loop(x) { 
 
    setTimeout(function() { 
 
    undoRect(x); 
 
    drawRect(x + 30); 
 
    loop(x + 30); 
 
    }, 1000/maxFps); 
 
}; 
 

 

 
function undoRect(x) { 
 
    context.clearRect(x, 0, 30, 30); 
 
}; 
 

 

 
function drawRect(x) { 
 
    context.fillStyle = 'black'; 
 
    context.fillRect(x, 0, 30, 30); 
 
}; 
 

 
loop(0.5); // boop
<canvas id="canvas"></canvas>

通過0.5px抵消你的矩形。

+0

這似乎並不奏效。 –

+0

@MetaXenology適合我。你使用的是什麼瀏覽器? –

+0

鉻。儘管如此,它也會在Firefox上留下痕跡。 –

0

不幸的是,在畫布上繪圖時,沒有可移植的方式來關閉消除鋸齒功能。例如,如果要繪製兩個共享邊的半透明多邊形,可能會產生問題,因爲邊界像素將無法正確處理(在每個基元的基礎上進行工作時,無法正確進行抗鋸齒......完全正確抗鋸齒在一般情況下需要全場處理)。

但是,如果您只需要繪製矩形,則可以通過使用座標來獲得像素精確的結果,例如在使用大小爲1px的筆進行繪製時,該座標爲int + 0.5

當繪製填充rects與fillRect座標不需要調整:

<!DOCTYPE html> 
 
<html> 
 

 
<body> 
 
    <canvas id="canvas"></canvas> 
 
    <script> 
 
    var x = 0; 
 
    setInterval(function() { 
 
     var canvas = document.getElementById("canvas"); 
 
     var ctx = canvas.getContext("2d"); 
 
     ctx.clearRect(x, 0, 30, 30); 
 
     x += 10; 
 
     ctx.fillStyle = "#F00"; 
 
     ctx.fillRect(x, 0, 30, 30); 
 
    }, 100); 
 
    </script> 
 
</body> 
 

 
</html>

另一種選擇是隻使用多個重疊畫布動畫代替繪圖/擦除一個畫布上(畫布像素默認是透明的,畫布上的每原始反鋸齒正確更新邊緣的透明度)。

+0

@帕特里克羅伯特的答案使用0.5技巧,但似乎沒有工作。你有解釋嗎?使用大小爲1px的筆畫出水平或垂直線時,需要使用 –

+1

+0.5。 'fillRect'不需要調整。 – 6502

2

顯示的代碼沒有問題。 fillRect()clearRect()不需要抵消以避免被消除鋸齒。

該問題表明在程序的早期版本中已應用偏移量,或者瀏覽器存在當前問題。

確保變換運行循環之前復位:如下圖所示然而

ctx.setTransform(1,0,0,1,0,0); // identity matrix 
// start loop 

如果仍然出現問題,那麼你應該報告此爲鉻/ Mozilla瀏覽器中的錯誤,這是不是一個問題在更新的版本中。您也可以考慮清除邊界框每個方向+1像素,可選地,清除整個畫布並重繪。

這裏是屏幕記錄結果(點擊圖片看100%) -

火狐(V47。0b9)

Firefox

鉻(V52金絲雀)

Chrome

無道(fiddle for test