如何清除画布以进行重绘

发布于 2024-08-19 18:18:35 字数 105 浏览 11 评论 0 原文

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

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

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(26

新一帅帅 2024-08-26 18:18:35

鉴于 canvas 是一个画布元素或 < code>OffscreenCanvas 对象,使用 <代码>clearRect

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

Given that canvas is a canvas element or an OffscreenCanvas object, use clearRect:

const context = canvas.getContext('2d');
context.clearRect(0, 0, canvas.width, canvas.height);
吹梦到西洲 2024-08-26 18:18:35

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

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

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

重置canvas.width会重置所有画布状态(例如变换、lineWidth、行程样式等),速度非常慢(与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

Use: 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;

Resetting canvas.width resets 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.

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.

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.

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
娇妻 2024-08-26 18:18:35

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

context.beginPath();

否则线条将不会被清除。

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

context.beginPath();

Otherwise the lines won't get cleared.

冰葑 2024-08-26 18:18:35

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

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:

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
};
指尖凝香 2024-08-26 18:18:35

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

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

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

优点:保留描边样式、填充样式等。 ;无滞后;

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

2.使用宽度/高度 hack:

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

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

优点:适用于 IE
缺点:将描边样式、填充样式重置为黑色;拉吉;

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

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

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

1.To completely clear canvas irrespective of how you draw:

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

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

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

2.Using the width/height hack:

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

OR

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

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

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().

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

眼眸 2024-08-26 18:18:35
  • 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;
}
  • 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.

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;
}
泅人 2024-08-26 18:18:35

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

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

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

canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, canvas.width, canvas.height);
魔法少女 2024-08-26 18:18:35

一个快速的方法是不

canvas.width = canvas.width

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

A quick way is to do

canvas.width = canvas.width

Idk how it works but it does!

-小熊_ 2024-08-26 18:18:35

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

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

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

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);
行至春深 2024-08-26 18:18:35

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

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。然后,恢复之前的上下文状态。

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 copy as globalCompositeOperation. Then, restores the previous context state.

怪我鬧 2024-08-26 18:18:35

我总是使用

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

用于自定义颜色,以及

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

用于在清除时使画布透明

I always use

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

For a custom color, and

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

For making the canvas transparent when clearing

顾冷 2024-08-26 18:18:35

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

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

缺点是画布不再透明。

I have found that in all browsers I test, the fastest way is to actually fillRect with white, or whataever color you would like. I have a very large monitor and in full screen mode the clearRect is agonizingly slow, but the fillRect is reasonable.

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

The drawback is that the canvas is no longer transparent.

简单气质女生网名 2024-08-26 18:18:35

这适用于 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

This worked for my pieChart in 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
养猫人 2024-08-26 18:18:35

最短路线:

canvas.width += 0

the shortest way:

canvas.width += 0
咽泪装欢 2024-08-26 18:18:35
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()
}
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()
}
写给空气的情书 2024-08-26 18:18:35

现在有一个 .reset() 方法不仅会清除画布缓冲区,还会完全重置上下文的所有属性(样式等),重置其转换矩阵,清除其当前子路径,清除其状态堆栈(由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;
  };
}

There is now a .reset() method which will not only clear the canvas buffer but also completely reset all the properties of the context (styles etc.), reset its transformation matrix, clear its current sub-path, clear its states stack (the one controlled by save() and restore()), and remove all the clipping regions.

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

Basically, it has the same effects as canvas.width += 0, except that it's more idiomatic.

However it seems that in current Chromium's implementation it's as slow as canvas.width += 0, it also does generate a new buffer instead of simply clearing the previous one (resulting in more memory garbage). Another caveat is that it's currently only supported in Chromium browsers.
Though to polyfill it you can go the Chrome way

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

眼眸里的那抹悲凉 2024-08-26 18:18:35

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

in webkit you need to set the width to a different value, then you can set it back to the initial value

活雷疯 2024-08-26 18:18:35
function clear(context, color)
{
    var tmp = context.fillStyle;
    context.fillStyle = color;
    context.fillRect(0, 0, context.canvas.width, context.canvas.height);
    context.fillStyle = tmp;
}
function clear(context, color)
{
    var tmp = context.fillStyle;
    context.fillStyle = color;
    context.fillRect(0, 0, context.canvas.width, context.canvas.height);
    context.fillStyle = tmp;
}
美男兮 2024-08-26 18:18:35

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

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

// after doing some rendering

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

A simple, but not very readable way is to write this:

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

// after doing some rendering

