讓動(dòng)效更酷炫!4 個(gè)常見(jiàn)且常用的 SVG 交互動(dòng)畫(huà)方法

本文介紹了 4 種常見(jiàn)的 SVG 交互動(dòng)畫(huà)方法,幫你了解 SVG 交互動(dòng)畫(huà)的原理和簡(jiǎn)單方法。

優(yōu)秀的人機(jī)交互和舒適合理的動(dòng)畫(huà),一直是 UX 設(shè)計(jì)師孜孜不倦追求的目標(biāo)。但 UX 設(shè)計(jì)師每天都遇到能做出效果,和程序交接、方案落地時(shí)卻困難重重的情況。要么是程序覺(jué)得這么多動(dòng)畫(huà)會(huì)很卡,要么認(rèn)為 UX 給的方案花里胡哨根本做不出來(lái)。每當(dāng)在 Behance 或者 Dribbble 上看到優(yōu)秀的交互設(shè)計(jì)稿,網(wǎng)友都會(huì)戲稱程序員說(shuō):「來(lái)來(lái)來(lái),鍵盤(pán)給你好吧,你來(lái)寫(xiě)?!箯倪@些戲言中也不難看出 UX 和程序落地其實(shí)沒(méi)有很好的技術(shù)溝通橋梁。

目前,SVG 的動(dòng)畫(huà)方案已可以解決一部分 UX 設(shè)計(jì)師和程序交接落地問(wèn)題,但是這些動(dòng)畫(huà)出現(xiàn)場(chǎng)景往往是圖標(biāo)、引導(dǎo)頁(yè)等,到核心的程序交互還是靠程序員去寫(xiě)交互邏輯動(dòng)畫(huà)。其中原因就是可交互的 SVG 動(dòng)畫(huà)方案尚不普及,國(guó)內(nèi)外都沒(méi)有很好的公開(kāi)資料。所以這次就來(lái)和大家分享一下,我已經(jīng)掌握的可交互 SVG 動(dòng)畫(huà)的可行方案。

由于 lottie 的方案相比于 SVG 有更好的自由度,在交互層面是完勝的。所以本次我將以 lottie 作為方案背景,來(lái)分享可交互 SVG 動(dòng)畫(huà)的原理和案例。由于我們團(tuán)隊(duì)目前主要是幫主播定制直播禮物特效和直播 UI,所以我希望在能減少設(shè)計(jì)工作量的同時(shí),為禮物動(dòng)效增加可交互性,從而讓禮物特效變得更多變,更加有意思。下面我們進(jìn)入正題,首先來(lái)了解下,什么是可交互的 SVG 動(dòng)畫(huà)?

什么是可交互的SVG動(dòng)畫(huà)?

之前的案例我們做的都是固定不變的動(dòng)畫(huà),假如我希望動(dòng)畫(huà)內(nèi)容是個(gè)性化的信息填充,這樣我們就需要讓 SVG 動(dòng)畫(huà)變成框架動(dòng)畫(huà),動(dòng)畫(huà)的內(nèi)容由后臺(tái)給出再填充動(dòng)畫(huà),最后呈現(xiàn)給使用者。最簡(jiǎn)單的例子就是產(chǎn)品的輪播圖。再假如,我希望動(dòng)畫(huà)的播放進(jìn)程是根據(jù)頁(yè)面滾動(dòng)來(lái)觸發(fā)播放,同時(shí)動(dòng)畫(huà)會(huì)和頁(yè)面的高度百分比同步進(jìn)度。那這些想法的落地就需要為 SVG 動(dòng)畫(huà)插上交互的翅膀,讓它能夠提高用戶體驗(yàn)。

我們先來(lái)看 3 個(gè)由 lottie-web 的開(kāi)發(fā)者 hernan,制作的一些可交互 SVG 動(dòng)畫(huà) demo,看完你就大致能了解到它的強(qiáng)大之處 。

讓動(dòng)效更酷炫!4 個(gè)常見(jiàn)且常用的 SVG 交互動(dòng)畫(huà)方法

△ Codepen:https://codepen.io/airnan/pen/gvBMPV

變色龍會(huì)根據(jù)鼠標(biāo)指向的葉片顏色來(lái)改變身體的顏色,當(dāng)鼠標(biāo)移動(dòng)到葉片中間時(shí),鼠標(biāo)指針會(huì)被吃掉。

讓動(dòng)效更酷炫!4 個(gè)常見(jiàn)且常用的 SVG 交互動(dòng)畫(huà)方法

△ Codepen:https://codepen.io/airnan/pen/bmvegP

