主要利用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>