(十六)SVG

来源:互联网 发布:sql row_number() over 编辑:程序博客网 时间:2024/05/21 13:13

版权声明:本文为博主原创文章,未经博主允许不得转载。

本文纯个人学习笔记,由于水平有限,难免有所出错,有发现的可以交流一下。

一、概述

1.SVG

SVG,全称为 Scalable Vector Graphics 可伸缩矢量图形。
附:w3school 的链接 http://www.w3school.com.cn/svg/svg_intro.asp

什么是 SVG

SVG 指可伸缩矢量图形 (Scalable Vector Graphics)
SVG 用来定义用于网络的基于矢量的图形
SVG 使用 XML 格式定义图形
SVG 图像在放大或改变尺寸的情况下其图形质量不会有所损失
SVG 是万维网联盟的标准
SVG 与诸如 DOM 和 XSL 之类的 W3C 标准是一个整体

SVG 的优势

SVG 可被非常多的工具读取和修改(比如记事本)
SVG 与 JPEG 和 GIF 图像比起来,尺寸更小,且可压缩性更强。
SVG 是可伸缩的
SVG 图像可在任何的分辨率下被高质量地打印
SVG 可在图像质量不下降的情况下被放大
SVG 图像中的文本是可选的,同时也是可搜索的(很适合制作地图)
SVG 可以与 Java 技术一起运行
SVG 是开放的标准
SVG 文件是纯粹的 XML

矢量图像与位图图像

矢量图像
SVG 是 W3C 推出的一种开放标准的文本式矢量图形描述语言,他是基于 XML 的、专门为网络而设计的图像格式。
SVG 是一种采用 XML 来描述二维图形的语言,所以它可以直接打开 xml 文件来修改和编辑。

位图图像
位图图像的存储单位是图像上每一点的像素值,因而文件会比较大,像GIF、JPEG、PNG等都是位图图像格式。

2.Vector

在 Android 中指的是 Vector Drawable,也就是 Android 中的矢量图。前端用的是 SVG,我们在安卓中用到的是一个 SVG 的简化版 Vector Drawable。并不支持全部的 SVG 语法,现已支持的完全足够用了。

3.补充

Vector 图像刚发布的时候,是只支持 Android 5.0+的,自从 AppCompat 23.2 之后,Vector 可以使用于Android 2.1以上的所有系统,只需要引用com.android.support:appcompat-v7:23.2.0以上的版本就可以了。(所谓的兼容,即低版本非真实使用 SVG ,而是生成 PNG 图片

二、微信里的 SVG

http://mp.weixin.qq.com/s?__biz=MzAwNDY1ODY2OQ==&mid=207863967&idx=1&sn=3d7b07d528f38e9f812e8df7df1e3322&scene=4#wechat_redirect

这篇文章是微信对 SVG 与 PNG的比较

1)清晰度
SVG 图片是根据 Path 进行绘制出来的,而 PNG则是按原先的大小进行缩放,这时候 SVG 图片的清晰度明xian高于 PNG。

2)体积
SVG 的体积比 PNG 小很多,特别是一个项目中图片较多的时候,如果全部替换,可以省出很大的一个体积,在优化的时候,进行 app 瘦身可以考虑图片换成 SVG。

3)性能
按微信的测试结果,SVG 图片加载的时候跟 PNG 相比,有很大的优势,虽然在 Draw 的时候因为没有硬件渲染导致性能远不如 PNG,但是整体时间(加载、渲染) SVG 约是 PNG 的三分之一。

三、Vector Drawable

Vector Drawable相对于普通的Drawable来说,有以下几个好处:

(1)Vector图像可以自动进行适配,不需要通过分辨率来设置不同的图片。
(2)Vector图像可以大幅减少图像的体积,同样一张图,用Vector来实现,可能只有PNG的几十分之一。
(3)使用简单,很多设计工具,都可以直接导出SVG图像,从而转换成Vector图像 功能强大。
(4)不用写很多代码就可以实现非常复杂的动画 成熟、稳定,前端已经非常广泛的进行使用了。

1.语法

通过使用 Path 标签,几乎可以实现 SVG 中的其它所有标签,可能会复杂一点。

Path指令解析如下所示:

