如何清除画布以进行重绘

时间:2010-01-26 20:50:42

标签: javascript html5 canvas html5-canvas composite

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

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

24 个答案:

答案 0 :(得分:1119)

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

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

答案 1 :(得分:693)

使用: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

答案 2 :(得分:211)

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

context.beginPath();

否则线条不会被清除。

答案 3 :(得分:115)

其他人已经很好地回答了这个问题但是如果上下文对象上的一个简单的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
};

答案 4 :(得分:35)

  • 根据@ Pentium10的建议,Chrome响应良好: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;
}

答案 5 :(得分:19)

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

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

答案 6 :(得分:16)

这是2018年,仍然没有完全清除画布以进行重绘的本机方法。 { fieldArrayName : [{temstart: 'data', longHour : 122323 }]} 没有完全清除画布。非填充类型图纸不会被清除(例如clearRect()

1.无论你如何绘制,完全清晰的画布:

rect()

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

缺点:如果您在绘制任何内容之前已经在使用beginPath

,则不必要

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

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

OR

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

优点:适用于IE 缺点:将strokeStyle,fillStyle重置为黑色; Laggy;

我想知道为什么本机解决方案不存在。实际上,context.canvas.height = context.canvas.height; 被视为单行解决方案,因为大多数用户在绘制任何新路径之前都会clearRect()。虽然beginPath只用于绘制线条而不是像beginPath()

那样的封闭路径

这就是为什么接受的答案没有解决我的问题,我最终浪费时间尝试不同的黑客。诅咒你莫扎拉

答案 7 :(得分: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);

答案 8 :(得分:8)

快速的方法是

canvas.width = canvas.width

Idk如何运作,但确实如此!

答案 9 :(得分:4)

在webkit中

你需要将宽度设置为不同的值,然后你可以将它设置回初始值

答案 10 :(得分:4)

这适用于chart.js中的pieChart

select * from Table1 CROSS JOIN Table2;

答案 11 :(得分: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;
}

答案 12 :(得分:4)

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

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

缺点是画布不再透明。

答案 13 :(得分:3)

这是我使用的,无论边界和矩阵变换如何:

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

基本上,它会保存上下文的当前状态,并绘制copyglobalCompositeOperation的透明像素。然后,恢复先前的上下文状态。

答案 14 :(得分:2)

一种简单但不易读的方式是写这个:

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

// after doing some rendering

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

答案 15 :(得分:2)

最快的方式:

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

答案 16 :(得分:1)

最短的方法:

canvas.width += 0

答案 17 :(得分:1)

我总是用这个

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

注意

将clearRect和requestAnimationFrame结合起来可以使动画更加流畅

答案 18 :(得分:0)

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
无论是浏览器!

答案 19 :(得分:0)

如果您只使用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);">

希望它有所帮助。

答案 20 :(得分:0)

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

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

答案 21 :(得分:0)

我总是使用


      {
      "$schema": "https://vega.github.io/schema/vega/v4.json",
      "width": 600,
      "height": 200,
      "padding": 5,
      "data": [
        {
          "name": "table",
          "values":   [

            {"mtime": 1545206725000 , "systemmaxload": 1},
            {"mtime": 1545292825000 , "systemmaxload": 1},
                       {"mtime": 1545292885000 , "systemmaxload": 3},
                       {"mtime": 1545292945000 , "systemmaxload": 5},
                       {"mtime": 1545293005000 , "systemmaxload": 2},
                       {"mtime": 1545293065000 , "systemmaxload": 1},

                       {"mtime": 1545293125000 , "systemmaxload": 3},
                       {"mtime": 1545465925000 , "systemmaxload":1}
                      ]
        }
      ],

      "scales": [
        {
          "name": "x",
          "type": "utc",
          "range": "width",
          "domain": {"data": "table", "field": "mtime"}
        },
        {
          "name": "y",
          "type": "linear",
          "range": "height",
          "nice": true,
          "zero": true,
          "domain": {"data": "table", "field": "systemmaxload"}
        } 
      ],

      "axes": [
        {"orient": "bottom", "scale": "x" ,"format": "%H:%M:%S %a", "labelOverlap": "parity"},
        {"orient": "left", "scale": "y"}
      ] 
    }

答案 22 :(得分:0)

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

答案 23 :(得分:-2)

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

在JavaScript中定义全局变量:

var clearCanvas = false;

从PaperScript定义:

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

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