機(jī)器人會(huì)根據(jù)控制面板的一些屬性,來(lái)變換走路或者跑步的姿態(tài),其中動(dòng)畫(huà)的 rigging 使用的是 Duik。

讓動(dòng)效更酷炫!4 個(gè)常見(jiàn)且常用的 SVG 交互動(dòng)畫(huà)方法

△ Codepen:https://codepen.io/airnan/pen/rvQrKL

動(dòng)畫(huà)會(huì)根據(jù)輸入的內(nèi)容和鼠標(biāo)點(diǎn)擊來(lái)完成分階段的動(dòng)畫(huà)。

由于這三個(gè)例子的交互方法算是比較復(fù)雜,其中涉及到了多種交互方法的交叉應(yīng)用,所以我認(rèn)為并不適合用這三個(gè)例子做初步技術(shù)分享。第一篇我會(huì)以更加淺顯的案例,來(lái)分享這些交互動(dòng)畫(huà)制作技術(shù)。

訪問(wèn)并修改動(dòng)畫(huà)的可行方案

在使用 AE 制作完動(dòng)畫(huà),并使用 Bodymovin 導(dǎo)出動(dòng)畫(huà)后,我們會(huì)獲得一個(gè) data.json 文件。這個(gè)文件包含了 AE 中關(guān)于動(dòng)畫(huà)的所有屬性和對(duì)應(yīng)的值,當(dāng)前端加載動(dòng)畫(huà)時(shí),就會(huì)讀取 json 文件中的數(shù)據(jù)并實(shí)時(shí)計(jì)算重繪制動(dòng)畫(huà)。