M = moveto(M X,Y) :将画笔移动到指定的坐标位置,相当于 android Path 里的moveTo()
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():关闭路径(会自动绘制链接起点和终点)

作为开发可以不需要精通这些语言,只需要了解,能够对这些 SVG 图片进行简单修改即可。

2.相关在线工具

SVG 编辑器:http://editor.method.ac/
可以在这个网站上进行在线 SVG 图片编辑,编辑完成后可以直接保存为 .svg 结尾的 SVG 图片。

SVG 图片转 Vector Drawable: http://inloop.github.io/svg2android/
把 SVG 图片直接拉进来,即可转化为 Vector 图片。

SVG 图片库:
http://www.shejidaren.com/8000-flat-icons.html
http://www.flaticon.com/
http://www.iconfont.cn/plus — 阿里巴巴

可以直接从这些网站取搜索自己想要的图标。

3.Vector Asset

Android Studio 自带的 Vector 工具,使用这个也是可以的。
这里写图片描述

四、Vector Drawable 的使用

这边采用的是 Android Studio 进行开发。

把 SVG 图片解析成 Vector Drawable,保存成 .xml 的文件,然后移到 drawable 下面即可使用。

这里写图片描述

Vector Drawable 在安卓5.0以上的使用跟其他图片没有区别,在5.0以下的时候需要注意进行兼容处理。

1、使用Android Studio 2.2以上的版本,gradle版本在2.0以上,准备步骤

1.1、build.gradle 添加defaultConfig {    vectorDrawables.useSupportLibrary = true}1.2、添加 compile 'com.android.support:appcompat-v7:25.3.1' //需要是23.2 版本以上的1.3、Activity 需要继承与 AppCompatActivity1.4、布局文件当中添加 xmlns:app="http://schemas.android.com/apk/res-auto"

这样就可以完美的进行兼容。

2.有时需要在 Actvity 前面添加一个 flag 设置

    static {        AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);    }

1.android:src 下使用

xml 引用:

<android.support.constraint.ConstraintLayout    xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    xmlns:app="http://schemas.android.com/apk/res-auto"    android:layout_width="match_parent"    android:layout_height="match_parent"    tools:context="com.xiaoyue.svgvector.MainActivity">    <ImageView        android:id="@+id/iv"        android:layout_width="24dp"        android:layout_height="24dp"        app:srcCompat="@drawable/hmg" /></android.support.constraint.ConstraintLayout>

注:这边需要采用 app:srcCompat 才可以在5.0系统以下使用,如果使用 android:src 标签,在5.0以上可以正常使用,但是在5.0以下的系统会报错。

代码引用:

    ImageView hmg = (ImageView) findViewById(R.id.hmg);    hmg.setImageResource(R.drawable.hmg);
    <ImageView        android:id="@+id/hmg"        android:layout_width="48dp"        android:layout_height="48dp" />

2.android:background 下使用

android:background 没有对应的 AppCompat 属性,要想在 android:background 中使用,必需依赖于 selector

xml 引用:
hmg_select.xml :

<?xml version="1.0" encoding="utf-8"?><selector xmlns:android="http://schemas.android.com/apk/res/android">    <item android:drawable="@drawable/hmg"/></selector>

布局文件:

  <ImageView        android:id="@+id/hmg"        android:layout_width="48dp"        android:layout_height="48dp"        android:background="@drawable/hmg_select" />

同时,需要在对应的 Activity 中添加一个 flag 设置。

    static {        AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);    }

代码引用:

    ImageView hmg = (ImageView) findViewById(R.id.hmg);    hmg.setBackgroundResource(R.drawable.hmg_select);

代码引用,也只能设置 select,不可直接使用 Vector Drawable,否则5.0以下系统也会报错。

总结:兼容5.0以下系统的时候,没有采用 AppCompat 的话,都必须依赖于 select ,同时在 Activity 中添加 flag。

五、动态 Vector Drawable

1.动画基础

先来个简单的例子:
这里写图片描述

新建一个 Vector Drawable
直接利用 Android Studio 生成一个 Vector Drawable。
这里写图片描述

找到 check 的图标,一直下一步。
这里写图片描述

这时候生成一个 ic_check.xml 的 Vector Drawable。

