android圖片系列 (4) - SVG動(dòng)畫(動(dòng)態(tài)SVG 圖片)

看過之前那篇介紹靜態(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)矢量圖

Snip20170701_6.png

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

Snip20170701_8.png

最上面的 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)畫

Snip20170701_9.png

這當(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)畫:

Snip20170701_9.png

剪切路徑動(dòng)畫是使用的屬性動(dòng)畫中的 trimPathStart/trimPathEnd 來實(shí)現(xiàn)的

通常的位移,旋轉(zhuǎn),縮放,漸變動(dòng)畫

Snip20170701_10.png

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

Snip20170701_11.png

變換路徑操作的是屬性動(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下的資源。

參考資料:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容