Reputation: 6083
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
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:
Cloud
in an inner scope, not sure this was causing any problem but it's a bad practice.canvas
elementUpvotes: 2