Creating Animated Particles in Water Effect using JavaScript

Creating Animated Particles in Water Effect using JavaScript

3 25570
Creating Animated Particles in Water Effect using JavaScript

Water simulation with javascript. Today we continue JavaScript lessons, and our article will about using js in modeling of water effects. Sometimes we can create very interesting solutions using ordinary Javascript.

Here are sample and downloadable package:

Live Demo

Step 1. HTML

As usual, we start with the HTML.

This is our main page code with all samples.

index.html

<link rel="stylesheet" href="css/main.css" type="text/css" media="all" />
<script src="js/main.js" type="text/javascript"></script>
<div class="example">
<img id="unit" src="unit.png" style="visibility:hidden" > 
<div id="main"></div> 
<div id="fps"></div> 
</div>

Step 2. CSS

Here are used CSS styles.

css/main.css

body{background:#eee;font-family:Verdana, Helvetica, Arial, sans-serif;margin:0;padding:0}
.example{position:relative;background:#FFF;width:600px;height:600px;border:1px #000 solid;margin:20px auto;padding:20px;-moz-border-radius:3px;-webkit-border-radius:3px}
#main{position:absolute;width:520px;height:520px;background:#000;outline:#f0f solid 3px;overflow:hidden;cursor:pointer}
#fps{position:absolute;right:20px;top:20px}

Step 3. JS

Here are our main control JS file.

js/main.js

var wp = function () { 
// variables
var scr, grid, npart, diam, nx, ny, nw, nh, gw, gh; 
var xm = 0; 
var ym = 0; 
var obj = new Array(npart); 
var down = false; 
var fps = 0; 
// add listeners
var addEvent = function  (o, e, f) { 
if (window.addEventListener) o.addEventListener(e, f, false); 
else if (window.attachEvent) r = o.attachEvent('on' + e, f); 
}
// resize function
var resize = function () { 
nw = scr.offsetWidth; 
nh = scr.offsetHeight; 
var o = scr; 
for (nx = 0, ny = 0; o != null; o = o.offsetParent) { 
nx += o.offsetLeft; 
ny += o.offsetTop; 
} 
gw = Math.round(nw / pdiam); 
gh = Math.round(nh / pdiam); 
} 
// particle constructor
var Particle = function (img) { 
this.x = Math.random() * nw; 
this.y = Math.random() * nh; 
this.vx = 0; 
this.vy = 0; 
this.dx = 0; 
this.dy = 0; 
this.wi = img.width * .5; 
this.hi = img.height * .5; 
// new html elements
var d = document.createElement('img'); 
d.style.position = "absolute"; 
d.style.left = "-1000px"; 
d.src = img.src; 
scr.appendChild(d); 
this.plo = d.style; 
} 
// move particle
Particle.prototype.move = function () { 
this.x  += this.dx; 
this.y  += this.dy; 
this.vx += this.dx; 
this.vy += this.dy; 
this.dx  = 0; 
this.dy  = 0; 
// DOM
this.plo.left = Math.round(this.x - this.wi) + 'px'; 
this.plo.top  = Math.round(this.y - this.hi) + 'px'; 
}
// water simulation
Particle.prototype.physics = function () { 
// mouse influence
if (down) { 
var dx = this.x - xm; 
var dy = this.y - ym; 
var d = Math.sqrt(dx * dx + dy * dy); 
if (d < pdiam * 2) { 
this.dx += dx / d; 
this.dy += dy / d; 
} 
} 
// gravity and acceleration
this.vy += .2; 
this.x += this.vx; 
this.y += this.vy; 
// screens limits
if (this.x < pdiam * .5) this.dx += (pdiam * .5 - this.x); 
else if (this.x > nw - pdiam * .5) this.dx -= (this.x - nw + pdiam * .5); 
if (this.y < pdiam * .5) this.dy += (pdiam * .5 - this.y); 
else if (this.y > nh - pdiam * .5) this.dy -= (this.y - nh + pdiam * .5); 
// grid coordinates
var gx = Math.round(this.x / pdiam); 
var gy = Math.round(this.y / pdiam); 
// neightbors constraints
for (var ix = gx - 1; ix <= gx + 1; ix++) { 
for (var iy = gy - 1; iy <= gy + 1; iy++) { 
var g = grid[iy * gw + ix] || []; 
for (j = 0, l = g.length; j < l; j++) { 
var that = g[j]; 
var dx = that.x - this.x; 
var dy = that.y - this.y; 
var d = Math.sqrt(dx * dx + dy * dy); 
if (d < pdiam && d > 0) { 
dx = (dx / d) * (pdiam - d) * .25; 
dy = (dy / d) * (pdiam - d) * .25; 
this.dx -= dx; 
this.dy -= dy; 
that.dx += dx; 
that.dy += dy; 
} 
} 
} 
} 
// update neighbors array
if (!grid[gy * gw + gx]) grid[gy * gw + gx] = [this]; 
else grid[gy * gw + gx].push(this); 
}
// loop
var run = function () { 
fps++; 
grid = new Array(gw * gh); 
for(var i = 0; i < npart; i++) obj[i].physics(); 
for(var i = 0; i < npart; i++) obj[i].move(); 
setTimeout(run, 1); 
}
return { 
// initialization
init : function (n, d) { 
scr = document.getElementById('main'); 
npart = n; 
pdiam = d; 
// subscribing to events
addEvent(document, 'mousemove', function (e) {
if (window.event) e = window.event;
xm = e.clientX - nx;
ym = e.clientY - ny;
});
addEvent(window, 'resize', resize);
addEvent(document, 'mousedown', function(e) {if (e.preventDefault) e.preventDefault(); down = true;return false;});
addEvent(document, 'mouseup', function() { down = false;return false;});
document.onselectstart = function () { return false; }
scr.ondrag = function () { return false; }
// fps countrt
setInterval(function() { 
document.getElementById('fps').innerHTML = fps + ' FPS'; 
fps = 0; 
}, 1000);
// starting
resize(); 
for (var i = 0; i < npart; i++) obj[i] = new Particle(document.getElementById('unit')); 
run(); 
} 
} 
}(); 
window.onload = function() { 
wp.init(50, 45); 
}

This is most interesting and important part of our article. Here we creating our main object – scene, and adding particle to it. Also added several events (mainly for mouse). All this looks like low level coding, but don`t worry – this is mainly mathematics.


Live Demo

Conclusion

Hope that you was happy to play with thas robo-water :) If is you were wondering – do not forget to thank. I would be grateful for your interesting comments. Good luck!

SIMILAR ARTICLES

jQuery Mobile Lesson 6

0 10
jQuery Mobile Lesson 5

0 10

3 COMMENTS

Leave a Reply