1175

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

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

4

25 回答 25

1544

鉴于这canvas是一个画布元素或一个OffscreenCanvas对象

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

context.clearRect(0, 0, canvas.width, canvas.height);
于 2010-01-26T20:52:18.097 回答
772

采用: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 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%。随着画布尺寸的增加,这种差异会下降。

这已经相对微不足道了,但在大多数情况下,你会抽出比你清除更多的东西,我相信这种性能差异是无关紧要的。

100000 iterations averaged 10 times:
1885ms to clear
2112ms to reset and clear
于 2011-07-17T05:06:28.823 回答
250

如果您正在画线,请确保不要忘记:

context.beginPath();

否则线条将不会被清除。

于 2011-01-13T07:12:09.707 回答
125

其他人已经很好地回答了这个问题,但是如果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 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
};
于 2012-03-15T15:05:13.993 回答
37

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

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

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

优点:保留 strokeStyle、fillStyle 等;没有滞后;

缺点:如果您在绘制任何内容之前已经使用 beginPath,则没有必要

2.使用宽度/高度黑客:

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

或者

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

优点:适用于 IE 缺点:将 strokeStyle、fillStyle 重置为黑色;懒惰的;

我想知道为什么不存在本机解决方案。实际上,clearRect()被认为是单线解决方案,因为大多数用户beginPath()在绘制任何新路径之前都会这样做。虽然 beginPath 仅用于绘制线条而不是封闭路径rect().

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

于 2018-05-08T12:29:51.363 回答
36
  • Chrome 响应良好:context.clearRect ( x , y , w , h );正如@Pentium10 所建议的,但 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;
}
于 2010-11-03T09:48:48.517 回答
21

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

canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, canvas.width, canvas.height);
于 2013-11-13T06:08:52.037 回答
15

一个快速的方法是做

canvas.width = canvas.width

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

于 2018-05-08T16:56:54.533 回答
14

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

这简单。假设您的背景颜色是白色:

// 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);
于 2012-05-04T04:36:42.540 回答
9

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

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

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

于 2018-05-28T15:14:28.903 回答
7

这适用于我在 chart.js 中的 pieChart

<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
于 2016-02-26T12:36:33.817 回答
7

我总是用

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

对于自定义颜色,以及

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

清除时使画布透明

于 2019-01-11T20:45:03.150 回答
6

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

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

缺点是画布不再透明。

于 2013-03-25T22:29:13.087 回答
6

最短的方法:

canvas.width += 0
于 2020-01-22T18:06:48.430 回答
4

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

于 2010-08-02T04:50:02.883 回答
4
function clear(context, color)
{
    var tmp = context.fillStyle;
    context.fillStyle = color;
    context.fillRect(0, 0, context.canvas.width, context.canvas.height);
    context.fillStyle = tmp;
}
于 2014-04-11T11:39:15.467 回答
4

一个简单但可读性不强的方法是这样写:

var canvas = document.getElementId('canvas');

// after doing some rendering

canvas.width = canvas.width;  // clear the whole canvas
于 2017-08-24T21:34:50.740 回答
2
context.clearRect(0,0,w,h)   

用 RGBA 值填充给定的矩形:
0 0 0 0:使用 Chrome
0 0 0 255:使用 FF 和 Safari

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

无论浏览器如何,让矩形填充
0 0 0 255 !

于 2016-12-12T09:53:44.530 回答
2
Context.clearRect(starting width, starting height, ending width, ending height);

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

于 2017-09-30T15:38:55.740 回答
2

我总是用这个

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

笔记

结合 clearRect 和 requestAnimationFrame 允许更流畅的动画,如果这是你想要的

于 2020-03-27T19:48:29.180 回答
2
private clearCanvas() {
  const canvas: HTMLCanvasElement = this.ctx.canvas
  this.ctx.save()
  this.ctx.setTransform(1, 0, 0, 1, 0, 0)
  this.ctx.clearRect(0, 0, canvas.width, canvas.height)
  this.ctx.restore()
}
于 2021-12-08T11:30:08.297 回答
1

最快的方法:

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
于 2012-08-13T18:32:05.220 回答
1

如果你只使用 clearRect ,如果你有它在一个表单中提交你的绘图,你会得到一个提交而不是清除,或者可以先清除它然后上传一个无效的绘图,所以你需要添加一个preventDefault 在函数开始时:

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

希望它可以帮助某人。

于 2017-01-10T18:14:56.580 回答
1

这是一个带有清除画布按钮的手绘画布。
请参阅此画布的实时示例,您可以在该画布上进行绘制,并在需要时将其清除以重新绘制 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 between        
        var 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>

于 2021-07-11T06:54:05.527 回答
0

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

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

var clearCanvas = false;

从您的 PaperScript 定义:

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

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

于 2012-04-12T15:58:27.667 回答