根據(jù)這個(gè)流程,如果我想要臨時(shí)更改動(dòng)畫(huà)的某一個(gè)屬性,那么可操作的方案大致有三種:

  • 第一種是直接訪問(wèn)請(qǐng)求到的 json 文件中的鍵并修改它的值,修改完再渲染播放動(dòng)畫(huà)。
  • 第二種是使用 lottie_api.js(https://github.com/bodymovin/lottie-api)來(lái)訪問(wèn)修改 json 文件中的內(nèi)容,修改完后再重新渲染動(dòng)畫(huà)。
  • 第三種是直接通過(guò) JS 去更改網(wǎng)頁(yè)中 DOM 元素的內(nèi)容。

第一個(gè)方案可以對(duì)動(dòng)畫(huà)的所有的值進(jìn)行修改,可調(diào)整的自由度非常大,但是缺點(diǎn)也很明顯,那就是前端程序必須十分熟悉導(dǎo)出的 json文件的數(shù)據(jù)結(jié)構(gòu),同時(shí)這樣的交互方案很難快速地抽象成通用的方法,從而導(dǎo)致幾乎每個(gè)動(dòng)畫(huà)都要寫(xiě)不同的 JS 來(lái)達(dá)到動(dòng)畫(huà)交互的目的。

第二個(gè)方案其實(shí)就是 lottie 的開(kāi)發(fā)者基于第一個(gè)方案寫(xiě)的一個(gè)現(xiàn)成的 JS 庫(kù),使用難度和學(xué)習(xí)成本較低。程序只需要使用這些 API 的方法,就能寫(xiě)出符合大多數(shù)業(yè)務(wù)交互的方法函數(shù)。相較之前第二個(gè)方案的缺點(diǎn)也很明顯,那就是目前 API 的公開(kāi)方法并不是很多,且只適用于 web 端,安卓和蘋(píng)果等并不能直接使用這個(gè) JS 庫(kù)(據(jù)我所知)。另外有一些較為復(fù)雜的交互還是需要與第一種方案結(jié)合來(lái)完成。

第三個(gè)方案簡(jiǎn)單快捷但是只能完成極少部分的交互效果,比較常用的案例是替換動(dòng)畫(huà)中的圖片素材,具體的方法下文會(huì)再介紹。

在 Lottie_api 的 github 網(wǎng)站上,有開(kāi)發(fā)者寫(xiě)的簡(jiǎn)單案例代碼和方法,所以這里就不純搬運(yùn)展開(kāi)了。通過(guò) Lottie_api 去修改動(dòng)畫(huà)文件的某一屬性時(shí),需要向它傳遞這個(gè)屬性在動(dòng)畫(huà)中的絕對(duì)位置。例如想要修改合成3中形狀2的填充顏色,那么我們就需要將(‘Comp 3,shape 2,Contents, Rectangle 1 ,Fill 1,Color’)這個(gè)作為參數(shù)傳遞到函數(shù)中,以讓函數(shù)去定位動(dòng)畫(huà)文件中這個(gè)屬性。由此設(shè)計(jì)師在將動(dòng)畫(huà)文件交付給程序時(shí),就需要將合成的層級(jí)邏輯圖或者直接將這個(gè)參數(shù)寫(xiě)出來(lái)一起交付。但絕大部分有使用到 SVG 動(dòng)畫(huà)的商用項(xiàng)目中,包含的動(dòng)畫(huà)肯定不止一兩個(gè),為了減輕前端開(kāi)發(fā)的交互工作量,建議在制作動(dòng)畫(huà)時(shí)對(duì)于要修改的相同類別予以相同的名稱,這樣普遍的交互方法就可以再抽象為一個(gè)函數(shù)。比如需要修改的文字內(nèi)容的圖層名稱命名為「.FeedbackMark」,在圖層名字前加「.」會(huì)讓動(dòng)畫(huà)在網(wǎng)頁(yè)加載時(shí)生成一個(gè)標(biāo)簽[class=“FeedbackMark”],前端就能通過(guò)這個(gè)屬性來(lái)篩選并修改內(nèi)容。另外,圖層名稱前加「#」會(huì)讓動(dòng)畫(huà)在生成時(shí)添加一個(gè)[id=“FeedbackMark”],但 id 在網(wǎng)頁(yè)端是唯一的,多個(gè)動(dòng)畫(huà)都用相同的 id 會(huì)導(dǎo)致網(wǎng)頁(yè)報(bào)錯(cuò),無(wú)法正常加載動(dòng)畫(huà)。

綜上,作為 UX 設(shè)計(jì)師在制作交互動(dòng)畫(huà)時(shí),首要任務(wù)就是正確的統(tǒng)一命名圖層,這會(huì)給后續(xù)的程序交互奠定一個(gè)良好的基石。下面來(lái)看看實(shí)際的例子。

實(shí)操案例

1. 修改動(dòng)畫(huà)中的圖片素材

讓動(dòng)效更酷炫!4 個(gè)常見(jiàn)且常用的 SVG 交互動(dòng)畫(huà)方法

由于 Lottie_api 中并沒(méi)有替換圖片素材的方法,所以這里使用的是直接修改渲染完的動(dòng)畫(huà)中的 URL。當(dāng) SVG 動(dòng)畫(huà)中有位圖元素時(shí),導(dǎo)出動(dòng)畫(huà)后會(huì)在 data.json 的同級(jí)目錄下生成一個(gè) images 文件夾,里面就放置了使用的位圖。比如這里我就將需要交互的圖片名字命名為 sample.jpg,放入動(dòng)畫(huà)中后,將圖層的名字重命名為「.GiverMark」。當(dāng)我需要更改這個(gè)動(dòng)畫(huà)中圖片的信息時(shí),我只需要通過(guò) JS 去找到Class=“GiverMark”,然后修改圖片的 URL 就行了。默認(rèn)情況下,被更新的圖片會(huì)自動(dòng)填充滿這個(gè)容器的寬高。 參考代碼如下:

   $(‘.GiverMark image’).attr(‘href’,’www.test.com/test.jpg’);

在設(shè)計(jì)動(dòng)畫(huà)時(shí),需要做的就是使用同一張圖來(lái)作為動(dòng)畫(huà)中的一個(gè)圖片占位符,合理規(guī)范圖片層的命名即可。

2. 修改文字內(nèi)容

讓動(dòng)效更酷炫!4 個(gè)常見(jiàn)且常用的 SVG 交互動(dòng)畫(huà)方法

修改動(dòng)畫(huà)中的文字內(nèi)容的方法,在不同的情況下需要選擇不同的交互方法。首先當(dāng)修改的文字層沒(méi)有添加文字 Animate,或者動(dòng)畫(huà)中其他部分與之沒(méi)有任何關(guān)聯(lián)時(shí),修改的方法同圖片修改 URL,我們只需要給文字圖層一個(gè)規(guī)范的命名即可。這樣前端程序就能通過(guò) JS 去更改文字層的內(nèi)容,參考代碼如下:

 $(‘.FeedBackMark text tspan').html(‘蛋卷直播實(shí)驗(yàn)室測(cè)試文字’);

當(dāng)動(dòng)畫(huà)中對(duì)文字添加了 mask 動(dòng)畫(huà),或者其他元素于文字層的屬性做了表達(dá)式的關(guān)聯(lián),那么就需要使用到 lottie_api 來(lái)完成修改,以讓動(dòng)畫(huà)正常的工作。例如:文字跟隨著 mask 路徑做上下起伏的運(yùn)動(dòng),這個(gè)動(dòng)畫(huà)實(shí)際在網(wǎng)頁(yè)中是將每個(gè)字符獨(dú)立開(kāi)渲染,所以簡(jiǎn)單的 JS 就不能做到更改內(nèi)容,同時(shí)讓新的文字動(dòng)畫(huà)正常工作。原因就在于前面的方法只修改網(wǎng)頁(yè)中已加載的內(nèi)容,而使用 lottie_api 則是修改動(dòng)畫(huà)內(nèi)容并重新計(jì)算渲染。參考代碼如下:

var animapi=lottie_api.createAnimationApi(anim);//anim為默認(rèn)動(dòng)畫(huà)的程序名字
var animkp=animapi.getKeyPath(‘.FeedBackMark’’);
animkp.getElements()[0].setText(‘這是新的文字內(nèi)容’,0);

3. 修改圖層的任一屬性

因?yàn)?json 文件中保存了所有 AE 中圖層的屬性和值,所以我們同樣可以使用 getKeyPath 方法來(lái)定向修改圖層中的某一屬性,例如可以改變位置,更改縮放大小,更改填充顏色等等。這里還是以上面的更改文字動(dòng)畫(huà)為例,這次我們來(lái)更改動(dòng)畫(huà)的位置,參考代碼如下:

var  animapi=lottie_api.createAnimationApi(anim);//anim為默認(rèn)動(dòng)畫(huà)的程序名字     
var  animkp=animapi.getKeyPath('.FeedBackMark,Transform,Position');
animapi.addValueCallback(animkp,[0,0]);

這里要注意的是 AE 中的動(dòng)畫(huà)屬性的值大多是以數(shù)組來(lái)保存的,所以我們傳遞參數(shù)的時(shí)候要根據(jù)該屬性的值的類型,來(lái)傳遞修改后的值。另外,修改顏色時(shí)我們傳遞的顏色色值必須是 rgba 格式,且需要對(duì)顏色進(jìn)行換算,例如 #333333 的 RGB 值為(50,50,50),那么傳遞參數(shù)時(shí) rgba(50/255,50/255,50/255,255/255)。

4. 修改動(dòng)畫(huà)配色

讓動(dòng)效更酷炫!4 個(gè)常見(jiàn)且常用的 SVG 交互動(dòng)畫(huà)方法

雖然我們可以通過(guò) lottie_api 來(lái)逐一修改圖層的顏色,但是當(dāng)我想要更改整個(gè)動(dòng)畫(huà)的配色時(shí),顯然這樣的方法不合理。更科學(xué)的方法是在合成中添一個(gè) null 圖層,然后為其添加 color control 效果,再把動(dòng)畫(huà)的圖層中的顏色,通過(guò)拉索工具連接到這個(gè) null 顏色控制中。這樣前端只需要通過(guò)一行代碼就可以訪問(wèn),并改變 color ctrl 圖層中的顏色,重渲染時(shí)與之有關(guān)的動(dòng)畫(huà)中的配色即會(huì)全部改變。參考代碼如下:

var  animapi=lottie_api.createAnimationApi(anim);//anim為默認(rèn)動(dòng)畫(huà)的程序名字
var animkp=animapi.getKeyPath('color ctrl,Effects,C1,0');
animapi.addValueCallback(animkp, function(){  return [0.1,0.2,0.3,1]});

當(dāng)我們需要更改 Effects 中的值時(shí),最后的一個(gè)參數(shù)值是屬性的索引值。這與直接訪問(wèn)屬性有點(diǎn)不同。

總結(jié)一下,作為 UX 設(shè)計(jì)師在制作交互動(dòng)畫(huà)時(shí),需要做的事就是根據(jù)團(tuán)隊(duì)的命名規(guī)則,去規(guī)范命名需要交互修改的圖層名。其次就是在與程序交接時(shí),提供給他對(duì)應(yīng)動(dòng)畫(huà)的交互屬性絕對(duì)位置信息,同時(shí),我們可以將可變信息的交互邏輯通過(guò)表達(dá)式寫(xiě)在動(dòng)畫(huà)中。這樣前端程序只需要對(duì)接動(dòng)畫(huà)即可,最終做到動(dòng)畫(huà)和交互邏輯的完美落地。

附源文件下載:https://pan.baidu.com/s/13bU7CelVG7_bkrsuAjBmZA

收藏 209
點(diǎn)贊 26

復(fù)制本文鏈接 文章為作者獨(dú)立觀點(diǎn)不代表優(yōu)設(shè)網(wǎng)立場(chǎng),未經(jīng)允許不得轉(zhuǎn)載。