Javascript Canvas 清除/重绘
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/30738717/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Javascript Canvas clear/ redraw
提问by tree
I've tried googling the answer to this but i'm just going around in circles.... If I clear the rect (using clearRect) then the image doesn't redraw after. However, if I don't clear the images just stack. What I want it to clear the current image and then draw with new one. What am I missing? Does it have something to do with the image Load ? Sorry if this is a question repeat, I couldn't find the exact answer to this- and I tried what others suggested but results were poor.
我试过在谷歌上搜索这个答案,但我只是在兜圈子……如果我清除了矩形(使用 clearRect),那么图像不会重绘。但是,如果我不清除图像只是堆叠。我希望它清除当前图像,然后用新图像绘制。我错过了什么?它与图像 Load 有关系吗?对不起,如果这是一个重复的问题,我找不到确切的答案 - 我尝试了其他人的建议,但结果很差。
function clear() {
var canvasTemp = document.getElementById(imgSection);
var ctxTemp = canvasTemp.getContext("2d");
ctxTemp.clearRect(0, 0, 500, 500);
}
function fillColorOrPattern(imgSection,currentcolor){
if ((oldcolor !== currentcolor) || (oldxImgToBeFilled !== xImgToBeFilled)){
clear();
}
imgFill.onload = function () {
imgToBeFilled.onload = function () {
if ((oldcolor !== currentcolor) || (oldxImgToBeFilled !== xImgToBeFilled)){
fill(imgSection,currentcolor)
}
};
imgToBeFilled.src = xImgToBeFilled;
}
imgFill.src = xImgFill;
}
function fill(imgSection,currentcolor){
canvas = document.getElementById(imgSection);
ctx = canvas.getContext("2d");
ctx.drawImage(imgToBeFilled, 0, 0);
ctx.globalCompositeOperation = "source-atop";
console.log(isItColorOrPattern);
if (isItColorOrPattern == "color"){
ctx.rect(0, 0, canvas.width, canvas.height);
console.log("currentcolor: " + currentcolor);
ctx.fillStyle = getColor(currentcolor);
console.log(getColor(currentcolor));
ctx.fill();
}else{
var pattern = ctx.createPattern(imgFill, 'repeat');
console.log("canvas.width: " + canvas.width);
console.log("xImgFill: " + xImgFill);
console.log(canvas.getContext);
ctx.rect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = pattern;
ctx.fill();
}
ctx.globalAlpha = .10;
ctx.drawImage(imgToBeFilled, 0, 0);
ctx.drawImage(imgToBeFilled, 0, 0);
ctx.drawImage(imgToBeFilled, 0, 0);
oldcolor = currentcolor;
oldxImgToBeFilled = xImgToBeFilled;
}
$(window).load(function(){
imgToBeFilled = new Image();
imgFill = new Image();
fillColorOrPattern(imgSection,currentcolor);
}
采纳答案by markE
You need to add a beginPath()in there. rect()will accumulate rectangles to the path, clearRect()won't clear those. Also reset comp. mode and alpha as they are sticky.
你需要beginPath()在那里添加一个。rect()将累积矩形到路径,clearRect()不会清除那些。也重置补偿。mode 和 alpha 因为它们是粘性的。
You could avoid beginPath()if you use fillRect()instead of rect()+ fill()(added example below) as fillRect()does not add to the path.
beginPath()如果您使用fillRect()而不是rect()+ fill()(下面添加的示例),fillRect()则可以避免,因为不会添加到路径中。
function fill(imgSection,currentcolor){
// these should really be initialized outside the loop
canvas = document.getElementById(imgSection);
ctx = canvas.getContext("2d");
// clear canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
// clear path
ctx.beginPath();
// use default comp. mode
ctx.globalCompositeOperation = "source-over";
// reset alpha
ctx.globalAlpha = 1;
ctx.drawImage(imgToBeFilled, 0, 0);
ctx.globalCompositeOperation = "source-atop";
if (isItColorOrPattern === "color"){
// rect() accumulates on path
ctx.rect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = getColor(currentcolor);
ctx.fill();
// instead of rect() + fill() you could have used:
// fillRect() does not accumulate on path
// fillRect(0, 0, canvas.width, canvas.height);
}
else {
var pattern = ctx.createPattern(imgFill, 'repeat');
ctx.rect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = pattern;
ctx.fill();
}
ctx.globalAlpha = .1;
ctx.drawImage(imgToBeFilled, 0, 0);
ctx.drawImage(imgToBeFilled, 0, 0);
ctx.drawImage(imgToBeFilled, 0, 0);
oldcolor = currentcolor;
oldxImgToBeFilled = xImgToBeFilled;
}
回答by markE
Canvas workflow goes like this:
Canvas 工作流程是这样的:
- Draw some things on the canvas.
- Calculate changes to the position of those things.
- Clear the canvas.
- Redraw all the things in their new positions.
- 在画布上画一些东西。
- 计算这些东西的位置变化。
- 清除画布。
- 重新绘制所有的东西在他们的新位置。
Canvas does not "remember" where it drew your things so you cannot directly order your things to move.
Canvas 不会“记住”它把你的东西画在哪里,所以你不能直接命令你的东西移动。
But you can save the definition of your things in javascript object:
但是您可以将事物的定义保存在 javascript 对象中:
var myCircle={
centerX:50,
centerY:50,
radius:25,
fill:'blue'
}
Then you can "move" your things using the javascript objects:
然后你可以使用 javascript 对象“移动”你的东西:
myCircle.centerX += 5;
And then redraw the things at their new positions. Putting the redraw code in a function makes redrawing easier:
然后在它们的新位置重新绘制这些东西。将重绘代码放在函数中使重绘更容易:
function redraw(){
// clear the canvas
ctx.clearRect(0,0,canvas.width,canvas.height);
// redraw one or more things based on their javascript objects
ctx.beginPath();
ctx.arc( myCircle.centerX, myCircle.centerY, myCircle.radius, 0, Math.PI*2 );
ctx.closePath();
ctx.fillStyle=myCircle.fill;
ctx.fill();
}
Putting it all together:
把它们放在一起:
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var myCircle={
centerX:50,
centerY:50,
radius:25,
fill:'blue'
}
redraw();
document.getElementById('move').addEventListener('click',function(){
myCircle.centerX+=5;
redraw();
});
function redraw(){
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.beginPath();
ctx.arc( myCircle.centerX, myCircle.centerY, myCircle.radius, 0, Math.PI*2 );
ctx.closePath();
ctx.fillStyle=myCircle.fill;
ctx.fill();
}
body{ background-color: ivory; }
#canvas{border:1px solid red; margin:0 auto; }
<button id=move>Move</button>
<br>
<canvas id="canvas" width=300 height=300></canvas>

