在尝试了合成操作并在画布上绘制图像之后,我现在尝试删除图像并进行合成。我该怎么做呢?
我需要清除画布以重绘其他图像;这可能会持续一段时间,所以我不认为每次都绘制一个新的矩形是最有效的选择。
canvas.style.backgroundColor = "lime";
假设 canvas
是画布元素或 OffscreenCanvas
object,
const context = canvas.getContext('2d');
context.clearRect(0, 0, canvas.width, canvas.height);
使用:context.clearRect(0, 0, canvas.width, canvas.height);
这是清除整个画布的最快和最具描述性的方法。
不要使用:canvas.width = canvas.width;
重置 canvas.width
重置所有画布状态(例如转换、lineWidth、strokeStyle 等),它非常慢(与 clearRect 相比),它不适用于所有浏览器,并且它没有描述您实际尝试的内容去做。
处理变换坐标
如果您修改了转换矩阵(例如使用 scale
、rotate
或 translate
),那么 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
ctx.canvas
来消除对本地 canvas
变量的需求。
canvas.width
和 canvas.height
。与重置转换相比,我没有对运行时差异进行任何数值分析,但我怀疑它会获得更好的性能。
如果您正在画线,请确保不要忘记:
context.beginPath();
否则线条将不会被清除。
beginPath
b>,不要仅仅因为您正在清除画布就认为您也想清除现有路径!这将是一种可怕的做法,并且是一种倒退的看待绘画的方式。
beginPath
不会清除画布上的任何内容,它会重置路径,以便在您绘制之前删除先前的路径条目。您可能确实需要它,但作为绘图操作,而不是清除操作。清除,然后开始路径并绘制,不清除并开始路径,然后绘制。区别有意义吗?在此处查看示例:w3schools.com/tags/canvas_beginpath.asp
其他人已经很好地回答了这个问题,但是如果上下文对象上的简单 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
};
context.clear()
的本机实现......但是,在原型增强中,我不会检查 clear()
是否可用。想象有一天该方法可用,然后它会默默地“覆盖”您的自定义方法,并可能由于不同的可能实现而引入难以发现的错误。
这是 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
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;
}
context.clearRect(0,0,context.canvas.width,context.canvas.height)
来简化该方法。
function clearCanvas(ctx) { ctx.beginPath(); ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); }
通过传递 x,y 坐标以及画布的高度和宽度来使用 clearRect 方法。 ClearRect 会将整个画布清除为:
canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, canvas.width, canvas.height);
一个快速的方法是做
canvas.width = canvas.width
我知道它是如何工作的,但确实如此!
这里有很多很好的答案。另一个注意事项是,有时只部分清除画布很有趣。也就是说,“淡出”之前的图像,而不是完全擦除它。这可以产生很好的轨迹效果。
这很简单。假设您的背景颜色是白色:
// 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);
这就是我使用的,不管边界和矩阵转换:
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
绘制一个透明像素。然后,恢复之前的上下文状态。
我总是用
ctx.fillStyle = "rgb(255, 255, 255)";
ctx.fillRect(0, 0, canvas.width, canvas.height);
对于自定义颜色,以及
ctx.clearRect(0, 0, canvas.width, canvas.height);
清除时使画布透明
<canvas>
默认是透明的。它应该显示底层内容,以防它与其他 HTML 元素重叠。使用上面的代码,您假设画布的父级(很可能是 <body>
)具有白色背景。另一方面,ctx.clearRect(0, 0, canvas.width, canvas.height)
正确地完成了这项工作。
cxt
和 ctx
有点令人沮丧。
这适用于我在 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
我发现在我测试的所有浏览器中,最快的方法是实际上用白色填充矩形,或者你想要的任何颜色。我有一个非常大的显示器,在全屏模式下 clearRect 非常慢,但 fillRect 是合理的。
context.fillStyle = "#ffffff";
context.fillRect(0,0,canvas.width, canvas.height);
缺点是画布不再透明。
最短的方法:
canvas.width += 0
canvas.width = canvas.width
在 webkit 中,您需要将宽度设置为不同的值,然后您可以将其设置回初始值
function clear(context, color)
{
var tmp = context.fillStyle;
context.fillStyle = color;
context.fillRect(0, 0, context.canvas.width, context.canvas.height);
context.fillStyle = tmp;
}
一个简单但可读性不强的方法是这样写:
var canvas = document.getElementId('canvas');
// after doing some rendering
canvas.width = canvas.width; // clear the whole canvas
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()
}
Context.clearRect(starting width, starting height, ending width, ending height);
示例:context.clearRect(0, 0, canvas.width, canvas.height);
我总是用这个
ctx.clearRect(0, 0, canvas.width, canvas.height)
window.requestAnimationFrame(functionToBeCalled)
笔记
结合 clearRect 和 requestAnimationFrame 允许更流畅的动画,如果这是你想要的
最快的方法:
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
clearRect
慢约 700 倍。
如果你只使用 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);">
希望它可以帮助某人。
这是一个带有“清除画布”按钮的手绘画布。
请参阅此现场示例的画布,您可以在其上进行绘制,并在需要时将其清除以重新绘制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) { 绘画 = true; ctx.fillStyle = "#ffffff"; lastX = e.pageX - this.offsetLeft; lastY = e.pageY - this.offsetTop; }; canvas.onmouseup = function(e){ 绘画 = false; } canvas.onmousemove = function(e) { if (painting) { mouseX = e.pageX - this.offsetLeft; mouseY = e.pageY - this.offsetTop; // 找到 var x1 = mouseX, x2 = lastX, y1 = mouseY, y2 = lastY 之间的所有点;变陡 = (Math.abs(y2 - y1) > Math.abs(x2 - x1));如果(陡峭){ var x = x1; x1 = y1; y1 = x;变量 y = y2; y2 = x2; x2 = y; } if (x1 > x2) { var x = x1; x1 = x2; x2 = x;变量 y = y1; y1 = y2; y2 = y; } var dx = x2 - x1, dy = Math.abs(y2 - y1), error = 0, de = dy / dx, yStep = -1, y = y1;如果 (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 ); } 错误 += 德; if (error >= 0.5) { y += yStep;错误-= 1.0; } } lastX = mouseX;最后一个 = 鼠标 Y; } } 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;字体大小:8px!重要;位置:绝对; top:1px;} #canvas{border-radius:10px}
这些都是如何清除标准画布的很好的例子,但是如果你使用的是 paperjs,那么这将起作用:
在 JavaScript 中定义一个全局变量:
var clearCanvas = false;
从您的 PaperScript 定义:
function onFrame(event){
if(clearCanvas && project.activeLayer.hasChildren()){
project.activeLayer.removeChildren();
clearCanvas = false;
}
}
现在,无论您将 clearCanvas 设置为 true,它都会清除屏幕上的所有项目。
clearRect
,您需要有一个未转换的上下文,或者跟踪您的实际边界。context.clearRect(0, 0, context.canvas.width, context.canvas.height)
。它实际上是同一件事,但依赖较少(1 个变量而不是 2 个)