前言css
这个东西呢无论看起来,听起来都很高大上哈.鄙人比较懒,知道有这么个东西,却一直没去研究.感叹技术突飞猛进,有时候以为本身掉队好远了.这不项目中便遇到了使用这家伙的状况.此次须要作一个音乐类app,须要有毛玻璃的高大上效果.这个效果在众多音乐app中很是常见,也确实很是漂亮.但在网页端见得比较少.大概是兼容性和性能问题吧(强烈吐槽性能).也没办法,有需求就得想办法去实现是否是,不过最讨厌跟那群UE,PM撕逼.若是对她们说这个东西很麻烦,很差实现.而后她们一副哥哥你必定能够的!!花痴表情强行绑架了我.哎,谁让我是程序员呢. 其实吧我本身也挺想去实现这个东西的。默默的给本身打了一针鸡血便投入无尽的搜寻,学习中.html
css3-filterios
搜索一番,找到这个属性filter:blur(5px)。赶快去实现一把。css3
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta http-equiv="content-type" content="text/html; charset=utf-8"> 5 <title></title> 6 <style> 7 .d1{ 8 background-image:url('./lp.png'); 9 background-size:cover; 10 -webkit-filter:blur(10px); 11 filter:blur(10px); 12 width:300px; 13 height:300px; 14 } 15 </style> 16 </head> 17 <body> 18 19 <div class="d1"></div> 20 </body> 21 </html>
咳咳, 献上一个萌妹子.实在找不到图片了.O(∩_∩)O哈哈~程序员
blur的效果就是虚化图片.值越大虚化得越厉害.web
瞬间高大上了有木有!! 算法
....canvas
....app
....ide
然而事情并无这么简单.滤镜算法是对图片的像素点作处理,也就是说你须要设置一张背景图.当前元素设置滤镜属性后,元素里面的内容也会被影响.就拿上面的例子来讲,若是元素里面有文字的话,那么文字也看不见了.聪明的你确定会想到再叠一层不就完了嘛.事实状况也确实如此(这不是废话么...)让咱们来看下
<!DOCTYPE html> <html> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"> <title></title> <style> .wrap{ position:relative; width:300px; height:300px; line-height:300px; text-align:center; } .d1{ background-image:url('./lp.png'); background-size:cover; -webkit-filter:blur(10px); filter:blur(10px); position: absolute; top:0; left:0; width:100%; height:100%; z-index:-1; } </style> </head> <body> <div class="wrap"> <div class="d1"></div> <div class="content">我爱你老婆</div> </div> </body> </html>
完美!
.....
.....
.....
然而事情并无这么简单!
歌词可能是用白色字体,毛玻璃仍是太亮了,容易混淆. 嘿嘿,其实也简单,再加上一点背景透明度就好啦.
<!DOCTYPE html> <html> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"> <title></title> <style> .wrap{ position:relative; width:300px; height:300px; } .d1{ background-image:url('./lp.png'); background-size:cover; -webkit-filter:blur(10px); filter:blur(10px); position: absolute; top:0; left:0; width:100%; height:100%; z-index:-1; } .content{ width:100%; height:100%; line-height:300px; color:#fff; text-align:center; background-color:rgba(0,0,0,0.3); } </style> </head> <body> <div class="wrap"> <div class="d1"></div> <div class="content">我爱你老婆</div> </div> </body> </html>
看这下是否是好多啦. 恩比较有玻璃质感了.其实吧,还有个坑爹的问题, 加了滤镜blur的元素就变成透明的了,虽然有背景图也仍是透明的.因此在须要毛玻璃覆盖底层的状况下,得再叠一层,添加一个背景色.
<!DOCTYPE html> <html> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"> <title></title> <style> .wrap{ position:relative; width:300px; height:300px; } .filter{ background-image:url('./lp.png'); background-size:cover; -webkit-filter:blur(10px); filter:blur(10px); position: absolute; top:0; left:0; width:100%; height:100%; z-index:-1; } .filter-bg{ position:absolute; top:0; left:0; width:100%; height:100%; background-color:#333; z-index:-2; } .content{ width:100%; height:100%; line-height:300px; color:#fff; text-align:center; background-color:rgba(0,0,0,0.3); } </style> </head> <body> <div class="wrap"> <div class="filter-bg"></div> <div class="filter"></div> <div class="content">我爱你老婆</div> </div> </body> </html>
我们能够隐约的发现,在图片的四周模糊效果不是很好,这种状况在blur的值越大的时候越明显,趋势是模糊区域向图像中颜色明显的地方靠近,边缘地方就显得透明,甚至貌似没有模糊.建议blur的值设置在30如下.
彷佛问题就这么解决了!!
真的解决了?!
真的?
svg-<filter>
我兴奋的,天真的觉得事情就这么完了,然而当我附上动画后,让毛玻璃动起来时,整我的都崩溃了. fuck! 哥才买的6s玫瑰金,卡得跟屎同样.固然补充下前提条件,是在播放音乐的时候拖动页面,页面元素数量通常.但不至于播放个音乐拖垮了整个页面性能吧.二愣子的我拖着电脑就去找pm了,你看,就是你要作这种效果,卡得跟方便面同样一条一条的.搞不定,砍需求!
pm碍于我愤怒的表情,打起了太极.你先冷静冷静.什么事儿都好商量.你要不喝点儿饮料?
我固然接受了(大家不要用异样的眼光看着我). 喝着饮料平静了下心情,这事儿吧总得解决.和pm鬼扯了半天仍是以为要保留这个效果,否则作了那么久就白费了.何况一个好的工程师(注意我没有用程序员!)就得迎难而上啊,创造力和解决问题的能力才是工程师们的价值所在.首先仍是得定位问题,为了肯定是filter属性的锅,我把滤镜层给删掉,卧槽丝滑般流畅.看来这属性真是性能堪忧啊.那怎么办呢,我最终仍是抱向了google的大腿.一番搜索,果真不负众望.原来除了css3以外,svg和canvas也是能够实现滤镜效果的.我试了下svg,效果然是好得出奇.很流畅.将咱们刚才的filter层替换为svg实现
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events" baseProfile="full"> <defs> <filter id="blur"> <feGaussianBlur stdDeviation="10" /> </filter> </defs> <image xlink:href="./mm.jpg" x="0" y="0" height="200" width="200" filter="url(#blur)"/> </svg>
<filter>标签用来描述滤镜,其id属性惟一标识一个滤镜.<filter>标签必须写在<defs>标签内.<defs>标签是对特殊效果进行描述.
最终效果不卡.我猜想应该是实现机制不一样,svg添加上滤镜后就会把它当成一个图片来处理,不会重复消耗cpu计算.而css3的filter属性应该是在滚动的时候会动态计算,在作一些比较复杂的效果时候,卡顿就很明显.
使用svg的滤镜依然会使得svg层变得透明,在不但愿透明的时候记得添加一层背景色.
canvas
用svg的时候遇到一个诡异的问题, 在手机上.把滤镜层隐藏,或者visibility:hidden, 切换的时候,滤镜不见了,图片还在.可是没有了模糊效果.怀疑是性能问题,不能及时重绘渲染.或者svg的滤镜只渲染一次.因此考虑用canvas来作高斯模糊.由于canvas渲染完毕后就是一张图片.不会再发生改变.
2016年04月24日补充: 后来无心中发现使用了
高斯算法参考 高斯算法原理
找到一个高斯算法库,stackBlur.js . 里面有一行注释,须要关注下,是关于getImageDate.获取本地图片的,须要删掉try,catch那段代码.这里又遇到一个问题.canvas的getImageDate有同源策略,只能操做同域的图片资源.
处理库API: stackBlurImage( sourceImageID, targetCanvasID, radius, blurAlphaChannel );
sourceImageID
表示要模糊的图片的id
, 默认这个图片要隐藏;
targetCanvasID
表示要显示模糊图片的canvas
元素的id
;
radius
表示模糊的半径大小。不过,根据个人对比测试,radius
好像与CSS中filter滤镜的模糊值不是1:1
匹配的,反却是有些相似2:1
. 也就是这里的20px
的半径模糊近似于CSS中blur
滤镜值设置为10px
;
blurAlphaChannel
为布尔属性,表示aplha
透明通道是否要模糊,true
表示要模糊。
兼容性对比
我们再来对比一下兼容性,可见svg稍好,在安卓上都是4.4才支持.另外一方面,在移动端,毛玻璃效果在ios上是没问题的. 但有至关一部分安卓不支持.
其余滤镜效果没用过,彷佛也不太经常使用,也很少说了,网上都能查到.
总结
参考资料: