Javascript Canvas clear/ redraw

35,248

Canvas workflow goes like this:

  1. Draw some things on the canvas.
  2. Calculate changes to the position of those things.
  3. Clear the canvas.
  4. 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.

But you can save the definition of your things in javascript object:

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

Then you can "move" your things using the javascript objects:

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>

Share:
35,248
tree
Author by

tree

Updated on June 10, 2020

Comments

  • tree
    tree almost 4 years

    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.

    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);
    }
    
  • tree
    tree almost 9 years
    but that seems to be the order of what i'm doing: drawImage, fill, clear, drawImage, fill
  • markE
    markE almost 9 years
    Well, I tried to get your code started, but you've left so much out that I couldn't even get it to start running :-( Having said that, when you set globalCompositeOperation='source-atop' all drawings after that will only be drawn over existing non-transparent pixels. Compositing must be turned off or it's effects will continue forever. Perhaps that's where your code is going wrong. To help further, we'll need to see mcve: stackoverflow.com/help/mcve