Javascript 如何清除画布以重新绘制

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2142535/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-22 22:55:53  来源:igfitidea点击:

How to clear the canvas for redrawing

javascripthtmlcanvashtml5-canvascomposite

提问by richard

After experimenting with composite operations and drawing images on the canvas I'm now trying to remove images and compositing. How do I do this?

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

I need to clear the canvas for redrawing other images; this can go on for a while so I don't think drawing a new rectangle every time will be the most efficient option.

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

回答by Pentium10

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

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

回答by Prestaul

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

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

This is the fastest and most descriptive way to clear the entire canvas.

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

Do not use: canvas.width = canvas.width;

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

Resetting canvas.widthresets all canvas state (e.g. transformations, lineWidth, strokeStyle, etc.), it is very slow (compared to clearRect), it doesn't work in all browsers, and it doesn't describe what you are actually trying to do.

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

Dealing with transformed coordinates

处理变换的坐标

If you have modified the transformation matrix (e.g. using scale, rotate, or translate) then context.clearRect(0,0,canvas.width,canvas.height)will likely not clear the entire visible portion of the canvas.

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

The solution? Reset the transformation matrix prior to clearing the canvas:

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

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

Edit:I've just done some profiling and (in Chrome) it is about 10% faster to clear a 300x150 (default size) canvas without resetting the transform. As the size of your canvas increases this difference drops.

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

That is already relatively insignificant, but in most cases you will be drawing considerably more than you are clearing and I believe this performance difference be irrelevant.

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

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

回答by trembl

If you are drawing lines, make sure you don't forget:

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

context.beginPath();

Otherwise the lines won't get cleared.

否则线条不会被清除。

回答by JonathanK

Others have already done an excellent job answering the question but if a simple clear()method on the context object would be useful to you (it was to me), this is the implementation I use based on answers here:

其他人已经很好地回答了这个问题,但如果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();
    }           
};

Usage:

用法:

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

回答by grenade

  • Chrome responds well to: context.clearRect ( x , y , w , h );as suggested by @Pentium10 but IE9 seems to completely ignore this instruction.
  • IE9 seems to respond to: canvas.width = canvas.width;but it doesn't clear lines, just shapes, pictures and other objects unless you also use @John Allsopp's solution of first changing the width.
  • Chrome 响应良好:context.clearRect ( x , y , w , h );正如@Pentium10 所建议的那样,但 IE9 似乎完全忽略了这条指令。
  • IE9 似乎响应:canvas.width = canvas.width;但它不会清除线条,只会清除形状、图片和其他对象,除非您还使用 @John Allsopp 的首先更改宽度的解决方案。

So if you have a canvas and context created like this:

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

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

You can use a method like this:

您可以使用这样的方法:

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

回答by sziraqui

This is 2018 and still there is no native method to completely clear canvas for redrawing. clearRect()does notclear the canvas completely. Non-fill type drawings are not cleared out (eg. rect())

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

1.To completelyclear canvas irrespective of how you draw:

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

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

Pros: Preserves strokeStyle, fillStyle etc.; No lag;

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

Cons: Unnecessary if you are already using beginPath before drawing anything

缺点:如果您在绘制任何内容之前已经使用了 beginPath,则不需要

2.Using the width/height hack:

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

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

OR

或者

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

Pros: Works with IE Cons: Resets strokeStyle, fillStyle to black; Laggy;

优点:适用于 IE 缺点:将strokeStyle、fillStyle 重置为黑色;迟钝;

I was wondering why a native solution does not exist. Actually, clearRect()is considered as the single line solution because most users do beginPath()before drawing any new path. Though beginPath is only to be used while drawing lines and not closed path like rect().

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

This is the reason why the accepted answer did not solve my problem and I ended up wasting hours trying different hacks. Curse you mozilla

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

回答by Vishwas

Use clearRect method by passing x,y co-ordinates and height and width of canvas. ClearRect will clear whole canvas as :

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

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

回答by orion elenzil

there are a ton of good answers here. one further note is that sometimes it's fun to only partially clear the canvas. that is, "fade out" the previous image instead of erasing it entirely. this can give nice trails effects.

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

it's easy. supposing your background color is white:

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

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

回答by Jacob Morris

A quick way is to do

一个快速的方法是做

canvas.width = canvas.width

Idk how it works but it does!

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

回答by superruzafa

This is what I use, regardless boundaries and matrix transformations:

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

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

Basically, it saves the current state of the context, and draws a transparent pixel with copyas globalCompositeOperation. Then, restores the previous context state.

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