簡體   English   中英

刪除HTML5畫布上以前繪制的線條

[英]Erasing previously drawn lines on an HTML5 canvas

為了使用HTML5畫布,我決定制作一個繪制模擬表盤的應用程序。 一切都很好,除了舊的線條沒有像我期望的那樣被抹去。 我已經包含了下面的部分代碼 - DrawHands()每秒調用一次:

var hoursPoint = new Object();
var minutesPoint = new Object();
var secondsPoint = new Object();

function drawHands()
{
    var now = new Date();

    drawLine(centerX, centerY, secondsPoint.X, secondsPoint.Y, "white", 1);
    var seconds = now.getSeconds();
    secondsPoint = getOtherEndOfLine(centerX, centerY, 2 * Math.PI / 60 * seconds, 0.75 * radius);
    drawLine(centerX, centerY, secondsPoint.X, secondsPoint.Y, "black", 1);

    drawLine(centerX, centerY, minutesPoint.X, minutesPoint.Y, "white", 3);
    var minutes = now.getMinutes();
    minutesPoint = getOtherEndOfLine(centerX, centerY, 2 * Math.PI / 60 * minutes, 0.75 * radius);
    drawLine(centerX, centerY, minutesPoint.X, minutesPoint.Y, "black", 3);

    drawLine(centerX, centerY, hoursPoint.X, hoursPoint.Y, "white", 3);
    var hours = now.getHours();
    if (hours >= 12) { hours -= 12; } // Hours are 0-11
    hoursPoint = getOtherEndOfLine(centerX, centerY, (2 * Math.PI / 12 * hours) + (2 * Math.PI / 12 / 60 * minutes), 0.6 * radius);
    drawLine(centerX, centerY, hoursPoint.X, hoursPoint.Y, "black", 3);
}

為了理解上述內容,有兩個輔助函數:

  • drawLine(x1,y1,x2,y2,顏色,厚度)
  • getOtherEndOfLine(x,y,angle,length)

問題在於,雖然所有的手都按照預期的黑色繪制,但它們永遠不會被刪除。 我希望由於相同的線條以白色(背景顏色)繪制,因此它將有效地擦除之前在該點繪制的內容。 但事實似乎並非如此。

我缺少什么?

由於我可以擴展的原因,你應該考慮清除畫布並重新繪制它,除非有性能或合成的原因不這樣做。

你想要clearRect ,像這樣:

//clear the canvas so we can draw a fresh clock
ctx.clearRect(0, 0, canvasWidth, canvasHeight);

//redraw your clock here
/* ... */

而不是刪除你不想要的東西,你可以:

  1. 保存畫布的狀態
  2. 畫出你不想要的東西
  3. 將畫布恢復到已保存狀態以“擦除”它們

使用ImageData可以非常輕松地完成此操作:

 var canvas = document.querySelector('canvas'), context = canvas.getContext('2d'); context.fillStyle = 'blue'; context.fillRect(0,0,200,200); // save the state of the canvas here var imageData = context.getImageData(0,0,canvas.width,canvas.height); // draw a red rectangle that we'll get rid of in a second context.fillStyle = 'red'; context.fillRect(50,50,100,100); setTimeout(function () { // return the canvas to the state right after we drew the blue rect context.putImageData(imageData, 0, 0); }, 1000); 
 <canvas width=200 height=200> 

你不能只用白色重繪線並希望它擦除舊線的原因是因為可能存在一些抗鋸齒/出血。 您還會注意到,由於此原因,在像素上繪制的直線水平線與半像素相比看起來非常不同。

當你做你的白色“擦除”行,試圖用一個更大的畫他們lineWidth約3或4應該針對你的情況下工作。

您還應首先繪制所有白線,然后繪制所有黑線,以防它們相交。

清除畫布的快捷方法是設置寬度:

context.canvas.width = context.canvas.width;

我的解決方案是雙緩沖:

 var shapes = [{type:"circle", x:50, y:50, radious:40, lineWidth:2, strokeStyle:"#FF0000", fillStyle:"#800000"} ,{type:"rectangle", x:50, y:50, width:100, height: 100, lineWidth:2, strokeStyle:"#00FF00", fillStyle:"#008000"} ,{type:"line", x1:75, y1:100, x2:170, y2:75, lineWidth:3, strokeStyle:"#0000FF"} ]; step1(); setTimeout(function () { step2(); setTimeout(function () { step3(); }, 1000); }, 1000); function step1() { clearCanvas('myCanvas1'); shapes.forEach((sh) => { drawShape('myCanvas1', sh); }); }; function step2() { clearCanvas('myCanvas2'); shapes.pop(); shapes.forEach((sh) => { drawShape('myCanvas2', sh); }); showOtherCanvas('myCanvas2', 'myCanvas1'); }; function step3() { clearCanvas('myCanvas1'); shapes.pop(); shapes.forEach((sh) => { drawShape('myCanvas1', sh); }); showOtherCanvas('myCanvas1', 'myCanvas2'); }; function showOtherCanvas(cnv1, cnv2) { var c1 = document.getElementById(cnv1); var c2 = document.getElementById(cnv2); c1.style['z-index'] = 3; c2.style['z-index'] = 1; c1.style['z-index'] = 2; } function clearCanvas(canvasID) { var canvas = document.getElementById(canvasID); var ctx = canvas.getContext('2d'); ctx.fillStyle="#FFFFFF"; ctx.fillRect(0,0,480,320); } function drawShape (canvasID, info) { switch (info.type) { case "line" : drawLine(canvasID, info); case "rectangle" : drawRectangle(canvasID, info); case "circle" : drawCircle(canvasID, info); } } function drawLine (canvasID, info) { var canvas = document.getElementById(canvasID); var ctx = canvas.getContext('2d'); ctx.strokeStyle = info.strokeStyle; ctx.lineWidth = info.lineWidth ctx.beginPath(); ctx.moveTo(info.x1, info.y1); ctx.lineTo(info.x2, info.y2); ctx.stroke(); } function drawRectangle (canvasID, info) { var canvas = document.getElementById(canvasID); var ctx = canvas.getContext('2d'); ctx.fillStyle = info.fillStyle; ctx.strokeStyle = info.strokeStyle; ctx.lineWidth = info.lineWidth ctx.fillRect(info.x, info.y, info.width, info.height); ctx.strokeRect(info.x, info.y, info.width, info.height); } function drawCircle (canvasID, info) { var canvas = document.getElementById(canvasID); var ctx = canvas.getContext('2d'); ctx.fillStyle = info.fillStyle; ctx.strokeStyle = info.strokeStyle; ctx.lineWidth = info.lineWidth ctx.beginPath(); ctx.arc(info.x, info.y, info.radious, 0, 2 * Math.PI); ctx.fill(); ctx.beginPath(); ctx.arc(info.x, info.y, info.radious, 0, 2 * Math.PI); ctx.stroke(); } 
 <canvas id="myCanvas2" width="480" height="320" style="border: 1px solid #000000; position: absolute; top: 10; left: 10; z-index:1"> </canvas> <canvas id="myCanvas1" width="480" height="320" style="border: 1px solid #000000; position: absolute; top: 10; left: 10; z-index:2"> </canvas> 

變化如此之快,你不會看到任何閃爍。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM