删除HTML5画布上以前绘制的线条

Saq*_*qib 15 html javascript 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);
}
Run Code Online (Sandbox Code Playgroud)

为了理解上述内容,有两个辅助函数:

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

问题在于,虽然所有的手都按照预期的黑色绘制,但它们永远不会被删除.我希望由于相同的线条以白色(背景颜色)绘制,因此它将有效地擦除之前在该点绘制的内容.但事实似乎并非如此.

我缺少什么?

ell*_*ben 17

由于我可以扩展的原因,你应该考虑清除画布并重新绘制它,除非有性能或合成的原因不这样做.

你想要clearRect,像这样:

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

//redraw your clock here
/* ... */
Run Code Online (Sandbox Code Playgroud)

  • 如果一个人想要清除特定的线条或形状(就像我做的那样),而不是清除一个矩形区域,设置`ctx.globalCompositeOperation ="destination-out"` - 正如andrewmu对[类似问题]的解决方案中所提到的那样(http://stackoverflow.com/questions/3328906/erasing-in-html5-canvas) - 几乎会让你的填充/描边操作就像橡皮擦工具一样.记得在完成后更改合成模式.有关详细信息,请参阅[Mozilla的合成和裁剪](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Compositing). (3认同)

mrm*_*reg 16

而不是删除你不想要的东西,你可以:

  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);
Run Code Online (Sandbox Code Playgroud)
<canvas width=200 height=200>
Run Code Online (Sandbox Code Playgroud)

  • 与使用 clearRectangle 相比,此方法的优势在于您可以在绘图的任何阶段获取 ImageData 并恢复到该级别,而 clearRectangle 将始终将您带回到空白画布。为此,我投了赞成票。 (2认同)

Sim*_*ris 5

您不能只用白色重新绘制线条并希望它擦除旧线条的原因是因为可能存在一些抗锯齿/出血。您还会注意到,因此,在像素上绘制的水平直线与半像素上绘制的水平线看起来非常不同。

当你做你的白色“擦除”线时,试着lineWidth用大约 3 或 4的大号来绘制它们。这应该适合你的情况。

您还应该先绘制所有白线,然后再绘制所有黑线,以防它们相交。