Android SVG

鋸齒流沙發表於2018-01-08

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得到向量圖。

View

AS中為Vector提供了大量的向量製作圖形

View

同樣開發者可以選擇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>
複製程式碼

View

動態Vector

有靜態的Vector,就有動態的Vector,動態Vector才是Android Vector Drawable的精髓所在。

在Android5.0以上,Google引入了大量的線圖動畫,頁面發生改變,icon不再生硬地切換。如下面這組:

Vector

這是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影象過於複雜時,不僅僅要注意繪製效率,初始化效率也是需要考慮的重要因素;

相關文章