在globalComposite操作之后完全清除HTML5画布的正确方法是什么?

时间:2019-05-17 07:44:48

标签: html5 image canvas

我知道this Q/A may be related,但是使用那里的解决方案我无法完全清除画布。
设置上下文的globalCompositeOperation之后,调用clearRect()后,我的画布仍具有一层。

canvas.width = canvas.width解决方案可以解决这个问题,但是there说并非所有浏览器都支持它,这也是一种不好的做法。

在globalComposite操作之后,我们如何正确清除画布?

const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
const img = new Image();
const reader = new FileReader();
const filterRed = document.getElementById("red");
const addText = document.getElementById("addText");
const upload = document.getElementById("upload");

upload.addEventListener("change", function(evnt) {
  const file = evnt.target.files[0];
  reader.onload = function(e) {
    img.src = e.target.result;
    img.onload = function() {
      ctx.drawImage(img, 0, 0, canvas.clientWidth, canvas.height);
    };
  };
  reader.readAsDataURL(file);
});

filterRed.addEventListener("click", function(e) {
  // redraw image again to prevent double clicking
  // behave not normaly
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
  ctx.fillStyle = "red";
  ctx.filter = "contrast(0.6) brightness(100%)";
  ctx.globalCompositeOperation = "multiply";
  ctx.fillRect(0, 0, canvas.width, canvas.height);
});

addText.addEventListener("click", function(e) {
  // redraw all things again
  // but here not behave normaly
  canvas.toBlob(function(blob) {
    img.src = URL.createObjectURL(blob);
    img.onload = function() {
      // using canvas.width = canvas.width solve the problem
      // but it is not the right way
      canvas.width = canvas.width;
      ctx.drawImage(img, 0, 0, canvas.width, canvas.width);
      ctx.font = "50px serif";
      ctx.fillStyle = "#00ff00";
      ctx.fillText("Hello world", 50, 90);
    };
  });
});
<p>
  Upload Image First
</p>
<label for="upload">Click to select file</label>
<input type="file" accept="image/*|video/*" id="upload" hidden>


<canvas id="canvas"></canvas>
<button id="red">
  red
</button>
<button id="addText">
  redraw with text
</button>

在这里复制codesandbox

图片上方不应有白色层,文字应为白色而不是图片。

1 个答案:

答案 0 :(得分:1)

您必须将上下文globalCompositeOperation重新初始化为其默认值:source-over

请注意,您可能还需要将上下文转换矩阵重置为其默认值,这可以通过使用setTransform方法和身份矩阵1, 0, 0, 1, 0, 0来完成。

现在唯一可能阻止clearRect正常工作的是活动剪切规则。因此,当您使用clip()时,请务必始终先调用ctx.save(),然后再调用ctx.restore()以禁用剪切区域(或完全不使用clip )。

const ctx = canvas.getContext('2d');
draw_btn.onclick = drawStuffs;
simpleclear_btn.onclick = brokenClear;
better_btn.onclick = betterClear;

drawStuffs();

function drawStuffs() {
  ctx.fillStyle = 'rgba(0,34,123, .75)';
  ctx.fillRect(0,0,45,45);
  ctx.globalCompositeOperation = 'source-atop';
  ctx.fillStyle = "red";
  ctx.translate(25, 25);
  ctx.fillRect(0,0,45,45);
}

function brokenClear() {
  ctx.clearRect(0,0,canvas.width,canvas.height);
}
function betterClear() {
 ctx.globalCompositeOperation = 'source-over';
 ctx.setTransform(1,0,0,1,0,0);
 ctx.clearRect(0,0,canvas.width,canvas.height);
}
<button id="draw_btn">draw stuff</button>
<button id="simpleclear_btn">simple clear (broken)</button>
<button id="better_btn">better clear</button>


<canvas id="canvas"></canvas>