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

时间:2018-11-12 15:27:08

标签: javascript html html5 canvas html5-canvas

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

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

上的实时演示

1 个答案:

答案 0 :(得分:2)

如果我们记下您在做什么,我们会得到:

一个屏幕外画布“ 缓冲区”和一个可见画布“ 屏幕”。

逐步

  • 在“ 缓冲区”上绘制一个圆圈
    在这个阶段
    • 缓冲区”表示一个
    • 屏幕”代表一个空白图片(透明像素)
  • 在“ 屏幕”画布上绘制“ 缓冲区
    • 缓冲区”代表一个圆圈
    • 屏幕”代表一个圆圈
  • 清除“ 缓冲区
    • 缓冲区”代表一个空图片(透明像素)
    • 屏幕”代表一个圆圈
  • 在“ 屏幕”画布上绘制“ 缓冲区
    • 缓冲区”代表一个空图片(透明像素)
    • 屏幕”代表一个圆圈

您的困惑似乎来自最后一个子弹。但是此操作可以改写为

  • 在表示的图像上绘制空图像(透明像素)

这确实没有任何作用……至少在正常的 compositing 模式 source-over 中,在该模式下绘制完全透明的像素不会执行任何操作。有关更多信息,请参见alpha-compositing

因此,如果您希望清除“ 屏幕”画布,则确实需要使用clearRect()上下文的screen方法清除它。 还有其他方法,但不要使用。



现在,我觉得我还应该指出,除了{em> source-over 以外,还有其他compositing modes种可用的方法,并且您实际上可以使用以下方法之一完成操作:复制

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>