巧用 SVG 濾鏡還能製做表情包?

本文將介紹一些使用 SVG feTurbulence 濾鏡實現的一些有趣、大膽的的動效。前端

系列另外兩篇:git

背景

今天在羣裏面聊天,看到有人發這個表情包:github

恰好最近一直在學習 SVG,腦海中就把這個表情包的效果和 feTurbulence 濾鏡關聯了起來。數組

若是咱們有一張相似上圖表情包的靜態圖,利用 feTurbulence 生成的噪聲函數,運用在靜態的表情包之上,再添加些許動畫,是否是也能製做一張相似的動圖效果呢?markdown

什麼是 SVG feTurbulence 濾鏡?

若是你對 SVG 濾鏡還不算太瞭解,能夠簡單看看個人這篇文章入門:有意思!強大的 SVG 濾鏡svg

這裏咱們會用到 SVG 中的 feTurbulence 濾鏡。再簡單介紹下。函數

feTurbulence 濾鏡

turbulence 意爲湍流,不穩定氣流,而 SVG <feTurbulence> 濾鏡可以實現半透明的煙燻或波狀圖像。一般用於實現一些特殊的紋理。濾鏡利用 Perlin 噪聲函數建立了一個圖像。噪聲在模擬雲霧效果時很是有用,能產生很是複雜的質感,利用它能夠實現了人造紋理好比說雲紋、大理石紋的合成。oop

簡單看個 DEMO:學習

<div>Coco</div>
<div class="turbulence">Coco</div>

<svg>
    <filter id="fractal" filterUnits="objectBoundingBox" x="0%" y="0%" width="100%" height="100%">
        <feTurbulence id="turbulence" type="fractalNoise" baseFrequency="0.03" numOctaves="1" />
        <feDisplacementMap in="SourceGraphic" scale="50"></feDisplacementMap>
    </filter>
