SVG簡介
SVG:即Scalable Vector Graphics 可伸縮向量圖形,這種影象格式在前端中已經使用的非常廣泛了。因SVG是向量圖形,而且伸縮不會損失質量,微信也使用SVG技術,可見SVG的優勢多麼強大。
在W3C對SVG的介紹是:SVG 是使用 XML 來描述二維圖形和繪圖程式的語言。
上面中提到SVG是向量圖,那麼什麼是向量圖呢?它和點陣圖有什麼不同?
1)、向量影象:SVG是W3C 推出的一種開放標準的文字式向量圖形描述語言,他是基於XML的、專門為網路而設計的影象格式。SVG是一種採用XML來描述二維圖形的語言,所以它可以直接開啟xml檔案來修改和編輯。
2)、點陣圖影象:點陣圖影象的儲存單位是影象上每一點的畫素值,因而檔案會比較大,像GIF、JPEG、PNG等都是點陣圖影象格式。
Android中的向量圖
向量圖在Android中使用Vector Drawable表示,在AS中我們可以通過新建一個Vector asset得到向量圖。
AS中為Vector提供了大量的向量製作圖形
同樣開發者可以選擇local file選擇本地的SVG和PNG圖片來製作。最終生成一個xml檔案。
注意:
1、Vector影象剛釋出的時,只支援Android 5.0+的,自從AppCompat 23.2之後,Vector可以使用於Android 2.1以上的所有系統。
2、使用時只需要引用com.android.support:appcompat-v7:23.2.0以上的版本就可以了。 其實所謂的相容也是個坑爹的相容,即低版本並非真實使用SVG,而是生成PNG圖片。
Vector Drawable優點:
(1)Vector影象可以自動進行適配,不需要通過解析度來設定不同的圖片。
(2)Vector影象可以大幅減少影象的體積,同樣一張圖,用Vector來實現,可能只有PNG的幾十分之一。
(3)使用簡單,很多設計工具,都可以直接匯出SVG影象,從而轉換成Vector影象 功能強大。
(4)不用寫很多程式碼就可以實現非常複雜的動畫 成熟、穩定,前端已經非常廣泛的進行使用了。
Vector 語法簡介
通過使用Path標籤,幾乎可以實現SVG中的其它所有標籤,雖然可能會複雜一點,但這些東西都是可以通過工具來完成的,所以,不用擔心寫起來會很複雜。 Path標籤所支援的指令:
M = moveto(M X,Y) :將畫筆移動到指定的座標位置,相當於 android Path 裡的moveTo(),’M’處理時,只是移動了畫筆, 沒有畫任何東西;
L = lineto(L X,Y) :畫直線到指定的座標位置,相當於 android Path 裡的lineTo();
H = horizontal lineto(H X):畫水平線到指定的X座標位置 ;
V = vertical lineto(V Y):畫垂直線到指定的Y座標位置;
C = curveto(C X1,Y1,X2,Y2,ENDX,ENDY):三次貝賽曲線 ;
S = smooth curveto(S X2,Y2,ENDX,ENDY) 同樣三次貝塞爾曲線,更平滑;
Q = quadratic Belzier curve(Q X,Y,ENDX,ENDY):二次貝賽曲線;
T = smooth quadratic Belzier curveto(T ENDX,ENDY):對映 同樣二次貝塞爾曲線,更平滑;
A = elliptical Arc(A RX,RY,XROTATION,FLAG1,FLAG2,X,Y):弧線 ,相當於arcTo()
Z = closepath():關閉路徑(會自動繪製連結起點和終點);
使用上面的指令時,需要注意以下幾點:
1)座標以(0,0)為中心,X軸水平向右,Y軸水平向下
2)所有指令大小寫均可,大寫絕對定位,參照全軍座標系;小寫相對定位,參照父容器座標系。
3)指令和資料間的空格可以省略
4)同一指令出現多次可以只用一次。
SVG常用指令
L:繪製直線的指令是L,代表從當前點繪製直線到給定點,“L”之後的引數是一個點座標,如"L 200 400"繪製直線,同時還可以使用H和V指令來繪製水平、豎直線,後面的引數是x座標(H指令)或y座標(V指令)。
M:類似Android繪圖中的path類的moveTo方法,即代表將畫筆移動到某一點,但並不發生繪製動作。
A:繪製一段弧線,且允許弧線不閉合。可以把A指令繪製的弧線想象成是橢圓的某一段,A指令有以下七個函式:
1)RX,RY指所在橢圓的半軸大小;
2)XROTATION指橢圓的X軸與水平方向順時針方向的夾角,可以想象成一個水平的橢圓繞中心點順時針旋轉XROTATION的角度;
3)FLAG1只有兩個值,1表示大角度弧線,0表示小角度弧線;
4)FLAG2只有兩個值,確定從七點至終點的方向,1為順時針,0為逆時針;
5)X、Y軸為終點座標。
SVG編輯器
關於上面的SVG的語法,開發者不必全部精通,一般熟悉即可,而且這些path標籤和資料可以交給SVG編輯器來實現,如:http://editor.method.ac/
,也可以下載離線的SVG編輯器,如Inkscape。
使用SVG編輯器得到SVG,然後使用http://inloop.github.io/svg2android/
生成VectorDrawable 的xml程式碼。
除了以上的方法得到SVG,AndroidStudio本身也集合了SVG的外掛(即上面所講的Android中的向量圖
),使用外掛時,AS自動生成相容性的圖片。
除了AS中提供大量的SVG資源,一些網站同樣提供了非常多的SVG給我們使用,如設計達人和Free Vector Icons。
靜態Vector影象
靜態的Vector比較生硬,比如我們使用AS生成的VectorDrawable 。
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M20,11H7.83l5.59,-5.59L12,4l-8,8 8,8 1.41,-1.41L7.83,13H20v-2z"/>
</vector>
複製程式碼
vector標籤包含兩組寬高屬性width、height、viewportHeight、viewportWidth,他們具有不同的含義。 width、height:SVG影象的具體大小 viewportHeight、viewportWidth:定義影象被劃分的比例大小,例如例子中的400,即把24dp大小的影象劃分成400份,後面Path標籤中的座標,就全部使用的是這裡劃分後的座標系統。這樣做有一個非常好的作用,就是將影象大小與影象分離,後面可以隨意修改影象大小,而不需要修改PathData中的座標。
使用vector的時候,就當普通的圖片使用就可以了。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:padding="20dp"
android:layout_height="match_parent"
tools:context="com.main.svg.SVGActivity">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/ic_method_draw_image"/>
</RelativeLayout>
複製程式碼
動態Vector
有靜態的Vector,就有動態的Vector,動態Vector才是Android Vector Drawable的精髓所在。
在Android5.0以上,Google引入了大量的線圖動畫,頁面發生改變,icon不再生硬地切換。如下面這組:
這是Android開啟抽屜時頁面的icon動畫,相信很多讀者看過,這就是通過動態的Vector來實現的。 實現動態Vector步驟: 1)繪製靜態的VectorDrawable
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportHeight="24"
android:viewportWidth="24">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M16 1L4 1C2.9 1 2 1.9 2 3L2 17 4 17 4 3 16 3Z"/>
<group android:name="sheet">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M19 5L8 5C6.9 5 6 5.9000001 6 7.0000001L6 21c0 1.1 0.9 2 2 2l11 0c1.1 0 2 -0.9 2 -2L21 7.0000001C21 5.9000001 20.1 5 19 5Zm0 16l-11 0 0 -13.9999999 11 0z"/>
</group>
</vector>
複製程式碼
2)編寫變換的屬性動畫
<?xml version="1.0" encoding="utf-8"?>
<set
xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300"
android:fillAfter="true">
<objectAnimator
android:duration="300"
android:propertyName="translateX"
android:repeatCount="1"
android:repeatMode="reverse"
android:valueFrom="0"
android:valueTo="-4"
android:valueType="floatType"/>
<objectAnimator
android:duration="300"
android:propertyName="translateY"
android:repeatCount="1"
android:repeatMode="reverse"
android:valueFrom="0"
android:valueTo="-4"
android:valueType="floatType"/>
</set>
複製程式碼
3)使用AnimatedVectorDrawable將VectorDrawable和ObjectAnimator粘合在一起
<?xml version="1.0" encoding="utf-8"?>
<animated-vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/a">
<target
android:name="sheet"
android:animation="@anim/aa">
</target>
</animated-vector>
複製程式碼
這裡的target的android:name必須和作用的group的android:name命名一致。
4)啟動動畫
private void starAnim() {
Drawable drawable = icon.getDrawable();
if (drawable instanceof Animatable){
((Animatable) drawable).start();
}
}
複製程式碼
以上就是實現動態的Vector過程。
VectorDrawable的效能
VectorDrawable的效能問題:
1)Bitmap的繪製效率並不一定會比Vector高,它們有一定的平衡點,當Vector比較簡單時,其效率是一定比Bitmap高的,所以,為了保證Vector的高效率,Vector需要更加簡單,PathData更加標準、精簡,當Vector影象變得非常複雜時,就需要使用Bitmap來代替了;
2)Vector適用於ICON、Button、ImageView的圖示等小的ICON,或者是需要的動畫效果,由於Bitmap在GPU中有快取功能,而Vector並沒有,所以Vector影象不能做頻繁的重繪;
3)Vector影象過於複雜時,不僅僅要注意繪製效率,初始化效率也是需要考慮的重要因素;