<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:name="path_check"        android:fillColor="#FF000000"        android:pathData="M9,16.17L4.83,12l-1.42,1.41L9,19 21,7l-1.41,-1.41z"/></vector>

这里需要给要执行动画的 Path 加上 name 属性,提供给动画寻找对应的目标。

vector 拥有的属性

android:name 定义该drawable的名字

android:width 定义该 drawable 的内部(intrinsic)宽度,支持所有 Android 系统支持的尺寸,通常使用 dp

android:height 定义该 drawable 的内部(intrinsic)高度,支持所有 Android 系统支持的尺寸,通常使用 dp

android:viewportWidth 定义矢量图视图的宽度,视图就是矢量图 path 路径数据所绘制的虚拟画布

android:viewportHeight 定义矢量图视图的高度,视图就是矢量图 path 路径数据所绘制的虚拟画布

android:tint 定义该 drawable 的 tint 颜色。默认是没有 tint 颜色的

android:tintMode 定义 tint 颜色的 Porter-Duff blending 模式,默认值为 src_in

android:autoMirrored 设置当系统为 RTL (right-to-left) 布局的时候,是否自动镜像该图片。比如 阿拉伯语。

android:alpha 该图片的透明度属性

新建动态 Drawable
在 deawable 下新建一个 check_anima.xml。

<?xml version="1.0" encoding="utf-8"?><animated-vector xmlns:android="http://schemas.android.com/apk/res/android"    android:drawable="@drawable/ic_check">    <target        android:animation="@animator/check_animator"        android:name="path_check">    </target></animated-vector>

android:drawable 选取的是要执行动画的 Vector Drawable。target 分别记录着该 Vector Drawable 下需要执行动画的 Path,以及动画。一个 Vector Drawable 可能多条 Path 同时执行不同的动画。

Path 执行的动画 check_animator
在 /res/animator 下新建文件 check_animator.xml

<?xml version="1.0" encoding="utf-8"?><set xmlns:android="http://schemas.android.com/apk/res/android">    <objectAnimator        android:duration="500"        android:propertyName="trimPathEnd"        android:valueFrom="0"        android:valueTo="1"        android:valueType="floatType">    </objectAnimator></set>
    <!--动画时间-->    android:duration="500"    <!--Path 要改变的属性-->    android:propertyName="trimPathEnd"    <!--起始值-->    android:valueFrom="0"    <!--结束值-->    android:valueTo="1"    <!--值类型-->    android:valueType="floatType"

Path 的属性:

android:name 定义该 path 的名字,这样在其他地方可以通过名字来引用这个路径

android:pathData 和 SVG 中 d 元素一样的路径信息。

android:fillColor 定义填充路径的颜色,如果没有定义则不填充路径

android:strokeColor 定义如何绘制路径边框,如果没有定义则不显示边框

android:strokeWidth 定义路径边框的粗细尺寸

android:strokeAlpha 定义路径边框的透明度

android:fillAlpha 定义填充路径颜色的透明度

android:trimPathStart 从路径起始位置截断路径的比率,取值范围从 0 到1

android:trimPathEnd 从路径结束位置截断路径的比率,取值范围从 0 到1

android:trimPathOffset 设置路径截取的范围 Shift trim region (allows showed region to include the start and end), in the range from 0 to 1.

android:strokeLineCap 设置路径线帽的形状,取值为 butt, round, square.

android:strokeLineJoin 设置路径交界处的连接方式,取值为 miter,round,bevel.

android:strokeMiterLimit 设置斜角的上限,Sets the Miter limit for a stroked path. 注:当strokeLineJoin设置为 “miter” 的时候, 绘制两条线段以锐角相交的时候,所得的斜面可能相当长。当斜面太长,就会变得不协调。strokeMiterLimit 属性为斜面的长度设置一个上限。这个属性表示斜面长度和线条长度的比值。默认是 10,意味着一个斜面的长度不应该超过线条宽度的 10 倍。如果斜面达到这个长度,它就变成斜角了。当 strokeLineJoin 为 “round” 或 “bevel” 的时候,这个属性无效。

布局文件

