看過之前那篇介紹靜態(tài) SVG 矢量圖片的童鞋,應(yīng)該時(shí)有感觸的,SVG 就是給我們一個(gè) 空的不限制大小的canvas畫板,然后我們使用 path 路徑去繪制我們需要的圖形,這就是靜態(tài)的 SVG。動(dòng)態(tài) SVG 就是對(duì)靜態(tài) SVG 的一種擴(kuò)展,就是給靜態(tài) SVG 加一個(gè)可以執(zhí)行動(dòng)畫操作的殼。
說的簡(jiǎn)單點(diǎn)就是這么回事,對(duì)于兼容性來說,你只要完成了前面靜態(tài) SVG 的兼容,那么這里就不用再做其他操作了。
廢話不多說,直接然我們來看看如何寫動(dòng)態(tài) SVG
先上效果圖:
這個(gè)大家看著是不是很熟悉啊,這就是那個(gè)切換抽屜的交互。使用矢量動(dòng)畫來實(shí)現(xiàn)其實(shí)很簡(jiǎn)單,就是用了一個(gè) pathData 的變換+旋轉(zhuǎn)。這里例子 地址
這是本文中學(xué)習(xí) 項(xiàng)目地址 就是下面這張圖

看到?jīng)]這幾個(gè)都是使用動(dòng)態(tài) SVG,俗稱矢量動(dòng)畫實(shí)現(xiàn)的,代碼很簡(jiǎn)單,原理也是很簡(jiǎn)單。
從實(shí)現(xiàn)上看是給靜態(tài) SVG矢量圖 VectorDrawable 添加一個(gè)殼 Animated-Vector,這里殼里面綁定了 SVG 矢量圖和 objectAnimator 的關(guān)系。對(duì)你沒看錯(cuò)就是objectAnimator屬性動(dòng)畫。
因此還有一種說法就是使用 objectAnimator屬性動(dòng)畫對(duì) SVG 矢量圖的 path 屬性進(jìn)行漸變操作,就成動(dòng)畫啦。
好了,現(xiàn)在我們一一來看一下:
SVG 靜態(tài)矢量圖

Animated-Vector 捆綁靜態(tài)矢量圖和動(dòng)畫的殼

最上面的 drawable 屬性是聲明使用哪張矢量圖,下面的 target 就是具體的捆綁關(guān)系了。 target 里面的name 屬性是說動(dòng)畫時(shí)對(duì)應(yīng)靜態(tài)矢量圖中的哪個(gè)部分,我們?cè)诋嬍噶繄D時(shí)是可以聲明 group 便簽的,這個(gè)就是為了后面的做動(dòng)畫準(zhǔn)備的。這個(gè) group 標(biāo)簽是給圖片中的某以部分圖像打個(gè)標(biāo)記,然后我們?cè)谕鈱涌梢越o這個(gè)標(biāo)記的圖片部分綁定一個(gè)動(dòng)畫。animator 就是具體的動(dòng)畫了,當(dāng)然這些動(dòng)畫都只能圍繞path 來做。
objectAnimtor 具體的動(dòng)畫

這當(dāng)然還沒完,這只能顯示出靜態(tài) SVG 在屏幕上,要讓我們的動(dòng)畫動(dòng)起來還是要執(zhí)行代碼的
public void anim(View view) {
ImageView imageView = (ImageView) view;
Drawable drawable = imageView.getDrawable();
if (drawable instanceof Animatable) {
((Animatable) drawable).start();
}
}
好了這樣一個(gè)動(dòng)畫 SVG 圖片就好了,在我們不執(zhí)行代碼時(shí)他就是一張靜態(tài) SVG 圖,我們開始執(zhí)行代碼后就可以跑我們?cè)O(shè)計(jì)的動(dòng)畫了。
這里我要感慨一些,SVG 這東西太好用了,尤其是對(duì)于 app 中我們點(diǎn)擊 icon 后做簡(jiǎn)單的動(dòng)畫來實(shí)現(xiàn)好看的交互這點(diǎn)來說,簡(jiǎn)直就是絕配啊,而且可以自由創(chuàng)作。SVG 我們?cè)诶L制path 時(shí)可以分塊,然后我們可以給按 path 塊設(shè)計(jì)不筒的動(dòng)畫,這樣是不是很簡(jiǎn)單很靈活,一個(gè) imageview 搞定。
好了來小小的總結(jié)下,每個(gè)Vector動(dòng)畫,基本都包含四部分內(nèi)容,即:
Vector:圖像資源
Animated-vector:動(dòng)畫、圖像粘合劑
ObjectAnimator:動(dòng)畫資源
代碼:?jiǎn)?dòng)動(dòng)畫
每個(gè)Vector動(dòng)畫通過這四個(gè)部分去進(jìn)行分析,就非常清晰了。
上面我們使用的trim path 的方式(剪切路徑),對(duì)path做動(dòng)畫有3種:
- trimPath 剪切路徑
- 通常的位移,旋轉(zhuǎn),縮放,漸變
- morphPath 變換路徑
我們來挨個(gè)看一下這幾個(gè)動(dòng)畫,這涉及到svg 動(dòng)畫的兼容
trimPath 剪切路徑動(dòng)畫:

剪切路徑動(dòng)畫是使用的屬性動(dòng)畫中的 trimPathStart/trimPathEnd 來實(shí)現(xiàn)的
通常的位移,旋轉(zhuǎn),縮放,漸變動(dòng)畫

morphPath 變換路徑動(dòng)畫

變換路徑操作的是屬性動(dòng)畫中的 pathData 來實(shí)現(xiàn)的
好了這3種對(duì) path 做動(dòng)畫的方式我們都看過了,這里我要說一下,兼容這東西都是不完善的,所以呢在5.0以下morphPath 變換路徑動(dòng)畫是不能使用的,寫了直接報(bào)錯(cuò)。在5.0以上版本這個(gè)morphPath 變換路徑動(dòng)畫可以使用,要是你在 xml 文件里對(duì) imageview 設(shè)置 src 屬性來指定動(dòng)態(tài)SVG 圖片,可以顯示,但不會(huì)執(zhí)行,這時(shí)系統(tǒng)的問題,你得手動(dòng)用代碼設(shè)置 src 屬性才行
ImageView imageView = (ImageView) view;
AnimatedVectorDrawable morphing = (AnimatedVectorDrawable) getDrawable(R.id.xxx);
imageView.setImageDrawable(morphing);
if (morphing != null) {
morphing.start();
}
這樣才行,手寫代碼設(shè)置圖片唄,這是因?yàn)槲覀兪褂?AppCompatActivity后,會(huì)自動(dòng)把 AnimatedVectorDrawable 轉(zhuǎn)換成 AnimatedVectorDrawableCompat ,后者是不支持 pathDatad屬性的,所以得自己手寫代碼。
其它非常奇怪、詭異、不能理解的兼容性問題,只能通過版本文件夾的方式來進(jìn)行兼容了,例如drawable-v21和drawable,分別創(chuàng)建兩個(gè)文件名相同的資源在兩個(gè)文件夾下,這樣在21以上版本,會(huì)使用drawable-v21的資源,而其它會(huì)使用drawable下的資源。
參考資料: