如何清除画布重绘

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

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

1153097 次浏览

假设canvas是一个画布元素或#1对象,使用#2

const context = canvas.getContext('2d');
context.clearRect(0, 0, canvas.width, canvas.height);

在webkit中,您需要将宽度设置为不同的值,然后您可以将其设置回初始值

  • Chrome对@Pentium10建议的context.clearRect ( x , y , w , h );响应良好,但IE9似乎完全忽略了这个指令。
  • IE9似乎回应:canvas.width = canvas.width;,但它不清除线条,只是形状,图片和其他对象,除非你也使用@John Allsopp的解决方案首先改变宽度。

所以如果你有一个像这样创建的画布和上下文:

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

你可以使用这样的方法:

function clearCanvas(context, canvas) {context.clearRect(0, 0, canvas.width, canvas.height);var w = canvas.width;canvas.width = 1;canvas.width = w;}

如果你在画线,确保你不要忘记:

context.beginPath();

否则,线路将无法清除。

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

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

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

重置canvas.width重置所有画布状态(例如转换,lineWidth,strokeStyle等),它非常慢(与clearRect相比),它不适用于所有浏览器,并且它没有描述您实际尝试做的事情。

处理变换坐标

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

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

// Store the current transformation matrixcontext.save();
// Use the identity matrix while clearing the canvascontext.setTransform(1, 0, 0, 1, 0, 0);context.clearRect(0, 0, canvas.width, canvas.height);
// Restore the transformcontext.restore();

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

这已经是相对微不足道的,但在大多数情况下,您将绘制远远超过您正在清理的内容,我相信这种性能差异是无关紧要的。

100000 iterations averaged 10 times:1885ms to clear2112ms to reset and clear

其他人已经在回答这个问题方面做得很好,但是如果上下文对象上的一个简单的clear()方法对你有用(对我有用),这是我根据这里的答案使用的实现:

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();}};

用法:

window.onload = function () {var canvas = document.getElementById('canvasId');var context = canvas.getContext('2d');
// do some drawingcontext.clear();
// do some more drawingcontext.setTransform(-1, 0, 0, 1, 200, 200);// do some drawing with the new transformcontext.clear(true);// draw more, still using the preserved transform};

这些都是关于如何清除标准画布的很好的例子,但是如果你使用的是纸质文件,那么这将起作用:

在JavaScript中定义一个全局变量:

var clearCanvas = false;

从您的PomeScript定义:

function onFrame(event){if(clearCanvas && project.activeLayer.hasChildren()){project.activeLayer.removeChildren();clearCanvas = false;}}

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

这里有很多很好的答案。另一个注意事项是,有时只部分清除画布很有趣。也就是说,“淡出”先前的图像,而不是完全擦除它。这可以提供很好的跟踪效果。

假设你的背景颜色是白色:

// 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);

最快的方法:

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

我发现在我测试的所有浏览器中,最快的方法是用白色或任何你喜欢的颜色填充Rect。我有一个非常大的显示器,在全屏模式下clearRect非常慢,但fillRect是合理的。

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

缺点是画布不再透明。

通过传递x、y坐标以及画布的高度和宽度来使用clearRect方法。ClearRect将清除整个画布:

canvas = document.getElementById("canvas");ctx = canvas.getContext("2d");ctx.clearRect(0, 0, canvas.width, canvas.height);
function clear(context, color){var tmp = context.fillStyle;context.fillStyle = color;context.fillRect(0, 0, context.canvas.width, context.canvas.height);context.fillStyle = tmp;}

这对我的pieChart在chart.js

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

如果你只使用clearRect,如果你有一个表单来提交你的绘图,你会得到一个提交而不是清除,或者它可以先被清除,然后上传一个无效的绘图,所以你需要在函数的设置中添加一个预防默认值:

   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);">

希望它能帮助某人。

一个简单但不太易读的方法是这样写:

var canvas = document.getElementId('canvas');
// after doing some rendering
canvas.width = canvas.width;  // clear the whole canvas
Context.clearRect(starting width, starting height, ending width, ending height);

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

