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

时间:2011-09-09 17:45:06

标签: 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);
}

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

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

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

我缺少什么?

5 个答案:

答案 0 :(得分:17)

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

你想要clearRect,如下所示:

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

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

答案 1 :(得分:15)

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

  1. 保存画布的状态
  2. 画出你不想要的东西
  3. 将画布恢复到已保存状态以“删除”#39;它们
  4. 使用ImageData

    可以非常轻松地完成此操作

    
    
    var canvas = document.querySelector('canvas'),
        context = canvas.getContext('2d');
    
    context.fillStyle = 'blue';
    context.fillRect(0,0,10,10);
    
    // 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.strokeStyle = 'red';
    context.strokeRect(70,70,20,20);
    
    setTimeout(function () {
        // return the canvas to the state right after we drew the blue rect
        context.putImageData(imageData, 0, 0);
    }, 1000);
    
    <canvas width=100 height=100>
    &#13;
    &#13;
    &#13;

答案 2 :(得分:4)

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

当您执行白色“擦除”行时,请尝试使用较大的lineWidth绘制约3或4行。这应该适合您的情况。

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

答案 3 :(得分:4)

清除画布的快捷方法是设置宽度:

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

答案 4 :(得分:0)

我的解决方案是双重缓冲:

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>

更改是如此之快,您不会看到任何闪烁。