春天,陪你一起去赏雨——HTML5下雨效果

转载 2012年03月29日 19:48:38

http://blog.csdn.net/qingfeilee/article/details/7394735

 不知从什么时候我们已经没有了淋雨的勇气、不知从什么时候我们已经不敢享受雨水的甘甜、不知从什么时候我们感受不到那雨声的清脆。桃花已开但我们却嗅不到他的清香、春雨已来但我们却想方设法将其遮挡、湖水已涨但我们却失去了赏鱼的闲情雅致。时光让我们学到了很多、时光也让我们失去了很多。成天奔波的我们从来不舍得停下脚步,因为今天的我们已经意识到了一寸光阴一寸金的真正内涵。为了冰箱里的那块面包,我们每天就这样奔波着、忙碌着......

    停止牢骚,言归正题。

    这篇blog描写的是一个动态水波的效果,主要是通过HTML5里面的canvas来实现。整片文章属于原创若有相同纯属有缘,但是里面的核心水波原理并非本人原创是参考网上很多关于水波原理进行综合而成,所以在这里要谢谢网上那些贡献知识的人。闲话少说,先看实现的效果如图一:


图一

       考虑到性能问题,建议图片不要太大,本例子用400*300的图片在chrome和firefox下还算流畅,但是safari相对较卡。把图片扩大2倍至800*600就比较卡,效果不是很好。下面将代码贴出共大家一起交流学习。