</svg>
複製代碼
.turbulence {
    filter: url(#fractal);
}
複製代碼

左邊是正常的效果,後邊是應用了 <feTurbulence> 的效果,你能夠試着點進 Demo,更改 baseFrequencynumOctaves 參數的大小,能夠看到不一樣的效果:動畫

CodePen Demo -- feTurbulence text demo

feTurbulence 濾鏡應用於圖片

咱們嘗試把上述 DEMO 中的文字轉換成圖片。我找到了一張靜態的哭的表情包:

簡單改造下代碼:

<div></div>
<svg>
    <filter id="fractal" filterUnits="objectBoundingBox" x="0%" y="0%" width="100%" height="100%">
        <feTurbulence id="turbulence" type="fractalNoise" baseFrequency="0.09" numOctaves="1" ></feTurbulence>
        <feDisplacementMap in="SourceGraphic" scale="15"></feDisplacementMap>
    </filter>
</svg>
複製代碼
div {
    background: url(image.jpg);
    filter: url(#fractal);
}
複製代碼

效果以下:

image

有點那個意思了,咱們經過 feTurbulence 濾鏡獲得了噪聲圖形,而後經過 feDisplacementMap 濾鏡根據 feTurbulence 所產生的噪聲圖形進行形變,扭曲,液化,獲得最終的效果。

經過調整 feTurbulence 中的 baseFrequencynumOctaves 以及 feDisplacementMap 中的 scale 參數,咱們能夠調試獲得不一樣的效果。

接下來,咱們再給上述濾鏡添加一個動畫,利用 SVG 的 animate 標籤,動態的改變 baseFrequency 參數:

<svg>
    <filter id="fractal" filterUnits="objectBoundingBox" x="0%" y="0%" width="100%" height="100%">
        <feTurbulence id="turbulence" type="fractalNoise" baseFrequency="0.1 0.1" numOctaves="1" >
            <animate attributeName="baseFrequency" from="0.1 0.1" to="0.08 0.01" dur="3.5s" repeatCount="indefinite"/>
        </feTurbulence>
        <feDisplacementMap in="SourceGraphic" scale="15"></feDisplacementMap>
    </filter>
</svg>
複製代碼

添加了動畫以後,一樣做用於圖片之上,咱們就能夠獲得以下的效果:

因爲截圖軟件的幀率問題,看着有點慢,你能夠戳進 DEMO 看看實際效果,仍是挺有意思的,至此咱們就簡單的利用 CSS 配合 SVG 的方式,經過一張靜態圖獲得了一個動態的表情包啦。:grin:

CodePen Demo -- 使用 SVG 濾鏡 feTurbulence 讓圖片動起來

巧用 feTurbulence 濾鏡實現各類動效

嘿,feTurbulence 固然不是僅能實現這個而已,下面咱們再探索一些有意思的場景。

首先,再明確下咱們主要使用到的兩個濾鏡 feTurbulencefeDisplacementMap,它們的核心代碼:

<svg>
    <filter id="feDisplacementMap" filterUnits="userSpaceOnUse" x="0" y="0" width="200" height="64">
        <feTurbulence type="fractalNoise" baseFrequency="0.0995" numOctaves="1" result="img" />
        <feDisplacementMap id="feDis" in="SourceGraphic" in2="img" scale="600" />
    </filter>
</svg>
複製代碼

其中濾鏡中的幾個參數 -- baseFrequencynumOctavesscale 的改變其實都會獲得不同的效果。咱們動態的變化其中的一個或多個也均可以獲得不一樣的動畫效果。

動態改變 feDisplacementMapscale 的參數

feDisplacementMap 濾鏡是用於改變元素和圖形的像素位置的。該濾鏡經過遍歷原圖形的全部像素點,經過 feTurbulence 濾鏡產生的噪聲函數將原圖像的每一個像素點從新映射到一個新的位置,造成一個新的圖形。

scale 表示新獲得的圖像的扭曲程度,這個值越大,圖像越加扭曲不可識別。

經過設置一個很是大初始值,咱們能夠徹底將輸入的任何源圖像粒子化,看看這個 Demo:

<div></div>
<div class="fractal"></div>

<svg viewBox="0 0 200 200" width="200px" height="200px">
    <defs>
        <filter id="fractal" filterUnits="userSpaceOnUse" x="0" y="0" width="200" height="200">
            <feTurbulence type="fractalNoise" baseFrequency="0.995" numOctaves="10" seed="1" stitchTiles="noStitch" result="img" />
            <feDisplacementMap in="SourceGraphic" in2="img" xChannelSelector="R" yChannelSelector="G" scale="600" />
        </filter>
    </defs>
</svg>
複製代碼
div {
    width: 200px;
    height: 200px;
    background: url(image.jpeg)
}

.fractal {
    filter: url(#fractal);
}
複製代碼

左邊爲正常的圖像,右邊爲做用了設置了 SVG 濾鏡效果的圖像,而且設置了 scale="600",徹底將圖片粒子化了:

這個時候,讓濾鏡的 scale="600" 動態變化回 scale="1"(當此參數爲 1 時,圖像表示爲正常狀態),也就能實現一個圖形從粒子化到正常化的轉變:

<svg viewBox="0 0 200 200" width="200px" height="200px">
    <filter id="fractal" filterUnits="userSpaceOnUse" x="0" y="0" width="200" height="200">
        <feTurbulence type="fractalNoise" baseFrequency="0.995" numOctaves="10" seed="1" result="img" />
        <feDisplacementMap in="SourceGraphic" in2="img" xChannelSelector="R" yChannelSelector="G" scale="600">
            <animate attributeName="scale" values="600;0;0" keyTimes="0;0.75;1" begin="0s" dur="2s" repeatCount="indefinite" />
        </feDisplacementMap>
    </filter>
</svg>
複製代碼

效果以下:

CodePen -- SVG Filter feTurbulence & feDisplacementMap 實現圖片粒子化復原動畫

動態改變 feDisplacementMapscale 的參數實現一些開獎動效

基於上述的效果,咱們能夠實現這樣一類效果,譬如一些開獎結果,一開始它是模糊的,可是用戶點擊以後,模糊的結果逐漸從模糊到真實。

可是點擊事件,因爲 SVG Animate 標籤的一些限制,須要藉助一些 Javascript 代碼,這裏借用 JQuery 簡單作個示意。

咱們有一串開獎數組 745846,實現點擊以後從模糊到真實:

<div id="fe1" class="fe1">745846</div>
<svg>
    <filter id="feDisplacementMap" filterUnits="userSpaceOnUse" x="0" y="0" width="200" height="64">
        <feTurbulence type="fractalNoise" baseFrequency="0.0995" numOctaves="1" result="img" />
        <feDisplacementMap id="feDis" in="SourceGraphic" in2="img" scale="200" />
    </filter>
</svg>
複製代碼
$("#fe1").click((e) => {
    const filter = $("#feDis");
    const startTime = Date.now();
    const duration = 1000;
    const target = 200;
    
    requestAnimationFrame(function aniMove() {
        const t = Math.min(1, (Date.now() - startTime) / duration);
        const nextTarget = target - (t * target) + 1;
        
        filter.attr('scale', nextTarget);

        if (t < 1.0) {
            requestAnimationFrame(aniMove);
        }
    });
});
複製代碼

點擊以前的狀態以下:

點擊以後:

上述效果,你能夠套用到任何地方,完整的 Demo 地址:

CodePen Demo -- SVG Filter Button Effects

動態改變 feDisplacementMapscale 的參數實現一些 fadeOut 動畫

固然,上述的效果也是能夠反着來的,就是一張圖(或者任何元素),點擊以後粒子化,而後漸變的消失,進階版的 fadeOut 效果。

經過動態的改變濾鏡的參數和圖片的透明度,固然,也須要藉助一些 JavaScript 代碼,完整的代碼就不貼了(與上述 DEMO 很是相似),直接上效果圖:

使用 SVG 濾鏡實現任意元素粒子化 FadeOut 效果.gif

是否是很是相似滅霸把人物消失的效果?以前看過這樣一篇文章 - 谷歌滅霸彩蛋的效果實現,其中介紹了一種使用 Canvas 實現相似效果的方式,本文這裏使用 SVG 濾鏡達成了近似的效果。

對源碼感興趣的能夠猛戳下面的 Demo,效果也是能夠方便的移植到其餘元素之上:

CodePen Demo -- 使用 SVG 濾鏡實現任意元素粒子化 FadeOut 效果

不要吹滅你的靈感和你的想象力; 不要成爲你的模型的奴隸。 ——文森特・梵高

最後

好了,本文到此結束,但願對你有幫助 :)

更多精彩 CSS 技術文章彙總在個人 Github -- iCSS ,持續更新,歡迎點個 star 訂閱收藏。

想 Get 到最有意思的 CSS 資訊,千萬不要錯過個人公衆號 -- iCSS前端趣聞 😄

若是還有什麼疑問或者建議,能夠多多交流,原創文章,文筆有限,才疏學淺,文中如有不正之處,萬望告知。

相關文章
相關標籤/搜索