用Illustrator, After Effects 做出高互動性的SVG動畫

蘇桓晨
13 min readApr 3, 2019

--

製作高互動性的SVG一直都是很多設計師的煩惱,本章介紹如何用平易近人的繪圖與動畫製作軟體建立網頁專用的SVG動圖,不僅能與使用者互動、還能依照後端資料變化的圖檔。這尤其對於資料視覺化網頁來說相當實用呢。可是本章並不是介紹將動畫直接從After Effect轉檔喔,After Effect沒辦法直接轉檔SVG,需要插件,但藉由插件所建立的動畫不態好調整、維護。

SVG製作也很適合專業分工。用Illustrator的鋼筆、After Effects的時間軸、最後匯到HTML中製作輕量動畫SVG。這三個部分接力製作的過程,讓流程可以有一個人參與,也可以有三個人分工參與(平面、動畫、程式),過程中Illustrator負責元素的設計,AE扮演著預覽、設置關鍵影格、輔助設計的角色,處理SVG的部份則將整個動畫匯出成一個3KB的永不失真動畫圖檔(多動人啊)。

開始之前你要先具備…

  • 能夠操作After Effects,Illustrator
  • 理解基礎SVG (如<path/>, <rect/>, <defs/>)

示範的成品示意圖

我利用這個動畫當做範例,圖中有容器與液體。液體會倒滿容器,容器會隨著液體而膨脹最後恢復原狀以重複動畫。這個動畫可以放在網頁上增加很多種類的互動,自由度相當高而且才3KB。

製作計畫

我們當然可以直接在SVG實作這個物件,可是何必呢?我們有了Illustrator, After Effects, Sketch等繪圖、動畫製作工具,當然要善加利用啊。

為了有效率的建立SVG向量圖,使用Illustrator製作靜態圖最好不過了,但光靠Illustrator建立錨點根本沒辦法讓圖動,於是我們借助After Effects的力量,讓我們能夠規劃動畫、預覽動畫,最後輸出動畫到SVG,SVG有SMIL的<animate>讓SVG動起來。

但注意,目前還沒有After Effects直接轉存SVG的選項,除非使用Lottie這個套件,但我們這次不用Lottie套件匯出。Lottie匯出的SVG沒辦法像我們這次的一樣調整樣式像調整CSS一樣方便直覺。這次用AE的動畫資料貼回Illustrator,再另存成SVG檔,如此一來我們就能發揮SVG當高彈性的互動潛力。所以這次順序是這樣的:

  1. 在Illustrator繪製各種所需的形狀
  2. 匯入After Effects,在AE製作使用影格獲取路徑、形狀、調整參數
  3. 透過剪貼簿到Illustrator,在AI匯入關鍵影格的形狀,擺齊形狀位置
  4. 匯出SVG格式,利用SMIL的<animate>製作動畫效果
  5. 加上自己想要的互動效果

從Illustrator繪製素材

首先我們在Illustrator利用形狀工具或是鋼筆工具放置素材,素材是會填滿的液體跟會被撐大的容器。

等等?!就這樣嗎?一個轉了45度的正方形?

沒錯,這階段我們不需要製作液體的動畫,它可以透過AE製作。事實上我做了兩個物件。一個是只有邊框的矩形;一個是有填色跟邊框的矩形。邊框的矩形(我取名container)會成為我們的容器;填色的容器(我取名liquid)將在AE套上遮罩後成為填裝的液體。

請注意!

每個點都是斤斤計較的。盡量不要讓你的AI檔有任何無關緊要的物件,例如工作區域上誤加上去的一點錨點等等。在SVG<path/>元件中,路徑的資料是由指令與位置資料組成,不同繪法都有不同指令,水平繪製是一個指令,垂直繪製是一個指令,甚至建立貝茲曲線的指令有四個。我們若是在製作途中修改到了都可能讓動畫無法實現。

在After Effects設定效果

另存成.ai檔之後,匯入After Effect中,並照計畫將填滿的形裝加上遮罩,透過遮罩形狀的移動我們能夠模擬出倒水的感覺。

事實上,你可以自行設計自己的填滿效果!在AE只是讓我們取得關鍵影格的形狀物件而用。