canvas.width = canvas.width;  // clear the whole canvas
眼前雾蒙蒙 2024-08-26 18:18:35
Context.clearRect(starting width, starting height, ending width, ending height);

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

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

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

灼疼热情 2024-08-26 18:18:35

我总是使用这个

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

注意

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

I always use this

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

NOTE

combining clearRect and requestAnimationFrame allows for more fluid animation if that is what you're going for

南薇 2024-08-26 18:18:35

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

希望它对某人有帮助。

If you use clearRect only, if you have it in a form to submit your drawing, you'll get a submit instead the clearing, or maybe it can be cleared first and then upload a void drawing, so you'll need to add a preventDefault at the beggining of the function:

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

Hope it helps someone.

如梦初醒的夏天 2024-08-26 18:18:35

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

This is a Free hand drawing Canvas with a Clear Canvas Button.
See this live example of a canvas which you can draw on and also when required clear it for redrawing clearRect() is used to delete the prersent canvas and fillRect() is used to again draw the initial canvas which was clean and had no drawings on it.

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>

寂寞陪衬 2024-08-26 18:18:35

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

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

var clearCanvas = false;

从您的 PaperScript 定义:

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

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

These are all great examples of how you clear a standard canvas, but if you are using paperjs, then this will work:

Define a global variable in JavaScript:

var clearCanvas = false;

From your PaperScript define:

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

Now wherever you set clearCanvas to true, it will clear all the items from the screen.

寒冷纷飞旳雪 2024-08-26 18:18:35

最快的方法:

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

fastest way:

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
月亮邮递员 2024-08-26 18:18:35

如果你不使用转换,这会做到这一点:

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

我通常用背景颜色的矩形填充整个画布

如果应用转换 - 你可以getTransform并做一些学校数学来清除画布中的画布应用变换空间。它并不那么复杂,但是昨天我花了一些时间在纸上,当时我需要将鼠标位置转换到每个绘制元素的本地空间(用于碰撞检查):

a,b,c,d,e,f - 是画布矩阵数据,X,Y - 鼠标位置,x,y - 本地空间中的位置

Math:
ax + cy + e = X
bx + dy + f = Y

x = (X - cy - e) / a
y = (Y - bx - f ) / d

x = (X - c*(Y - bx - f) / d - e ) / a

adx = dX - cY + bcx + cf - ed
x(ad - bc) = dX - cY + cf - ed

Answer:
x = (dX - cY + cf - ed)/(ad - bc)
y = (Y - bx - f) / d

您需要对所有 4 个角 (0,0),(w,0),(w,h),(0 ,h),然后获取所有结果 x 和 y 的最小值/最大值,然后使用 fillRectclearRect 获取带有参数的 rect:(minX, minY, maxX-minX, maxY -minY)

我认为这在性能方面并不是最佳的。实际上,我认为最高效的方法是获取空画布的 getImageData 并通过 putImageData 方法将其放回原处,但性能测试表明情况并非如此。清除是否应用转换的最佳方法是:

context.save();
context.setTransform(1,0,0,1,0,0);
context.clearRect(0,0,800, 600);
context.restore();

Here is a jsperf link 其中包含我尝试过的所有选项。

If you do not use transformations this would do the thing:

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

I usually fill the full canvas with a rect of background color

If transformations are applied — you can getTransform and do some school math to clear the canvas in the applied transform space. It is not so complicated, but I spent some time yesterday with paper when I needed to transform the mouse position to the local space of each drawn element (for collision check):

a, b, c, d, e, f — is the canvas matrix data, X, Y — mouse position, and x, y — position in local space

Math:
ax + cy + e = X
bx + dy + f = Y

x = (X - cy - e) / a
y = (Y - bx - f ) / d

x = (X - c*(Y - bx - f) / d - e ) / a

adx = dX - cY + bcx + cf - ed
x(ad - bc) = dX - cY + cf - ed

Answer:
x = (dX - cY + cf - ed)/(ad - bc)
y = (Y - bx - f) / d

You would need to do it for all 4 corners (0,0), (w,0), (w,h), (0,h), then get min/max of all results x, and y, then fillRect or clearRect for rect with arguments: (minX, minY, maxX-minX, maxY-minY)

I do not think it would be optimal in the performance term way. Actually, I thought that the most performant way would be to getImageData of an empty canvas and put it back by the putImageData method, but performance tests show that this is not the case. An optimal way to clear if transformations are applied is:

context.save();
context.setTransform(1,0,0,1,0,0);
context.clearRect(0,0,800, 600);
context.restore();

Here is a jsperf link with all options that I've tried.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文