图片水中倒影 【js读书笔记】

主要利用HTML5的canvas与IE浏览器的滤镜技术

  1 <!DOCTYPE html>
  2 <html>
  3     <head>
  4         <meta charset="UTF-8">
  5         <title>图片水中倒影</title>
  6     </head>
  7     <style type="text/css">
  8         .shadowInWater{
  9             position: relative;
 10             top: -20px;
 11             filter: wave(strength=3,freq=3,phase=0,lightstrength=30)blur()flipv();
 12         }
 13     </style>
 14     <body>
 15         <h2>图片水中倒影</h2>
 16         <p><img src="img/logo.jpg" height="132" data-water='shadowInWater' id="shadowInWaterSrurce"></p>
 17         <p><img src="img/logo.jpg" height="132" class="shadowInWater" id="shadowInWater"/></p>
 18     </body>
 19     
 20     <script type="text/javascript">
 21         window.onload=function(){
 22             var 
 23                 setCss=function(_this,cssOption){ //设置样式
 24                     if(!_this||_this.nodeType===3||_this.nodeType===8||!_this.style){
 25                         return;
 26                     }
 27                     for(var cs in cssOption){
 28                         _this.style[cs]=cssOption[cs];
 29                     }
 30                     return _this;
 31                 },
 32                 
 33                 isIE=function(){ //是否是IE浏览器
 34                     return !!window.ActiveXobject;
 35                 },
 36                 
 37                 isIE6=function(){ //是否是IE6浏览器
 38                     return isIE() && !window.XMLHttpRequest;
 39                 },
 40                 
 41                 isIE7=function(){ //是否是IE7浏览器
 42                     return isIE() && !isIE6() &&!isIE8();
 43                 },
 44                 
 45                 isIE8=function(){ //是否是IE8浏览器
 46                     return isIE() && !!document.documentMode;
 47                 };
 48             
 49             /**********************
 50              * 水中倒影效果   start
 51              ***********************/
 52             var shadows=null,
 53                 shadowsLen=0,
 54                 shadowInWater=function(){ //水中倒影效果
 55                     shadowsSrurce=document.getElementById("shadowInWaterSrurce");
 56                     shadows=document.getElementById(shadowsSrurce.getAttribute("data-water"));
 57                     
 58                     if(isIE()){  //如果是IE浏览器
 59                         updateShadow();
 60                         return;
 61                     }else{   //如果非IE浏览器,创建canvas完成倒影效果
 62                         canvasShadowInWater();
 63                     }
 64                 },
 65                 
 66                 canvasShadowInWater=function(){ //canvas的水中倒影
 67                     //配置以及初始化数据,创建canvas
 68                     var settings={
 69                             'speed':1,//速度
 70                             'scale':1,//比例
 71                             'waves':10 //波幅度
 72                         },
 73                         waves=settings['waves'],
 74                         speed=settings['speed']/4,
 75                         scale=settings['scale']/2,
 76                         ca=document.createElement('canvas'),//创建画布
 77                         c=ca.getContext('2d'),//获取画布
 78                         img=shadowsSrurce;
 79                         img.parentNode.insertBefore(ca,img);//canvas覆盖源图片
 80                         
 81                     var w,h,dw,dh,offset=0,frame=0,max_frames=0,frames=[];
 82                     
 83                     c.save();
 84                     c.canvas.width=shadowsSrurce.offsetWidth;
 85                     c.canvas.height=shadowsSrurce.offsetHeight*2; //因为基于原图进行倒影投射,,所以必须是原图的2倍高度
 86                     
 87                     /*
 88                     *绘制图形context.drawImage(img,sx,sy,sw,sh,x,y,w,h)
 89                     *[必须]img-要是用的图片、视频、画布
 90                     *[可选]sx-开始剪切的x坐标
 91                     *[可选]sy-开始剪切的y坐标
 92                     *[可选]sw-被剪切图形的宽度
 93                     *[可选]sh-被剪切图形的高度
 94                     *[必须]x-在画布上放置图形的x位置
 95                     *[必须]y-在画布上放置图形的y位置
 96                     *[可选]w-将要使用图形的宽度
 97                     *[可选]h-将要使用图形的高度
 98                     * 在画布上绘制原图
 99                     */
100                     c.drawImage(shadowsSrurce,0,0);
101                     c.scale(1,-1);//垂直镜像转换
102                     c.drawImage(shadowsSrurce,0,-shadowsSrurce.offsetHeight*2);
103                     c.restore();//返回之前保存过的路劲状态和属性
104                     w=c.canvas.width;
105                     h=c.canvas.height;
106                     dw=w;
107                     dh-h/2;
108                     
109                     /*
110                      * 复制画布上制定的矩形的像素数据-context.getImageData(x,y,w,h);
111                      * 以左上角为(0,0)原点
112                      * x代表开始的x位置
113                      * y代表开始的y位置
114                      * w欲复制的矩形区域宽度
115                      * h欲复制的矩形区域高度
116                      * 在被创建的第一个原图的基础上,绘制倒影
117                     */
118                     var id=c.getImageData(0,h/2,w,h).data,
119                         end=false;
120                     c.save();//将状态保存起来
121                     while(!end){  //预先计算缓存的帧
122                         var odd=c.getImageData(0,h/2,w,h),
123                             od=odd.data,
124                             pixel=0;
125                         for(var y=0;y<dh;y++){
126                             for(var x=0;x<dw;x++){
127                                 var displacement=(scale*10(Math.sin((dh/(y/waves))+(-offset))))|0,
128                                     j=((displacement+y)*w+x+displacement)*4;
129                                 if(j<0){ //修复倒影与原图的水平线闪烁的问题
130                                     pixel +=4;
131                                     continue;
132                                 }
133                                 var m=j%(w*4),//修复边缘波纹问题
134                                     n=scale*10*(y/waves);
135                                 if(m<n||m>(m*4)-n){
136                                     var sign=y<w/2?1:-1;
137                                     od[pixel]  =od[pixel+4*sign];
138                                     od[++pixel]=od[pixel+4*sign];
139                                     od[++pixel]=od[pixel+4*sign];
140                                     od[++pixel]=od[pixel+4*sign];
141                                     ++pixel;
142                                     continue;
143                                 }
144                                 if(id[j+3]!=0){  //水影陈列计算
145                                     od[pixel]  =id[j];
146                                     od[++pixel]=id[++j];
147                                     od[++pixel]=id[++j];
148                                     od[++pixel]=id[++j];
149                                     ++pixel;
150                                 }else{
151                                     od[pixel]  =od[pixel-w*4];
152                                     od[++pixel]=od[pixel-w*4];
153                                     od[++pixel]=od[pixel-w*4];
154                                     od[++pixel]=od[pixel-w*4];
155                                     ++pixel;
156                                 }
157                             }
158                         }
159                         if(offset>speed*(6/speed)){
160                             offset=0;
161                             max_frames=frame-1;
162                             //frames.pop();
163                             frame=0;
164                             end=true;
165                         }else{
166                             offset +=speed;
167                             frame++;
168                         }
169                         frames.push(odd);
170                     }
171                     setCss(shadows,{"display":"none"}); //隐藏原图
172                     setCss(shadowsSrurce,{"display":"none"}); //隐藏原图
173                     c.restore();
174                     
175                     setInterval(function(){
176                         c.putImageData(frames[frame],0,h/2);
177                         if(frame<max_frames){
178                             frame++;
179                         }else{
180                             frame=0;
181                         }
182                     },50);
183                 },
184                 
185                 updateShadow=function(){ //ie中动态跟新倒影
186                     if(isIE6()){
187                         return;
188                     }
189                     shadows.filters.wave.phase+=10;
190                     setTimeout("updateShadow()",150);
191                 };
192                 
193                 shadowInWater();
194         };
195     </script>
196 
197 </html>

 

posted @ 2016-05-04 10:03  HollyLearningNotes  阅读(512)  评论(0编辑  收藏  举报