UI設計師SVG動畫進階篇——蒙版動畫(上)

泱泱發表於2017-05-18

蒙版對於UI設計師來說,太熟悉不過了,當然了,可能PS裡面用的多一些,AI裡面用的少一些,SVG同樣支援蒙版,而且藉助蒙版,能完成很多神奇的效果。我喜歡稱蒙版動畫為一種魔術,這是真正的“障眼法”,它只讓你看到想要看到的部分。
前面SVG的動畫效果裡,有兩次用過了蒙版,一個是在路徑動畫中(juejin.im/post/590941… 這篇文章的結尾),利用蒙版的路徑描邊動畫,逐漸畫出白色的螺旋線,從而動態顯示底部的小豆豆組成的路徑,達到飛機撒播小豆的效果。
還有一次是在路徑變形動畫中(juejin.im/post/59195c… 第9部分的內容),利用蒙版的路徑變形動畫來實現鏤空圖形的變形動畫。這還只是蒙版動畫的冰山一角,下面會介紹幾個有代表性的應用,掌握了蒙版動畫之後,嗯,你會開啟一扇全新的門。

1.SVG蒙版基本語法

先簡單說一下SVG蒙版的基本語法,給沒有SVG基礎的UI設計師入入門。

<mask id="shade"><circle cx="50" cy="50" r="30" /></mask>
<rect mask="url(#shade)"/>複製程式碼

表示我定義了一個半徑30的圓形蒙版shade,矩形使用這個shade蒙版。蒙版如果裡面不定義任何形狀,則預設為全黑蒙版,也就是說,使用蒙版的形狀完全被遮罩了,蒙版裡定義的任何形狀都是在這個黑色畫布上進行繪製的。至於使用過程中,那自然是各種變化多多,下面由淺入深,慢慢來講。

2.靜態SVG蒙版

這個嚴格來說不是蒙版動畫,而是蒙版下的動畫,還記得馮老闆的新電影《我不是潘金蓮》裡面獨特的表現手法吧,所有畫面集中於一個圓形的視窗裡,那用蒙版來實現的話,就是黑色底上放一個白色的圓形。下面就來模擬一下這種效果。這是我做的一個水波紋的動態效果
(實現方法可以參考以前發過的路徑變形動畫)。

水波紋動態效果
水波紋動態效果

一開始說過預設的蒙版是全黑的,這樣我們只需要加白色一個圓形就可以實現圓形的視窗了。
蒙版動畫原理
蒙版動畫原理

簡化程式碼及註釋如下:

<svg>
<style>
@keyframes deform1{0% {d:path('');} 100%{d:path('');}}/*第一個路徑變形動畫*/
@keyframes deform1{0% {d:path('');} 100%{d:path('');}}/*第二個路徑變形動畫*/
#animate1 {animation: deform1 2s alternate infinite ;fill:#71CFD1;opacity:0.5}/*設定透明度*/
#animate2 {animation: deform2 2s alternate infinite;fill:#71CFD1;opacity:0.3} 
</style>
<mask id="shade"><circle fill="#ffffff" cx=" " cy=" " r="200"/></mask><!--定義蒙版-->
<g mask="url(#shade)"><!--把變形動畫放到一個組裡,再呼叫蒙版-->
<path  id="animate1" />
<path  id="animate2"/>
</g>複製程式碼

看一下效果:

使用蒙版後的效果
使用蒙版後的效果

圓形視窗實現了,但似乎少了些什麼,不錯,就是黑色的背景,這裡有兩種新增方法,可以在AI裡面繪製一箇中間為鏤空的圓形的黑色矩形,鏤空圓形部分與蒙版裡的白色圓形重合,但還有一個偷懶的好方法,就是不用蒙版(搞什麼?!)。直接把這個鏤空的黑色矩形,放到變形動畫上面就好了。這樣路徑部分程式碼簡化如下:

<path  id="animate1" />
<path  id="animate2"/>
<path d=""/> <!--黑色鏤空矩形對應的路徑-->複製程式碼

注意一下路徑疊加的順序,從上到下對應AI裡的圖層順序從下到上。也就是瀏覽器先渲染排序在前的路徑圖形,然後層層疊加。
效果棒棒噠

直接使用黑色鏤空矩形遮住多餘區域
直接使用黑色鏤空矩形遮住多餘區域

當然了,蒙版的方法還是要掌握的,因為這是唯一一個特例嘛。而且缺點顯而易見,你的矩形不能任意控制大小,只能大於被遮住的動畫的區域。
如果說這種簡單的圓形無法體現蒙版的優勢,那下面這種會展現的更為充分。

注水的杯子
注水的杯子

簡單說一下杯子和蒙版的關係

杯子與蒙版
杯子與蒙版

來看程式碼部分:

<mask id="shade"><path fill="#FFFFFF" d=" "/></mask>
<g mask="url(#shade)">
<path  id="animate1"/>
<path  id="animate2"/>
</g>
<g>
…此處省略若干杯子形狀的程式碼…
</g>複製程式碼

其實大多數工作AI會幫我們很好的完成,我們要做的不過是定義動畫和擺好各個圖形的關係而已。這種給容器里加水的動效,如果不借助,那麼做變形動畫的時候還要精確計算邊緣,而利用蒙版,不但動態底圖繪製時無所畏忌,還可以實現多個不同容器同時加水的動畫,只要蒙版上多繪製幾個白色的容器形狀就可以了。來點小小的改動,發揮一下SVG的優勢,來個大雜燴,咖啡,紅酒,橙汁,我們只要改變定義的變形動畫的填充色,嗯,就這麼簡單。

三杯飲料~
三杯飲料~

3.文字蒙版

蒙版的強大,不僅僅在於支援圖形,同樣還支援文字,通過文字蒙版,還可以輕鬆實現填充變換的文字。比如我做了一個漸變的動態背景,這個用CSS3實現比用SVG更容易,不過我懶,就直接用SVG實現了,而且用的是最不靠譜的方法,動態背景實現方法很多,我是讓一個很大的漸變背景位移實現的,沒用過SVG漸變填充的可以看一下,就是下面這種方法:

<svg width="800"  height="600" >
<style>
@keyframes animate{
0% {transform: translateX(0px) translateY(0px)}
100% {transform: translateX(-3000px) translateY(-2000px)}}
rect{animation:animate 4s alternate infinite}
</style>
<defs>
<linearGradient id="dream" x1="0%" y1="0%" x2="100%" y2="100%" spreadMethod="pad">
<stop offset="0%"   stop-color="#345ca5" />
<stop offset="20%" stop-color="#6134a5" />
<stop offset="40%" stop-color="#3479a5"/>
<stop offset="60%" stop-color="#2b008b"/>
<stop offset="80%" stop-color="#3DC4D0"/>
<stop offset="100%" stop-color="#5c2392"/>
</linearGradient>
</defs>
<rect x="0" y="0" width="3800" height="3600" fill="url(#dream)" />
</svg>複製程式碼

先定義一個傾斜線性漸變dream,一共6個停靠點,然後畫一個超大的矩形來使用這個漸變,並做位移動效,但由於尺寸是寫死的,所以你只能看到800*600的區域,從而實現了動態漸變效果。

動態漸變背景
動態漸變背景

那這個動態漸變如何賦給文字呢?簡單,我只需要像如下定義一下文字蒙版就可以了

<mask id="shade"><text>生如夏花</text></mask><!--文字的位置大小字型填充色單獨定義-->
<g mask="url(#shade)">
<rect x="0" y="0" width="3800" height="3600" fill="url(#dream)"/>
</g>複製程式碼

我這裡並沒有讓動態漸變的矩形去直接呼叫文字蒙版,而是外面單獨又套了一個<g>標籤,是因為我動態漸變的實現方式不好嘛,是移動實現的,如果蒙版直接給這個矩形,意味著蒙版就跟著一起跑啦。

文字蒙版實現動態漸變填充
文字蒙版實現動態漸變填充

這種效果還有一個實現方法是可以把文字轉成路徑再匯出,但若論起易用性,自然文字蒙版更好一些,因為文字可以隨心所欲的修改。如果你喜歡,你還可以把這種效果賦給描邊,不過這次描邊是白色,填充時黑色,會得到像下面這種:

文字蒙版實現的動態漸變描邊
文字蒙版實現的動態漸變描邊

4.帶透明度的蒙版

見識過文字蒙版之後,說一下帶透明度的蒙版,SVG的蒙版真真是和作圖工具中的蒙版一模一樣,依然支援透明度,漸變,怎麼都行,因為我沒想到太好的案例,所以還是拿我們上面的案例下刀吧。
我給文字蒙版的上面再加一個蒙版,蒙版新增方式如下:

再套一層蒙版
再套一層蒙版

程式碼如下:

<mask id="shade"> <text x="" y="" >生如夏花</text></mask>
<mask id="shade2"><!--由灰色矩形和白色矩形組成的蒙版-->
<rect fill="#969696" x="0" y="0" width="800" height="150"></rect>
<rect fill="#ffffff" x="0" y="150" width="800" height="300"></rect>
</mask>
<g mask="url(#shade2)"> <!--新加蒙版-->
<g mask="url(#shade)">
<rect x="0" y="0" width="3800" height="3600" fill="url(#dream)" id="aaa"/><!--由於新加蒙版使用了矩形,所以這裡要給矩形背景一個id,並修改CSS樣式。-->
</g>
</g>    複製程式碼

那效果是怎樣呢?

水晶效果
水晶效果

新加的蒙版產生了水晶效果。
漸變的效果來看一下
加漸變蒙版後的效果
加漸變蒙版後的效果

雖然不及上面那個效果明顯,但還是可以看出來蒙版發揮的作用。

5.動態蒙版位移動畫

以上都是靜態蒙版的應用,其作用就是重新生成一個視窗。下面,要開始動態蒙版的介紹了,等真正會用動態蒙版之後,SVG動畫簡直可以發揮想象不到的強大。動態蒙版說白了和普通形狀的動效是一樣的,無非以蒙版效果展現而已,依舊從最簡單的入手,來一個日食的效果。
動畫思路理一下

日食過程
日食過程

這個用蒙版似乎很簡單。當一個白色底色上黑色圓形組成的蒙版從左到右水平位移時,自然就會遮擋住太陽


程式碼如下:

<svg width="800"  height="600" >
<style>
@keyframes animate{
0% {transform: translateX(0)}
100% {transform: translateX(390px)}
}
#dog{animation:animate 4s ease 2s}
</style>
<mask id="shade"> <rect x="0" y="0" width="800" height="600" fill="#FFFFFF"/><circle cx="205" cy="200" r="95" fill="#000000" id="dog"/></mask>
<circle cx="400" cy="200"  r="100" fill="#ff7f00" mask="url(#shade)" />
</svg>複製程式碼

產生的動畫效果是下面這種

天狗吃月亮
天狗吃月亮

可是我還想用黑色的部分來表示被侵吞的太陽,怎麼辦呢?再加一個黑色圓形同步位移肯定是不行的,會露出來。靈機一動,沒錯,我們可以讓太陽所在的圓形區域作為靜態蒙版的白色部分,加在同步位移的黑色圓形上。然後再加上一個隨著太陽被侵吞的變化背景,程式碼如下:

<svg width="800"  height="600" >
<style>
@keyframes animate1{  /*定義變化的背景色*/
0% {fill:#c0f1ff;}
50% {fill:#1d3074;}
100% {fill:#c0f1ff;}
}
rect{animation:animate1 4s;fill:#c0f1ff;}
@keyframes animate2{
0% {transform: translateX(0)}
100% {transform: translateX(390px)}
}
#dog{animation:animate2 4s}
</style>
<rect width="800" height="600" /> <!--先繪製最下層的天空-->
<circle cx="400" cy="200"  r="100" fill="#ff7f00"  /><!--其次是完整的太陽-->
<mask id="shade"><circle cx="400" cy="200" r="100" fill="#FFFFFF" /></mask>
<g mask="url(#shade)">
<circle cx="205" cy="200" r="95" fill="#000000" fill-opacity="0.7" id="dog" />
</g>
</svg>複製程式碼

效果如下:

加上天空變化
加上天空變化

機智的你一定會發現,咦,這不是用不著動態蒙版了嘛,沒有關係,萬一其他地方用得上呢,比如想做個月圓月缺對吧。

寫到這裡,感覺又囉裡囉嗦說了太多,所以還有一部分還是放到下篇吧。

相關文章