Today I continue with JavaScript examples, and this article will about using javascript in modeling of water effects. This will emulate water drop effect at images. We should click at image in desired place to see this effect.
RippleEffectStyles.CSS
Step 1. HTML
As usual, we start with the HTML.
This is our main page code with all samples
RippleEffect.html
RippleEffect.html
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Water drops effect</title>
<link rel="stylesheet" href="css/main.css" type="text/css" />
<script src="js/vector2d.js" type="text/javascript" charset="utf-8"></script>
<script src="js/waterfall.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div class="example">
<h3><a href="#">Water drops effect</a></h3>
<canvas id="water">HTML5 compliant browser required</canvas>
<div id="switcher">
<img onclick='watereff.changePicture(this.src);' src="data_images/underwater1.jpg" />
<img onclick='watereff.changePicture(this.src);' src="data_images/underwater2.jpg" />
</div>
<div id="fps"></div>
</div>
<hr style="clear:both;" />
<h4><a href="http://www.script-tutorials.com/how-to-create-water-drops-effect-using-html5-canvas/">back to original article page</a></h4>
</body>
</html>
Step 2. CSS
Here are the used CSS styles
RippleEffectStyles.CSS
body{background:#eee;margin:0;padding:0}
.example{background:#FFF;width:600px;border:1px #000 solid;margin:20px auto;padding:15px;-moz-border-radius: 3px;-webkit-border-radius: 3px}
#water {
width:500px;
height:400px;
display: block;
margin:0px auto;
cursor:pointer;
}
#switcher {
text-align:center;
overflow:hidden;
margin:15px;
}
#switcher img {
width:160px;
height:120px;
}
Step 3. JavaScript
Here is our main control JS and i used two JavaScript files here.
1.Waterfall.js
function drop(x, y, damping, shading, refraction, ctx, screenWidth, screenHeight){
this.x = x;
this.y = y;
this.shading = shading;
this.refraction = refraction;
this.bufferSize = this.x * this.y;
this.damping = damping;
this.background = ctx.getImageData(0, 0, screenWidth, screenHeight).data;
this.imageData = ctx.getImageData(0, 0, screenWidth, screenHeight);
this.buffer1 = [];
this.buffer2 = [];
for (var i = 0; i < this.bufferSize; i++){
this.buffer1.push(0);
this.buffer2.push(0);
}
this.update = function(){
for (var i = this.x + 1, x = 1; i < this.bufferSize - this.x; i++, x++){
if ((x < this.x)){
this.buffer2[i] = ((this.buffer1[i - 1] + this.buffer1[i + 1] + this.buffer1[i - this.x] + this.buffer1[i + this.x]) / 2) - this.buffer2[i];
this.buffer2[i] *= this.damping;
} else x = 0;
}
var temp = this.buffer1;
this.buffer1 = this.buffer2;
this.buffer2 = temp;
}
this.draw = function(ctx){
var imageDataArray = this.imageData.data;
for (var i = this.x + 1, index = (this.x + 1) * 4; i < this.bufferSize - (1 + this.x); i++, index += 4){
var xOffset = ~~(this.buffer1[i - 1] - this.buffer1[i + 1]);
var yOffset = ~~(this.buffer1[i - this.x] - this.buffer1[i + this.x]);
var shade = xOffset * this.shading;
var texture = index + (xOffset * this.refraction + yOffset * this.refraction * this.x) * 4;
imageDataArray[index] = this.background[texture] + shade;
imageDataArray[index + 1] = this.background[texture + 1] + shade;
imageDataArray[index + 2] = 50 + this.background[texture + 2] + shade;
}
ctx.putImageData(this.imageData, 0, 0);
}
}
var fps = 0;
var watereff = {
// variables
timeStep : 20,
refractions : 2,
shading : 3,
damping : 0.99,
screenWidth : 500,
screenHeight : 400,
pond : null,
textureImg : null,
interval : null,
backgroundURL : 'data_images/underwater1.jpg',
// initialization
init : function() {
var canvas = document.getElementById('water');
if (canvas.getContext){
// fps countrt
fps = 0;
setInterval(function() {
document.getElementById('fps').innerHTML = fps / 2 + ' FPS';
fps = 0;
}, 2000);
canvas.onmousedown = function(e) {
var mouse = watereff.getMousePosition(e).sub(new vector2d(canvas.offsetLeft, canvas.offsetTop));
watereff.pond.buffer1[mouse.y * watereff.pond.x + mouse.x ] += 200;
}
canvas.onmouseup = function(e) {
canvas.onmousemove = null;
}
canvas.width = this.screenWidth;
canvas.height = this.screenHeight;
this.textureImg = new Image(256, 256);
this.textureImg.src = this.backgroundURL;
canvas.getContext('2d').drawImage(this.textureImg, 0, 0);
this.pond = new drop(
this.screenWidth,
this.screenHeight,
this.damping,
this.shading,
this.refractions,
canvas.getContext('2d'),
this.screenWidth, this.screenHeight
);
if (this.interval != null){
clearInterval(this.interval);
}
this.interval = setInterval(watereff.run, this.timeStep);
}
},
// change image func
changePicture : function(url){
this.backgroundURL = url;
this.init();
},
// get mouse position func
getMousePosition : function(e){
if (!e){
var e = window.event;
}
if (e.pageX || e.pageY){
return new vector2d(e.pageX, e.pageY);
} else if (e.clientX || e.clientY){
return new vector2d(e.clientX, e.clientY);
}
},
// loop drawing
run : function(){
var ctx = document.getElementById('water').getContext('2d');
watereff.pond.update();
watereff.pond.draw(ctx);
fps++;
}
}
window.onload = function(){
watereff.init();
}
2.Vector2d.jsfunction vector2d(x, y){ this.x = x this.y = y this.add = function(other){ return new vector2d(this.x + other.x, this.y + other.y); } this.sub = function(other){ return new vector2d(this.x - other.x, this.y - other.y); } this.scale = function(scale){ return new vector2d(this.x * scale, this.y * scale); } this.length = function(){ return Math.sqrt(this.dot(this)); } this.angle = function(other){ return Math.acos(this.dot(other) / (this.length() * other.length())); } this.setAngleVector = function(len, angle){ this.x = -len * Math.sin(angle); this.y = len * Math.cos(angle); return this; } this.dot = function(other){ return this.x * other.x + this.y * other.y; } this.normalize = function(){ var l = this.length() return new vector2d(this.x / l, this.y / l); } this.clone = function(){ return new vector2d(this.x, this.y); } this.distanceSquared = function(other){ var xlen = this.x - other.x; var ylen = this.y - other.y; return xlen * xlen + ylen * ylen; } this.toString = function(){ return "(" + this.x + ", " + this.y + ")"; } } function vector2dCompareX(vector2dA, vector2dB){ return vector2dA.x - vector2dB.x; } function vector2dCompareY(vector2dA, vector2dB){ return vector2dA.y - vector2dB.y; }
No comments:
Post a Comment