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图像过于复杂时,不仅仅要注意绘制效率,初始化效率也是需要考虑的重要因素;