关于javascript:如何清除画布以进行重绘

How to clear the canvas for redrawing

在尝试了组合操作和在画布上绘制图像之后,我现在正在尝试删除图像和组合。我该怎么做?

我需要清除画布以重新绘制其他图像;这可能会持续一段时间,所以我不认为每次绘制一个新矩形都是最有效的选择。


1
2
3
const context = canvas.getContext('2d');

context.clearRect(0, 0, canvas.width, canvas.height);


用途:context.clearRect(0, 0, canvas.width, canvas.height);

这是清除整个画布的最快和最具描述性的方法。

不使用:canvas.width = canvas.width;

重置canvas.width将重置所有画布状态(例如转换、线条宽度、strokestyle等),它非常慢(与clearrect相比),在所有浏览器中都不起作用,也无法描述您实际要做的事情。

处理变换坐标

如果修改了转换矩阵(例如使用scalerotatetranslate,那么context.clearRect(0,0,canvas.width,canvas.height)可能无法清除画布的整个可见部分。

解决方案?清除画布前重置转换矩阵:

1
2
3
4
5
6
7
8
9
// Store the current transformation matrix
context.save();

// Use the identity matrix while clearing the canvas
context.setTransform(1, 0, 0, 1, 0, 0);
context.clearRect(0, 0, canvas.width, canvas.height);

// Restore the transform
context.restore();

编辑:我刚刚做了一些分析(在Chrome中),在不重置转换的情况下清除300x150(默认大小)画布的速度大约快10%。随着画布大小的增加,这种差异会减小。

这已经是相对无关紧要的了,但在大多数情况下,你会画得比你正在清除的要多得多,我相信这一性能差异是无关的。

1
2
3
100000 iterations averaged 10 times:
1885ms to clear
2112ms to reset and clear


如果要绘制线条,请确保不要忘记:

1
context.beginPath();

否则线路就不会被清除。


其他人已经很好地回答了这个问题,但是如果上下文对象上的一个简单的clear()方法对您(对我来说)有用的话,这就是我基于以下答案使用的实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
CanvasRenderingContext2D.prototype.clear =
  CanvasRenderingContext2D.prototype.clear || function (preserveTransform) {
    if (preserveTransform) {
      this.save();
      this.setTransform(1, 0, 0, 1, 0, 0);
    }

    this.clearRect(0, 0, this.canvas.width, this.canvas.height);

    if (preserveTransform) {
      this.restore();
    }          
};

用途:

1
2
3
4
5
6
7
8
9
10
11
12
13
window.onload = function () {
  var canvas = document.getElementById('canvasId');
  var context = canvas.getContext('2d');

  // do some drawing
  context.clear();

  // do some more drawing
  context.setTransform(-1, 0, 0, 1, 200, 200);
  // do some drawing with the new transform
  context.clear(true);
  // draw more, still using the preserved transform
};


  • chrome对@pentium10建议的context.clearRect ( x , y , w , h );反应很好,但ie9似乎完全忽略了这个指令。
  • IE9似乎响应:canvas.width = canvas.width;,但它不清楚线条、形状、图片和其他对象,除非您也使用@john allsopp的解决方案来首次更改宽度。

因此,如果您有这样一个画布和上下文:

1
2
var canvas = document.getElementById('my-canvas');
var context = canvas.getContext('2d');

您可以使用这样的方法:

1
2
3
4
5
6
function clearCanvas(context, canvas) {
  context.clearRect(0, 0, canvas.width, canvas.height);
  var w = canvas.width;
  canvas.width = 1;
  canvas.width = w;
}


使用ClearRect方法通过传递画布的X、Y坐标和高度和宽度。ClearRect将整个画布清除为:

1
2
3
canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, canvas.width, canvas.height);


这是2018年,仍然没有完全清除画布重新绘制的本地方法。clearRect()没有完全清除画布。未清除非填充式图纸(如rect())

1.要完全清除画布,无论您如何绘制:

1
2
context.clearRect(0, 0, context.canvas.width, context.canvas.height);
context.beginPath();

优点:保留strokestyle、fillstyle等;无滞后;

缺点:如果在绘制之前已经使用了beginpath,则不需要

2.使用宽度/高度hack:

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

1
context.canvas.height = context.canvas.height;

专业:与IE合作缺点:重置strokestyle,fillstyle为黑色;laggy;

我想知道为什么不存在本地解决方案。实际上,clearRect()被认为是单线解决方案,因为大多数用户在绘制任何新路径之前都会先执行beginPath()。虽然beginpath只在绘制线条时使用,而不是像rect().那样封闭的路径。

