今天,我们继续分享 javascript 实现的效果例子,这篇文章会介绍使用 javascript 实现水波纹效果。水波效果以图片为背景,点击图片任意位置都会触发。有时候,我们使用普通的 javascript 就可以创建一个很有趣的解决功能。
源码下载
step 1. html
和以前一样,首先是 html 代码:
复制代码
代码如下:
water drops effect
water drops effect
html5 compliant browser required
step 2. css
这是用到的 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. js
下面是主要的 javascript 代码:
复制代码
代码如下:
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.buffer1.push(0);
this.buffer2.push(0);
}
this.update = function(){
for (var i = this.x + 1, x = 1; i if ((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 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();
}
正如你所看到的,这里使用 vector2d 函数,这个函数在 vector2d.js 里提供了。另一个很难的方法是使用纯数学实现,感兴趣的可以自己实验一下。