这是2018年,仍然没有本地方法来完全清除画布以进行重绘。clearRect()不要完全清除画布。未清除非填充类型的图纸(例如rect()

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

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

优点:可以保留strokeStyle、fillStyle等样式,不滞后

缺点:如果您在绘制任何内容之前已经在使用开始路径,则不必要

2.使用宽度/高度hack:

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

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

优点:适用于IE缺点:重置,填充样式为黑色;Laggy;

我想知道为什么不存在原生解决方案。实际上,clearRect()被认为是单行解决方案,因为大多数用户在绘制任何新路径之前都会进行beginPath()。尽管开始路径只能在画线时使用,而不是像rect().这样的封闭路径

这就是为什么接受的答案没有解决我的问题,我最终浪费了几个小时尝试不同的黑客。诅咒你mozilla

一个快速的方法是做

canvas.width = canvas.width

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

这是我使用的,不管边界和矩阵转换:

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作为#1绘制一个透明像素。然后,恢复以前的上下文状态。

我总是用

ctx.fillStyle = "rgb(255, 255, 255)";ctx.fillRect(0, 0, canvas.width, canvas.height);

对于自定义颜色,以及

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

清除时使画布透明

最短的路:

canvas.width += 0

我一直用这个

ctx.clearRect(0, 0, canvas.width, canvas.height)window.requestAnimationFrame(functionToBeCalled)

结合clearRect和请求动画帧允许更流畅的动画,如果这就是你要做的

这是一个免费的手绘画布与清晰的画布按钮。
请参阅此实例的画布,您可以在其上绘制,并且在需要时清除它以重新绘制clearRect()用于删除预先发送的画布,fillRect()用于再次绘制干净且没有绘图的初始画布。

var canvas = document.getElementById("canvas"),ctx = canvas.getContext("2d"),painting = false,lastX = 0,lastY = 0,lineThickness = 1;
canvas.width=canvas.height = 250;ctx.fillRect(0, 0, 250, 250);
canvas.onmousedown = function(e) {painting = true;ctx.fillStyle = "#ffffff";lastX = e.pageX - this.offsetLeft;lastY = e.pageY - this.offsetTop;};
canvas.onmouseup = function(e){painting = false;}
canvas.onmousemove = function(e) {if (painting) {mouseX = e.pageX - this.offsetLeft;mouseY = e.pageY - this.offsetTop;
// find all points betweenvar x1 = mouseX,x2 = lastX,y1 = mouseY,y2 = lastY;

var steep = (Math.abs(y2 - y1) > Math.abs(x2 - x1));if (steep){var x = x1;x1 = y1;y1 = x;
var y = y2;y2 = x2;x2 = y;}if (x1 > x2) {var x = x1;x1 = x2;x2 = x;
var y = y1;y1 = y2;y2 = y;}
var dx = x2 - x1,dy = Math.abs(y2 - y1),error = 0,de = dy / dx,yStep = -1,y = y1;
if (y1 < y2) {yStep = 1;}
lineThickness = 4;
for (var x = x1; x < x2; x++) {if (steep) {ctx.fillRect(y, x, lineThickness , lineThickness );} else {ctx.fillRect(x, y, lineThickness , lineThickness );}
error += de;if (error >= 0.5) {y += yStep;error -= 1.0;}}


lastX = mouseX;lastY = mouseY;
}}var button=document.getElementById("clear");button.onclick=function clearcanvas(){canvas=document.getElementById("canvas"),ctx = canvas.getContext('2d');ctx.clearRect(0, 0, 250, 250);canvas.width=canvas.height = 250;ctx.fillRect(0, 0, 250, 250);}
#clear{border-radius:10px;font-size:8px !important;position:absolute;top:1px;}#canvas{border-radius:10px}
<link href="https://www.w3schools.com/w3css/4/w3.css" rel="stylesheet"/><button id="clear" class="w3-padding w3-xxlarge w3-pink" type="button">Clear Canvas</button><canvas id="canvas"></canvas>

private clearCanvas() {const canvas: HTMLCanvasElement = this.ctx.canvasthis.ctx.save()this.ctx.setTransform(1, 0, 0, 1, 0, 0)this.ctx.clearRect(0, 0, canvas.width, canvas.height)this.ctx.restore()}

现在有一个#0方法,它不仅会清除画布缓冲区,还会完全重置上下文的所有属性(样式等),重置其转换矩阵,清除其当前子路径,清除其状态堆栈(由save()restore()控制的堆栈),并删除所有裁剪区域。

context.reset();// now 'context' is clear as new

基本上,它具有与canvas.width += 0相同的效果,只是它更惯用。

然而,在当前Chromium的实现中,它似乎和canvas.width += 0一样慢,它也会生成一个新的缓冲区,而不是简单地清除前一个缓冲区(导致更多的内存垃圾)。另一个警告是,它目前仅在Chromium浏览器中受支持。如果你想得到它,你可以Chrome

if (!CanvasRenderingContext2D.prototype.reset) {CanvasRenderingContext2D.prototype.reset = function() {this.canvas.width += 0;};}if (!OffscreenCanvasRenderingContext2D.prototype.reset) {OffscreenCanvasRenderingContext2D.prototype.reset = function() {this.canvas.width += 0;};}