Igal
Igal

Reputation: 6083

Animating 3 images in canvas

I need to animate 3 images of clouds in canvas, they should be moving on X axis and once they disappear on the right side they should reappear on the left. Each cloud should be on different X and Y axis starting positions and they should be moving with different speed.

First I tried to create only 1 cloud animation and this is what I came up with:

var canvas, context, docWidth, docHeight;

window.onload = function(){
    docWidth = window.innerWidth;
    docHeight =  window.innerHeight
    canvas = document.getElementById('canvas');
    context = canvas.getContext('2d')
    resizeCanvas(docWidth, docHeight);
    drawCloud(0, 0, docWidth, docHeight);
}

function resizeCanvas(width, height){
    canvas.width = docWidth;
    canvas.height = docHeight;
}

function drawCloud(x,y,width, height){
    var img = new Image();
    img.src = 'images/cloud1.png';

    img.onload = function(){
        context.save();
        context.clearRect(0,0,width,height);
        imageWidth = img.naturalWidth;
        imageHeight = img.naturalHeight;
        context.drawImage(img,x-imageWidth,10);
        context.restore();

        if(x >= width+imageWidth){
            x=0-imageWidth/2;
        } else {
            x += 3;
        }
        var loopTimer = setTimeout('drawCloud('+x+','+y+','+width+','+height+')',24);
    }
}

This works just fine, I see the cloud animation, it disappears on the right side and reappears on the left. Now with 3 images that's where things get complicated. I tried an OOP approach:

First in my Canvas element I tried to preload images:

<canvas id="canvas" width="0px" height="0px">
<script type="text/javascript">
    <!--//--><![CDATA[//><!--
        var images = new Array()
        function preload() {
            for (i = 0; i < preload.arguments.length; i++) {
                images[i] = new Image()
                images[i].src = preload.arguments[i]
            }
        }
        preload(
            "images/cloud1.png",
            "images/cloud2.png",
            "images/cloud3.png"
        )
    //--><!]]>
</script>
</canvas>

Then I tried to create the Cloud objects:

function Cloud (x, y, width, height, filename, velocity, rate) {
    this.x = x;
    this.y = y;
    this.width = width;
    this.height = height;
    this.filename = filename;
    this.velocity = velocity;
    this.rate = rate;
}

Cloud.prototype = {
    constructor:Cloud,
    moveCloud:function(imageWidth){
        if(x >= width+imageWidth){
            x=0-imageWidth/2;
        } else {
            x += velocity;
        }
    },
    getFilename:function(){
        return this.filename;
    },
    getX:function(){
        return this.x;
    },
    getY:function(){
        return this.y;
    }
}

Then this drawing function:

function drawCloud(clouds, width, height){
    var img;
    var arrLength = clouds.length;

        context.save();
        context.clearRect(0,0,width,height);
        for(var i=0; i<arrLength; i++){
            var Cloud = clouds[i];
            img = new Image();
            img.src = Cloud.getFilename();
            imageWidth = img.naturalWidth;
            imageHeight = img.naturalHeight;
            context.drawImage(img, Cloud.getX()-imageWidth, Cloud.getY());
            clouds[i].moveCloud(imageWidth);
        }

        context.restore();

        var loopTimer = setTimeout('drawCloud('+clouds+', '+width+', '+height+')',24);

}

And finally I call for this function in my window.onload:

var canvas, context, docWidth, docHeight;

window.onload = function(){
    docWidth = window.innerWidth;
    docHeight =  window.innerHeight
    canvas = document.getElementById('canvas');
    context = canvas.getContext('2d')
    resizeCanvas(docWidth, docHeight);

    var cloud1 = new Cloud(0, 10, docWidth, docHeight, 'images/cloud1.png', 3, 24);
    var cloud2 = new Cloud(400, 10, docWidth, docHeight, 'images/cloud2.png', 5, 24);
    var cloud3 = new Cloud(160, 10, docWidth, docHeight, 'images/cloud3.png', 1, 24);
    var clouds = [cloud1, cloud2, cloud3];
    drawCloud(clouds, docWidth, docHeight);
}

Now I don't even see the clouds images on canvas, not to mention their animation. Any idea how to make it work?

Upvotes: 0

Views: 1154

Answers (1)

Variant
Variant

Reputation: 17365

I improved your fiddel and made it work: http://jsfiddle.net/z3azsn5a/3/

There were a few things I had to fix, you can compare your original source to mine but the most important ones were:

  1. setTimeOut should get a function not a built string with parameters
  2. You redefined Cloud in an inner scope, not sure this was causing any problem but it's a bad practice.
  3. there was javascript inside the canvas element
  4. the jsfiddle was configured to have the code inside the onload event and you declared that event yourself, thus your window.onload was not running

Upvotes: 2

Related Questions