我知道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
图片上方不应有白色层,文字应为白色而不是图片。
答案 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>