这就是为什么被接受的答案不能解决我的问题,结果我浪费了几个小时尝试不同的黑客。诅咒你Mozilla


这里有很多好答案。另一个需要注意的是,有时候只清理画布的一部分是很有趣的。也就是说,"淡出"前一个图像,而不是完全删除它。这可以产生很好的轨迹效果。

这很容易。假设你的背景色是白色:

1
2
3
// assuming background color = white and"eraseAlpha" is a value from 0 to 1.
myContext.fillStyle ="rgba(255, 255, 255," + eraseAlpha +")";
myContext.fillRect(0, 0, w, h);


一个快速的方法就是

1
canvas.width = canvas.width

我想知道它是如何工作的,但它确实如此!


在WebKit中,需要将宽度设置为其他值,然后可以将其设置回初始值。


1
2
3
4
5
6
7
function clear(context, color)
{
    var tmp = context.fillStyle;
    context.fillStyle = color;
    context.fillRect(0, 0, context.canvas.width, context.canvas.height);
    context.fillStyle = tmp;
}


这对chart.js中的piechart很有用。

1
2
3
4
5
    <canvas id="pieChart" height="5" width="6"></canvas>


$('#pieChartContainer').html(''); //remove canvas from container
$('#pieChartContainer').html('<canvas id="pieChart" height="5" width="6"></canvas>'); //add it back to the container

我发现,在我测试的所有浏览器中,最快的方法是用白色填充,或者你想要的任何颜色。我有一个非常大的显示器,在全屏模式下,ClearRect速度非常慢,但是FillRect是合理的。

1
2
context.fillStyle ="#ffffff";
context.fillRect(0,0,canvas.width, canvas.height);

缺点是画布不再透明。


这就是我所使用的,不管边界和矩阵变换是什么:

1
2
3
4
5
6
7
8
9
10
function clearCanvas(canvas) {
  const ctx = canvas.getContext('2d');
  ctx.save();
  ctx.globalCompositeOperation = 'copy';
  ctx.strokeStyle = 'transparent';
  ctx.beginPath();
  ctx.lineTo(0, 0);
  ctx.stroke();
  ctx.restore();
}

基本上,它保存了上下文的当前状态,并用copy作为globalCompositeOperation绘制了一个透明像素。然后,恢复以前的上下文状态。


最快的方式:

1
2
3
4
5
6
7
canvas = document.getElementById("canvas");
c = canvas.getContext("2d");

//... some drawing here

i = c.createImageData(canvas.width, canvas.height);
c.putImageData(i, 0, 0); // clear context by putting empty image data


一个简单但不太可读的方法是写:

1
2
3
4
5
var canvas = document.getElementId('canvas');

// after doing some rendering

canvas.width = canvas.width;  // clear the whole canvas

我总是使用

1
2
cxt.fillStyle ="rgb(255, 255, 255)";
cxt.fillRect(0, 0, canvas.width, canvas.height);

1
context.clearRect(0,0,w,h)

用rgba值填充给定的矩形:0 0 0 0:带Chrome0 0 0 0 255:带FF&Safari

但是

1
2
3
context.clearRect(0,0,w,h);    
context.fillStyle = 'rgba(0,0,0,1)';  
context.fillRect(0,0,w,h);

让矩形填充0 0 0 0不管是浏览器!


如果您只使用clearect,如果您有一个表单提交您的图纸,您将得到一个提交而不是清除,或者可能它可以先清除,然后上传一个无效的图纸,所以您需要在函数的开头添加一个preventdefault:

1
2
3
4
5
6
7
   function clearCanvas(canvas,ctx) {
        event.preventDefault();
        ctx.clearRect(0, 0, canvas.width, canvas.height);
    }


<input type="button" value="Clear Sketchpad" id="clearbutton" onclick="clearCanvas(canvas,ctx);">

希望它能帮助别人。


1
Context.clearRect(starting width, starting height, ending width, ending height);

示例:context.clearRect(0, 0, canvas.width, canvas.height);


这些都是如何清除标准画布的好例子,但是如果您使用PaperJS,那么这将起作用:

在javascript中定义全局变量:

1
var clearCanvas = false;

从书面脚本中定义:

1
2
3
4
5
6
function onFrame(event){
    if(clearCanvas && project.activeLayer.hasChildren()){
        project.activeLayer.removeChildren();
        clearCanvas = false;
    }
}

现在,无论您将ClearCanvas设置为true,它都将从屏幕上清除所有项目。