三個關鍵影格上的遮罩示意圖

我們都知道在AI, AE, PS裡面有錨點有控制點。一個錨點可以擁有零個、一個,最多兩個的控制點。控制點可以對稱也可以不對稱。當一個錨點沒有控制點,途中就不要多加;當一個錨點有鏡射的對稱控制點,途中就不要弄掉鏡射。因為這些會影響SVG繪製路徑的資料格式,進而影響到時動畫的成敗。

在After Effects設定容器變形

接著我在容器的路徑上位移了錨點,讓容器有變形的感覺。容器物件以及液體物件都要套用看起來才對喔!

各個關鍵影格形狀示意圖,第一張、第二張靜止,三四張變形,第五張恢復原狀。

搬移向量資料

動畫製作好之後,把複製每個關鍵影格的形狀到AI,就可以把AE關掉了(咦!?)

沒錯,透過Control/Command+C,我們可以直接將調好的路徑資料搬回Illustrator中,並重新擺放好位置。動畫將會在SVG實現,AE的工作告一段落。

成果大概是這樣,很簡單吧!

要注意不要亂增加、刪除錨點,也盡量不要改到控制點唷!

這裡命名路徑方便下面的解釋

輸出向量資料

直接用另存新檔存成SVG或是直接Control+C複製都可以,但盡量不要用檔按->轉存成SVG來輸出,因為轉存的輸出時,路徑會被簡化,這不利SVG製作補間動畫。

用文字編輯軟體打開之後可以看到很多像HTML的標籤,我們可以在這些標籤找到容器的形狀以及遮罩的形狀。先建立一個<defs>把資料放進裡面清空畫面吧!

<?xml version="1.0" encoding="utf-8"?>
<svg ...>
<defs>
<g id="container-shape">
<path id="container-shape-E" ... d="..."/>
<path id="container-shape-B" ... d="..."/>
<path id="container-shape-c" ... d="..."/>
<path id="container-shape-D" ... d="..."/>
<path id="container-shape-A" ... d="..."/>
</g>
<g id="liquid-clip-path">
<path id="liquid-clip-path-A" opacity="0.3" d="..."/>
<path id="liquid-clip-path-B" opacity="0.3" d="..."/>
<path id="liquid-clip-path-C" opacity="0.3" d="..."/>
</g>
</defs>
</svg>

用瀏覽器預覽確認空空如也之後,就可以放置我們的兩個物件 — 容器跟液體。

在SVG放置物件

首先建立一個<path>當做液體,標籤屬性使用#container-shape-A的屬性設定,順便改一下邊框、填色顏色。

<svg ...>
<defs>
...
</defs>
<path
id="container-shape-A"
fill="#0071BC"
stroke="#0071BC"
stroke-miterlimit="10"
d="M50,92.4c0,0-6.2-6.2-20.7-20.7S7.6,50,7.6,50s6.7-6.7,21.5- 21.5c12.7-12.8,21-21,2121s8.5,8.5,21.4,21.4C84.2,41.8,92.4,50,92.4,50s-7.7,7.1-20.3,20.3S50,92.4,50,92.4z"/>
</svg>

再加上一個<path>當做容器,標籤屬性使用#container-shape-A的屬性設定如邊框,但調填色顏色為無。製作完成之後會像這樣:

這跟我們第一步驟在Illustrator上呈現的一模一樣。

建立動畫 — 容器

在開始動畫之前我們先理解該如何動。容器要膨脹縮小,需要移動容器的路徑來達成,而移動路徑是使用SVG中的<animate>來達成。(CSS的Keyframe也能實現CSS屬性的動畫,但SVG的p屬性不在其內,Chrome以外有許多瀏覽器無法做出p的Keyframe動畫)

容器要膨縮,液體也要。液體不僅也要跟著膨縮,還要利用遮罩做出液體的動畫。也就是說,液體這物件要使用<clipPath/>來定義外觀,而<clipPath/>要使用<animate/>來達成膨縮效果。*

容器:<path> 套用<animate>
液體:<path> 套用<clipPath>,<clipPath>套用<animate>

先命名我們這兩個物件:

