JavaScript画布清除/重绘

7
我尝试过用谷歌搜索答案,但一直在打转...... 如果我清除矩形(使用clearRect),那么图像就不会重新绘制。 然而,如果我不清除图像,它们只是叠加。 我想要的是清除当前图像,然后用新的绘制。 我错过了什么吗? 这与图片加载有关吗? 如果这是一个重复的问题,对不起,我找不到确切的答案-我尝试了其他人建议的方法,但结果很差。

http://jsfiddle.net/bxeuhh4h/

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

我刚刚尝试使用canvas.width = canvas.width; - 我是否有任何理由不使用它? - tree
只需在您的填充函数底部添加两行代码:ctx.globalCompositeOperation = "source-over";ctx.globalAlpha = 1;,您链接的fiddle应该就可以开始工作了。 - Niddro
2个回答

6

Canvas工作流程如下:

  1. 在画布上绘制一些元素。
  2. 计算这些元素的位置变化。
  3. 清空画布。
  4. 在新位置上重新绘制所有元素。

Canvas不会“记住”它在哪里绘制了你的元素,因此你不能直接命令你的元素移动。

但你可以在JavaScript对象中保存你的元素定义:

var myCircle={
    centerX:50,
    centerY:50,
    radius:25,
    fill:'blue'
}

然后你可以使用 JavaScript 对象来“移动”你的东西:
myCircle.centerX += 5;

然后在它们的新位置上重新绘制。将重绘代码放入一个函数中可以使重绘变得更加容易:

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

综合起来:

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>


但这似乎是我正在做的顺序:drawImage、fill、clear、drawImage、fill。 - tree
嗯,我试图启动你的代码,但是你留下了太多空缺,以至于我甚至无法让它开始运行 :-( 话虽如此,当你设置 globalCompositeOperation='source-atop' 后,所有在此之后的绘画都只会被绘制在现有的非透明像素上。混合必须被关闭,否则其效果将永远持续。也许这就是你的代码出错的地方。为了进一步帮助,我们需要看到 mcve:http://stackoverflow.com/help/mcve - markE

6
你需要在这里添加一个beginPath()rect()会将矩形累加到路径中,clearRect()不会清除它们。还要重置组合模式和alpha值,因为它们是粘性的。
如果你使用fillRect()而不是rect() + fill(),就可以避免使用beginPath()(下面附有示例),因为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;    
}

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