高斯模糊濾鏡效果解析

前言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>
View Code

完美!

.....

.....

.....

然而事情並無這麼簡單!

歌詞可能是用白色字體,毛玻璃仍是太亮了,容易混淆. 嘿嘿,其實也簡單,再加上一點背景透明度就好啦.

<!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>
View Code

看這下是否是好多啦. 恩比較有玻璃質感了.其實吧,還有個坑爹的問題, 加了濾鏡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>
View Code

我們能夠隱約的發現,在圖片的四周模糊效果不是很好,這種狀況在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>
View Code

<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上是沒問題的. 但有至關一部分安卓不支持.

 

其餘濾鏡效果沒用過,彷佛也不太經常使用,也很少說了,網上都能查到.

 

總結

  • css3濾鏡方便,性能很差,適合作靜止的簡單效果. 若是濾鏡之上有浮層動畫,會很是卡.
  • svg濾鏡性能好,適合作多層運動,可是有不能重繪的問題
  • css3濾鏡須要添加背景圖,svg濾鏡背景能夠是畫出來的
  • css3和svg的高斯模糊濾鏡都會使得該層變得透明
  • 高斯模糊在圖片的邊緣效果不太好,能夠放大圖片width=105%
  • 兼容性兩者差很少,svg稍好

 

 

參考資料:

相關文章
相關標籤/搜索