<svg ...><defs>
...
</defs>
<path id="container" fill="none" stroke="#0071BC" d="..."/><path id="liquid" fill="#0071BC" stroke="#0071BC" d="..."/></svg>

<animate>可以透過兩種方法實現,一種是成為目標的子元件,一種是href屬性指定目標元件。由於測試過href不是每個瀏覽器都行,所以直接利用子元件比較恰當。

<path id="container" fill="none" stroke="#0071BC" d="..."/><animate 
attributeType="XML"
attributeName="d"
keyTimes="0; 0.3; 0.6; 0.8; 1"
dur="1s"
repeatCount="indefinite"
values="(value1); (value2); (value3); (value4); (value5)"/>
<path id="liquid" fill="#0071BC" stroke="#0071BC" d="..."/>

我們依照<animate/>填入所需的屬性。我們的動畫是靠變化d屬性的完成,所以attributeName寫入d。需要留意的是values與keyTimes。在這裡Values需要填入我們每個關鍵影格的動畫內容,我們設置了五個所以填入五個,是哪五個?還記得我們AI匯出時的五個容#container-shape-A, #container-shape-B, #container-shape-C, #container-shape-D, #container-shape-E。keyTimes則是定義關鍵影格的時間,以Values的數目決定。

<container/>底下的<animate/>內,填入我們在AI轉存時的這五個形狀的路徑值。

目前長這樣:

建立動畫 —液體

液體是一大塊填色,這塊填色需要透過<animate>來動,且液體還要透過遮罩塑型,這形狀也要跟容器一樣動,總共有兩個要動的地方,我們從填色動畫開始。先在#liquid下建立<animate/>子物件。

<path id="liquid" fill="#0071BC"><animate 
attributeType="XML"
attributeName="d"
keyTimes="0; 0.5; 1"
dur="1s"
repeatCount="indefinite"
values="(value 1); (value 2); (value 3)"/>
</path>

這個animate標籤values值有三個值,分別代表遮罩的三個形狀,這三個值是源自於匯出SVG時的<path>,分別來自前面的標籤#liquid-clip-path-A,#liquid-clip-path-B,#liquid-clip-path-C。

這三個遮罩路徑成為<animate>的值,<animate>將幫我們補間動畫

成功之後我們建立遮罩,讓液體只呈現在容器內。

SVG中遮罩有兩種,一種是Clip-Path,一種是Mask。我們Clip-Path作範例,在<defs/>中先建立<clipPath>標籤並定義內容。

<defs>  <clipPath >    <path d="..."/>  </clipPath> </defs>

上面<path>的d屬性我們先使用#container-shape-A的內容值,等等再回頭製作遮罩的膨縮效果。

我們的動畫剩下液體的膨縮就完成了:

膨縮的效果將針對液體的遮罩,在液體的遮罩<clipPath>加入跟容器底下一樣的子元件<animate>即可:

<clipPath id="liquid-clip"><path><animate 
attributeType="XML"
attributeName="d"
keyTimes="0; 0.2; 0.5; 0.8; 1"
dur="1s"
repeatCount="indefinite"
values="(value 1); (value 2); (value 3); (value 4); (value 5)"/>
</path></clipPath>

上面的value值來自Illustrator匯入的容器形狀 #container-shape-A, #container-shape-B, #container-shape-C, #container-shape-D, #container-shape-E,我們也可以直接從容器#container的子元件<animate>複製而來。

做完之後成品如下:

加一點互動功能

我們的動畫製作完還要一點互動性,SVG除了可以直接被Javascript作更深入的互動功能以外,它還能透過一點自己的屬性看起來更玩味。

<svg id="my-svg">
...
<animate
...
begin="container.click"
repeatCount="1"
...>
...
</svg>

在所有animate加入begin=”container.click”讓動畫的啟動要透過使用者點擊SVG來觸發,repeatCount設成1能夠讓使用者每點擊一次就執行一次。我還增加了液體恢復原狀的動畫,也透過Javascript幫標籤增加點擊後的屬性改變。直接用Javascript或是SVG本身的功能也能很有趣。

有關於SVG動畫的製作就告一段落,我希望我能夠幫到其他正在研究SVG食物上應用的設計師、工程師們,如果有任何需要糾正的地方請在下方留言,謝謝指教!

--

--