[javascript] view plaincopy
  1. <pre name="code" class="html"><!DOCTYPE html>  
  2. <html>  
  3.     <head>  
  4.         <meta charset="utf-8" />  
  5.         <title>春天,陪你一起去赏雨——HTML5下雨效果</title>  
  6.         <style type="text/css">  
  7.             #box{   
  8.                 border:2px solid #f60; margin:0 auto;  
  9.             }  
  10.         </style>  
  11.         <script>  
  12.             var floor = Math.floor;//向下取整  
  13.             var canvas;//画布  
  14.             var context;//画布上下文  
  15.             var width;//背景图片、画布宽  
  16.             var height;//背景图片、画布宽  
  17.             var size;//像素点个数、width*height  
  18.             var nextPoint = [];//下一振幅  
  19.             var prePoint = [];//上一振幅  
  20.             var tempPoint = [];//临时存储  
  21.             var imgData;//背景图片数据  
  22.             var speed = 100;//下雨大小,默认是一秒钟一个雨滴  
  23.             var weight = 1000;//雨滴的大小  
  24.             /** 
  25.                 author:qingfeilee 
  26.                 date:2012-03-24 
  27.                 description:开始启动程序 
  28.             **/  
  29.             function start() {  
  30.                 initImage("background.jpg");  
  31.             }  
  32.             /** 
  33.                 author:qingfeilee 
  34.                 date:2012-03-24 
  35.                 description:初始化图片信息 
  36.             **/  
  37.             function initImage(src) {  
  38.                 var img = new Image();  
  39.                 img.src = src;  
  40.                 img.onload = function() {  
  41.                     init(img);  
  42.                 };  
  43.             }  
  44.             /** 
  45.                 author:qingfeilee 
  46.                 date:2012-03-24 
  47.                 description:初始化系统函数 
  48.             **/  
  49.             function init(img){  
  50.                     initSize(img);  
  51.                     initPoint();  
  52.                     initCanvas();  
  53.                     loadImage(img);  
  54.             }  
  55.             /** 
  56.                 author:qingfeilee 
  57.                 date:2012-03-24 
  58.                 description:绘制图片函数 
  59.             **/  
  60.             function loadImage(img){  
  61.                 context.drawImage(img, 0, 0);  
  62.                 imgData = context.getImageData(0, 0, width, height);  
  63.                 setInterval(spread, 1000/60);  
  64.                 setInterval(rain, speed);  
  65.             }  
  66.             /** 
  67.                 author:qingfeilee 
  68.                 date:2012-03-24 
  69.                 description:初始化画布信息 
  70.             **/  
  71.             function initCanvas(){  
  72.                 canvas = document.getElementById('ripper');  
  73.                 context =canvas.getContext('2d');  
  74.                 canvas.width = width;  
  75.                 canvas.height = height;  
  76.                 canvas.onclick = function(e) {  
  77.                     setDropPoint(floor(e.clientX-(document.body.clientWidth  - width)/2), floor(e.clientY - (document.body.clientHeight  - height) / 2), 15000);  
  78.                 }  
  79.             }  
  80.             /** 
  81.                 author:qingfeilee 
  82.                 date:2012-03-24 
  83.                 description:设置画布宽高及画布像素数 
  84.             **/  
  85.             function initSize(img){  
  86.                 width = img.width;  
  87.                 height = img.height;  
  88.                 document.getElementById("box").style.width = width+"px";  
  89.                 document.getElementById("box").style.height = height+"px";  
  90.                 size = width*height;  
  91.             }  
  92.             /** 
  93.                 author:qingfeilee 
  94.                 date:2012-03-24 
  95.                 description:初始化存储图像前一个和后一个点的数组 
  96.             **/  
  97.             function initPoint(){  
  98.                 for (var i = 0; i < size; i++) {  
  99.                     nextPoint.push(0);  
  100.                     prePoint.push(0);  
  101.                 }                 
  102.             }  
  103.             /** 
  104.                 author:qingfeilee 
  105.                 date:2012-03-24 
  106.                 description:一石激起千层浪,设置波动点及注入的能量 
  107.                             其中x表示物体进入水面的X坐标,Y表示物体进入水面的Y坐标,power表示物体的能量大小 
  108.             **/  
  109.             function setDropPoint(x, y, power) {  
  110.                 if (x < 2 || x > width - 2 || y < 1 || y > height - 2) return;  
  111.                 var i = x + y * width;  
  112.                 nextPoint[i] += power;  
  113.                 nextPoint[i - 1] -= power;  
  114.             }  
  115.             /** 
  116.                 author:qingfeilee 
  117.                 date:2012-03-24 
  118.                 description:核心算法,处理像素的波动效果 
  119.                 PS:该算法非原创,借鉴网络上多个版本算法综合 
  120.             **/  
  121.             function spread() {  
  122.                 var img = context.getImageData(0, 0, width, height),  
  123.                 data = img.data;  
  124.                 //平均一下各个点的能量  
  125.                 for (var i = width + 1; i < size - width - 1; i += 2) {  
  126.                     for (var x = 1; x < width - 1; x++, i++) {  
  127.                         nextPoint[i] = (nextPoint[i] + nextPoint[i + 1] + nextPoint[i - 1] + nextPoint[i - width] + nextPoint[i + width]) / 5;  
  128.                     }  
  129.                 }  
  130.                 //渲染除了第一行、最后一行、第一列、最后一列外的所有点  
  131.                 for (var i = width + 1; i < size - width - 1; i += 2) {  
  132.                     for (var x = 1; x < width - 1; x++, i++) {  
  133.                         //水波振幅线性公式参考的是网络上的一些研究文献得出的  
  134.                         prePoint[i] = (nextPoint[i - 1] + nextPoint[i + 1] + nextPoint[i + width] + nextPoint[i - width])/2 - prePoint[i];  
  135.                         var ti = i + floor((prePoint[i - 2] - prePoint[i]) * 0.08) + floor((prePoint[i - width] - prePoint[i]) * 0.08) * width;  
  136.                         ti = ti < 0 ? 0 : ti > size ? size: ti;  
  137.                         var light = prePoint[i] * 2.0 - prePoint[i - 2] * 0.6;  
  138.                         light = light < -10 ? -10 : light > 100 ? 100 : light;  
  139.                         //之所以是i*4是因为canvas获取的data数据每四个值表示一个像素包括分别是红/绿/蓝/透明,要想了解更多关于canvas的请参看我的另一篇blog:http://blog.csdn.net/qingfeilee/article/details/7233683  
  140.                         data[i * 4] = imgData.data[ti * 4] + light;  
  141.                         data[i * 4 + 1] = imgData.data[ti * 4 + 1] + light;  
  142.                         data[i * 4 + 2] = imgData.data[ti * 4 + 2] + light;  
  143.                         //波能渐渐衰减  
  144.                         prePoint[i] -= prePoint[i]>>5;  
  145.                     }  
  146.                 }  
  147.                 tempPoint = nextPoint;  
  148.                 nextPoint = prePoint;  
  149.                 prePoint = tempPoint;  
  150.                 context.putImageData(img, 0, 0);  
  151.             }  
  152.               
  153.             function rain(){  
  154.                 setDropPoint(floor(Math.random()*width), floor(Math.random()*height), floor(Math.random()*weight));  
  155.             }  
  156.             function setWeight(weight){  
  157.                 this.weight = weight;  
  158.             }  
  159.               
  160.             window.addEventListener("load", start, true);  
  161.         </script>  
  162.           
  163.     </head>  
  164.       
  165.     <body>  
  166.         <div id="box">  
  167.             <canvas id="ripper" style="width:100%;height:100%; "></canvas>  
  168.             <div align="center">  
  169.             <button onclick = "setWeight('1000')">小雨</button>  
  170.             <button onclick = "setWeight('10000')">中雨</button>  
  171.             <button onclick = "setWeight('20000')">大雨</button>  
  172.               
  173.         </div>  
  174.         </div>  
  175.         <div><h5 style = "text-align:center"><a href = 'http://blog.csdn.net/qingfeilee/'>阿飞blog</a></h5></div>  
  176.         </div>  
  177.     </body>  
  178.   
  179. </html>  



       核心算法的解释,在我们利用这个水波原理解析图像的时候我们只需要获取除了第一行、最后一行、第一列、最后一列的像素点即可,如图二:

图二

本Demo中还需要一张背景图片,注:图片不能太大、否则画面将比较不流畅。本文的背景图片如图三:

图三

       由代码注释较详细,具体就不再赘述。倘若对Canvas不太了解希望我的另外一篇blog《通过小画板认识Canvas》能够帮助到你。哪位大牛有好的算法实现希望能够多多交流,共同学习,共同进步,欢迎拍砖哭
    本文乃原创Demo,转载请注明出处:http://blog.csdn.net/qingfeilee/article/details/7394735 使用代码请保留作者署名,O(∩_∩)O谢谢
     备注:本代码直接在chrome和firefox下面运行无法运行需要放到服务器里通过http://ip的形式来访问才行,safari可以直接访问但是运行效率较低。之所以前两者不能直接运行的,是因为chrome和firefox两家浏览器的安全策略所致getImageData()不能获取图片数据的原因,但是通过网络即可。

春天,陪你一起去赏雨——HTML5下雨效果

不知从什么时候我们已经没有了淋雨的勇气、不知从什么时候我们已经不敢享受雨水的甘甜、不知从什么时候我们感受不到那雨声的清脆。桃花已开但我们却嗅不到他的清香、春雨已来但我们却想方设法将其遮挡、湖水已涨但我...
  • QingfeiLee
  • QingfeiLee
  • 2012年03月26日 13:39
  • 22384

android 实现漫天飞舞雪花以及下雨天的效果

前言: 这个效果实现的原作者是国外一位大神。我在其基础上测试,以及在代码上加了不少注释,以及局部修改。后面我有根据漫天飞舞雪花,实现下雨天场景的效果。原作者项目还是android studio版本的...
  • qq_16064871
  • qq_16064871
  • 2016年01月28日 20:57
  • 7361

jquery 自定义容器下雨效果

.box{border-left:5px solid #F93;border-right:5px solid #F93;border-bottom:10px solid #F93;width:100p...
  • zyx13859002783
  • zyx13859002783
  • 2014年04月23日 10:31
  • 3070

unity3D 下雨效果实现

这个效果借鉴自unity例子angrybot,并做了一部分适应项目的修改。 angrybot的实现方法 单个雨滴 RainBox 1.Start的时候从Mgr里面取一个雨滴的mesh给MeshFil...
  • songchao_xx
  • songchao_xx
  • 2016年02月29日 22:26
  • 4750

Unity3d中使用自带动画系统制作下雨效果(二)

接着昨天的(一),今天上下雨效果的后半部分。在最后附上网盘链接,有使用的素材及本次的工程源文件,想看看的童鞋可以下载~~       文章出自【狗刨学习网】       下雨效果分两部分:...
  • Carl180
  • Carl180
  • 2015年01月27日 20:24
  • 1369

css3写下雨效果

css3写下雨效果 .xiayuxiaoguo{ width:100%; height: 100%; position: absolute; ...
  • oMiracle123
  • oMiracle123
  • 2017年03月15日 14:42
  • 502

2D动画+GUI实现(含星星闪烁、下雪、下雨场景)

使用Win32编程实现的简单二维Demo。主要模拟了游戏客户端的部分功能,切换进入背景故事、系统设置界面;添加自定义按钮;实现星星闪烁、下雪、下雨场景。 exe 下载地址:http://downlo...
  • a4775019136
  • a4775019136
  • 2014年10月12日 13:28
  • 1276

推荐《陪你一起健身的疯狂教练》

观后心得: 1.健身教练习惯了健身餐,每天摄入卡路里4000,即使是开始4个月的增重阶段,吃油脂大的美食时心里也在默念卡路里。 2.教练增重时,刚开始感觉还好,但一周后就开始出现反应:吃吐了(习惯...
  • ysmz4
  • ysmz4
  • 2017年10月17日 18:08
  • 2765

Unity3d中使用自带动画系统制作下雨效果(一)

之前看了以前版本的unity3d demo AngryBots ,觉得里面的下雨效果不错,刚好前段时间学习了,写出来跟大家分享下,直接开始。       文章出自【狗刨学习网】      ...
  • Carl180
  • Carl180
  • 2015年01月27日 20:24
  • 1541

Html5下炫酷文字雨滴效果_简单实现

@yuHG在学习h5,需要做个炫酷文字效果,让我帮忙,我也快速学习下html知识,写个demo。 先看下效果: 动态图:http://yunpan.cn/cFdKWrfA7gv2B 访问密码 ...
  • lyltiger
  • lyltiger
  • 2015年10月17日 00:41
  • 3276
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:春天,陪你一起去赏雨——HTML5下雨效果
举报原因:
原因补充:

(最多只允许输入30个字)