为什么在HTML5中我无法使用另一个空画布清除画布?

4
const buffer = document.createElement('canvas');
const context = buffer.getContext('2d');
const canvas = document.getElementById('canvas');
const screen = canvas.getContext('2d');
// buffer canvas and screen canvas have same width and height

// draw a circle on buffer canvas
context.beginPath();
context.arc(50, 50, 10, 0, Math.PI * 2);
context.fillStyle = 'rgba(156, 39, 176,1)';
context.fill();

// render to screen canvas (working)
screen.drawImage(buffer, 0, 0);

// clear canvas when click
canvas.addEventListener('click', () => {
  context.clearRect(0, 0, buffer.width, buffer.height);
  screen.drawImage(buffer, 0, 0);   // not working
  // only working with `screen.clearRect(0, 0, canvas.width, canvas.height);`
})

像上面的代码一样,当使用一个空画布来清除另一个画布时,它不起作用。(仅限HTML,带有<canvas id="canvas"></canvas>标记)。在https://jsfiddle.net/wjvtzng7/上查看实时演示。

在JavaScript中,您只能获得对象的引用。如果您有两个对象,则有两个完全相同的对象,如果您更改其中一个,则也更改了另一个。这就是为什么您的函数不像您想象的那样工作的原因。 - episch
HTML5只允许一个canvas实例吗? - sabertazimi
不,那不是我想要的意思。我的意思是,在你的JavaScript中,这样写: const buffer = document.createElement('canvas'); const canvas = document.getElementById('canvas'); 这样就会保证buffer和canvas都引用同一块画布,对buffer或canvas所做的任何更改都会直接影响这两个变量,它们只是该对象的引用。 - episch
你可以尝试删除 line 14 中的 screen.drawImage(buffer, 0, 0); 并查看结果。实时演示请访问 https://jsfiddle.net/wjvtzng7/ - sabertazimi
2
fillRect并不能真正清除buffercanvas(它在line 14中也起作用)。 - sabertazimi
显示剩余2条评论
1个回答

2
如果我们把你正在做的事情写下来,就是:
一个离屏画布“buffer”,和一个可见画布“screen”。
逐步进行:
在“缓冲区”上画一个圆圈。在这个阶段,“缓冲区”代表一个圆形,“屏幕”代表一个空图像(透明像素)。
在“屏幕”画出“缓冲区”。在这里,“缓冲区”代表一个圆形,“屏幕”也代表一个圆形。
清除“缓冲区”。在这里,“缓冲区”代表一个空图像(透明像素),而“屏幕”代表一个圆形。
在“屏幕”画出“缓冲区”。在这里,“缓冲区”代表一个空图像(透明像素),而“屏幕”代表一个圆形。
似乎你的困惑来自于最后一条项目。但是这个操作可以被重新解释为:
  • 将一个空白图像(透明像素)绘制到一个代表圆形的图像中。

这确实什么都不做...至少在正常的合成模式source-over中,绘制完全透明的像素不会有任何效果。关于它的更多信息,请参见alpha-compositing

所以,如果你想要清除你的"屏幕"画布,你确实需要使用screen上下文的clearRect()方法进行清除。还有其他方法,但不建议使用。



现在,我感觉我也应该指出,除了“source-over”之外,还有其他合成模式可用,而您期望的实际上可以通过其中之一来完成:复制。

const buffer = document.createElement('canvas');
const context = buffer.getContext('2d');
const canvas = document.getElementById('canvas');
const screen = canvas.getContext('2d');

// initialize
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
buffer.width = window.innerWidth;
buffer.height = window.innerHeight;
// draw a circle
context.beginPath();
context.arc(50, 50, 10, 0, Math.PI * 2);
context.fillStyle = 'rgba(156, 39, 176,1)';
context.fill();

// render to screen canvas
screen.drawImage(buffer, 0, 0);

// clear canvas when click
canvas.addEventListener('click', () => {
  context.clearRect(0, 0, buffer.width, buffer.height);
  // only the next drawing operation on screen will be visible
  // everything else will get cleared out
  screen.globalCompositeOperation = "copy";
  screen.drawImage(buffer, 0, 0);
  // set back to default mode
  screen.globalCompositeOperation = "sourc-over";
})
<canvas id="canvas"></canvas>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接