<?xml version="1.0" encoding="utf-8"?><android.support.constraint.ConstraintLayout    xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    xmlns:app="http://schemas.android.com/apk/res-auto"    android:layout_width="match_parent"    android:layout_height="match_parent"    tools:context="com.xiaoyue.svgvector.MainActivity">    <ImageView        android:id="@+id/check"        android:layout_width="48dp"        android:layout_height="48dp"        android:onClick="anim"        app:srcCompat="@drawable/check_anima"/></android.support.constraint.ConstraintLayout>

一样要采用 AppCompat 下的标签,否则5.0以下系统不支持。

Activity

public class MainActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);    }    public void anim(View view) {        Drawable drawable = ((ImageView)view).getDrawable();        ((Animatable)drawable).start();    }}

通过这个 demo,基本可以了解到整个 Vector Drawable 动画的流程。简单的说,就是在引用的 Drawable 中把 Vector Drawable 上的路径和对应的 Animator 关联起来。
这里写图片描述

有时候我们需要对几个路径一起处理,可以在 Vector Drawable 中使用 group 元素来把多个 path 放到一起。

group 支持的属性如下:

android:name 定义 group 的名字

android:rotation 定义该 group 的路径旋转多少度

android:pivotX 定义缩放和旋转该 group 时候的 X 参考点。该值相对于 vector 的 viewport 值来指定的。

android:pivotY 定义缩放和旋转该 group 时候的 Y 参考点。该值相对于 vector 的 viewport 值来指定的。

android:scaleX 定义 X 轴的缩放倍数

android:scaleY 定义 Y 轴的缩放倍数

android:translateX 定义移动 X 轴的位移。相对于 vector 的 viewport 值来指定的。

android:translateY 定义移动 Y 轴的位移。相对于 vector 的 viewport 值来指定的。

2.改变 Path

在上面的 Animator 里面可以对 Path 的一些属性进行改变,从而达到动画的效果。这边还有一个特殊的变化,那就是直接改变整条 Path。

先来看一个效果:
这里写图片描述

这是一个五角星变成一个五边形的动画效果。下面是五角星和五边形的 Path:

    //五角星 Path    "M 48,54 L 31,42 15,54 21,35 6,23 25,23 32,4 40,23 58,23 42,35 z"    //五变形 Path    "M 48,54 L 31,54 15,54 10,35 6,23 25,10 32,4 40,10 58,23 54,35 z"

要实现 Path 的移动,要求移动前后的两个 Path,拥有相似的结构(动作和点的个数)。五角星的第一个操作为 M,第二个操作为 L,则要求五边形的 Path 也必须是这样的。五边形的 Path 本来在 L 的时候只需要在来四个点即可,在这边变成9个点,是为了跟五角星的点数相同。

Vector Drawable

<vector xmlns:android="http://schemas.android.com/apk/res/android"        android:width="120dp"        android:height="120dp"        android:viewportHeight="64"        android:viewportWidth="64">    <group>        <path            android:name="star"            android:fillColor="#22e171"            android:pathData="M 48,54 L 31,42 15,54 21,35 6,23 25,23 32,4 40,23 58,23 42,35 z"            android:strokeColor="#000000"            android:strokeWidth="1"/>    </group></vector>

Drawable

<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"                 android:drawable="@drawable/fivestar">    <target        android:name="star"        android:animation="@animator/anim_fivestar_morph" /></animated-vector>

Animator

<objectAnimator    xmlns:android="http://schemas.android.com/apk/res/android"    android:duration="1000"    android:propertyName="pathData"    android:valueFrom="M 48,54 L 31,42 15,54 21,35 6,23 25,23 32,4 40,23 58,23 42,35 z"    android:valueTo="M 48,54 L 31,54 15,54 10,35 6,23 25,10 32,4 40,10 58,23 54,35 z"    android:valueType="pathType"/>

onClick 的处理需要改变一下:

   public void anim(View view) {        ImageView imageView = (ImageView) view;        AnimatedVectorDrawable tickToCross = (AnimatedVectorDrawable) getDrawable(R.drawable.fivestat_anim);        imageView.setImageDrawable(tickToCross);        if (tickToCross != null) {            tickToCross.start();        }    }

注:Path 的改变只支持5.0以上的系统。

原创粉丝点击