Reputation: 9076
I am trying to create water drop falling effect on canvas.I created some sample drops using array.to animate it i mean to change their positions i introduced a setTimeout function.it worked for single water drop.since there are multiple drops on my canvas it is not working anymore.drops remain still.how the setTimeout function can be used to animate all the individual drops?
here is the fiddle jsfiddle
animate effect for an individual drop single drop animation
<html>
<head>
</head>
<body>
<script>
function makeit(){
var canvas=document.getElementById("mycanvas");
var ctx=canvas.getContext('2d');
canvas.width=600;
canvas.height=600;
canvas.style.border="1px solid black";
var drop=function (x,y){
ctx.save();
ctx.fillStyle="orange";
ctx.fillRect(0,0,canvas.width,canvas.height);
ctx.fill();
ctx.fillStyle="red";
ctx.moveTo(x-5,y);
ctx.lineTo(x,y-7);
ctx.lineTo(x+5,y);
ctx.arc(x,y,5,0,Math.PI);
ctx.closePath();
ctx.fill();
ctx.restore();
y=y+3;
if(y==canvas.height){
y=0;
}
var m=setTimeout('drop('+x+','+y+')',20);
}
var xpos=[10,20,30,40,50,60,70,70,76];
var ypos=[30,20,60,80,76,90,30,40,79];
for(i=0;i<xpos.length;i++){
drop(xpos[i],ypos[i]);
}
}
window.onload=makeit;
</script>
<canvas id="mycanvas" ></canvas>
</body>
</html>
Upvotes: 3
Views: 6332
Reputation: 105035
Here's another option using window.requestAnimationFrame to animate your drops:
Define a Drop pseudo-class which knows its x,y position and the speed at which it falls
Add Drop methods to redraw the drop on the canvas and increment its Y value to make it fall.
Create an animation loop with window.requestAnimationFrame to (1) clear the canvas by filling it with an orange background, (2) make each drop fall and (3) redraw each drop on the canvas.
Annotated code and a Demo: http://jsfiddle.net/m1erickson/m8UPC/
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; }
canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
// a flag to let you stop the animation
var ok2animate=true;
// a Drop pseudo-class
// Properties: current x,y & the speed at which this drop falls
function Drop(){
this.x=Math.random()*(canvas.width-20);
this.y=-Math.random()*20;
this.fallRate=1;
}
// draw this drop on the canvas
Drop.prototype.draw=function(){
ctx.beginPath();
ctx.moveTo(this.x-5,this.y);
ctx.lineTo(this.x,this.y-7);
ctx.lineTo(this.x+5,this.y);
ctx.arc(this.x,this.y,5,0,Math.PI);
ctx.closePath();
ctx.fill();
return(this);
}
// make this drop "fall"
Drop.prototype.fall=function(){
this.y+=this.fallRate;
return(this);
}
// an animation loop to make some test drops fall
function animate(){
// request another animation frame
if(ok2animate){
requestAnimationFrame(animate);
}
// fill the canvas with the orange background
ctx.fillStyle="orange";
ctx.fillRect(0,0,canvas.width,canvas.height)
// make all drops fall and then redraw them
ctx.fillStyle="red";
for(var i=0;i<drops.length;i++){
drops[i].fall().draw();
}
}
// let the user stop the animation
$("#stop").click(function(){
ok2animate=false;
});
// an array of objects each representing 1 drop
var drops=[];
// add some test drops
for(var i=0;i<10;i++){
drops.push(new Drop());
}
// start the animation
requestAnimationFrame(animate);
}); // end $(function(){});
</script>
</head>
<body>
<button id="stop">Stop</button><br>
<canvas id="canvas" width=300 height=300></canvas>
</body>
</html>
Upvotes: 2
Reputation: 2721
Here is how I would do what you're trying to :
function makeit() {
// These variables can be used in the drawing functions
var canvas = document.getElementById("mycanvas");
var ctx = canvas.getContext('2d');
var drops = [];
// Init canvas & drops
init();
// Make the 3rd drop falls
var fall = setInterval(function () {
updateDrop(3);
}, 200);
// Make the 7th drop falls
var fall2 = setInterval(function () {
updateDrop(7);
}, 400);
// Stop the 3rd drop at anytime with this code :
// clearInterval(fall);
// Functions
function init() {
canvas.width = 600;
canvas.height = 600;
canvas.style.border = "1px solid black";
// Draw background
drawBackground();
// Draw drops
var xpos = [10, 20, 30, 40, 50, 60, 70, 70, 76];
var ypos = [30, 20, 60, 80, 76, 90, 30, 40, 79];
for (i = 0; i < xpos.length; i++) {
drops.push(drawDrop(xpos[i], ypos[i]));
}
}
function drawBackground() {
ctx.fillStyle = "orange";
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fill();
}
function drawDrop(x, y) {
ctx.beginPath();
ctx.fillStyle = "red";
ctx.moveTo(x - 5, y);
ctx.lineTo(x, y - 7);
ctx.lineTo(x + 5, y);
ctx.arc(x, y, 5, 0, Math.PI);
ctx.closePath();
ctx.fill();
return {
'x': x,
'y': y
};
}
function updateDrop(dropNumber) {
var dropNumber = dropNumber - 1; //Because 0 is first
// Update position
if (drops[dropNumber].y >= canvas.height) {
drops[dropNumber].y = 0;
} else {
drops[dropNumber].y += 3;
}
//Draw background
drawBackground();
//Draw drops
for (i = 0; i < drops.length; i++) {
drawDrop(drops[i].x, drops[i].y);
}
}
}
window.onload = makeit;
Then, if you want to stop the 3rd drop from falling, you can execute this line :
clearInterval(fall);
Just look at the JSFiddle : http://jsfiddle.net/Oliboy50/QHRaS/5/
Don't forget ctx.beginPath()
before drawing lines, else you won't be able to clear them.
Upvotes: 2