什么是 SVG?

Google 在 Android5.X 中增加了对 SVG 矢量图形的支持,可以用来创建高效率的动画, 所以我们先来了解一下 SVG 的定义:

  • 可伸缩矢量图形(Scalable Vector Graphics)
  • 使用 XML 格式定义图形
  • 图像在放大或改变尺寸的情况下图片质量不会有所损失
  • Android 中使用 vector 标签表示 SVG

与 bitmap 相比,SVG 最大的优点是放大不会失真,而 bitmap 需要为不同的分辨率准备很多套图标,而 SVG 则不需要,前面说了 SVG 要用 vector 表示,我们先来看看 vector 标签中属性的含义。

vector 的各个属性是什么意义?

<vector xmlns:android="http://schemas.android.com/apk/res/android"  //命名空间android:height="200dp"  //这个是图片的intrinsic高度android:width="200dp"   //这个是图片的intrinsic宽度android:viewportHeight="100"    //这个是为这个图片设置的纵坐标,表示将图片分为100等份,主要下面的pathData需要依赖这个坐标的划分android:viewportWidth="100"     //同上,只不过这个是横坐标, heigh,width的比例和viewportHeight,viewportWidth的比例必须保持一致,不然图形就会发生形变android:alpha="0.2"     //这个是整个图像的透明度,取值范围0到1><group      //这个标签中可以放入若干个<pathData/>标签,并给它们设置一些共同的属性android:name="group_name"   //这个name很有用,在设置objectAnimator的时候用来区分给那个部分施加动画android:pivotY="50"     //这个设置这个group的中心点的X坐标,取值范围为0到100,在做rotation时有用android:pivotX="50"     //这个设置这个group的中心点的Y坐标,取值范围为0到100,在做rotation时有用android:translateX="20" //将整个group在X轴方向平移多少像素android:translateY="30" //将整个group在Y轴方向平移多少像素android:rotation="90"   //将整个group以中心点左边旋转的角度,360为一圈android:scaleX="0.5"    //横坐标的缩放比例 , 取值1表示100%android:scaleY="0.3">   //纵坐标的缩放比例,取值0.5表示50%,取值1.5表示150%<pathData   //这个标签是重头戏,矢量图绘制的路径android:name="path_name"    //为这个path标记的名字,在使用objectAnimator的时候用来区分给哪个部分施加动画android:pathData="m 0,0 L50,0 L100,100 L0,100 z"    //这个是SVG的语法,下面讲android:fillColor="@color/red"  //定义填充图形的颜色,如果没有定义则不填充路径android:fillAlpha="1"       //定义填充图形的透明度,取值范围0到1android:strokeAlpha="0.5"   //定义路径的透明度,取值范围0到1android:strokeColor="#ff0000ff" //定义如何绘制路径,如果没有定义则不显示路径android:strokeWidth="20"    //线段的宽度android:strokeLineCap="butt|round|square"   //线的末端形状,butt严格到指定的坐标就截至,round是圆角,square是方形,到指定的坐标后还会再冒出一点来android:strokeLineJoin="round|bevel|miter"  //线的连接处形状,round是圆角的,bevel和miter貌似看不出来有什么区别....android:trimPathStart="0.5"    //顾名思义,从path开始的地方(0%)去除path,去除到指定的百分比位置,取值范围0到1android:trimPathEnd="0.5"      //顾名思义,从path结束的地方(100%的地方)去除path,去除到指定的百分比位置,取值范围0到1android:trimPathOffset="0.5"   //这个属性是和上面两个属性共同使用的,单独使用没有用,这个属性的意思是,在去除path的时候设置path原点的位置,按百分比设置,取值范围0到1/></group>
</vector>

下面就来讲解 path 标签,path 标签是用来创建 SVG 的,就像用指令控制一只画笔,path 标签所支持的指令有以下几种。

标签的绘图指令

M = moveto(M X, Y): 将画笔移动到指定的位置,但未发生绘制
L = lineto(L X, Y): 画直线到指定位置
H = horizontal(H X): 画水平线到指定X坐标
V = vertical lineto(V Y): 画垂直线到指定Y坐标
C = curveto(C X1,Y1,X1,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): 画弧线
Z = closepath(): 关闭路径,把前面的路径连起来

在使用以上指令时,需要注意:

  1. 坐标轴以(0,0)为中心,X 轴水平向右,Y 轴水平向下
  2. 所有指令大小写均可。大写绝对定位,参考全局坐标系;小写相对定位,参考父容器坐标系
  3. 指令和数据间的空格可以省略,可以用逗号隔开,也可以用空格
  4. 同一指令出现多次可以只用一个

SVG 的指令参数非常复杂,但是在 Android 中,不需要太多太复杂的 SVG 图形,所以我们先来掌握几个常用的指令,在以后的学习中,读者将会慢慢掌握更多的 SVG 绘制技巧和方法。

常用指令

  • M :类似 Android 绘图中 path 类的 moveTo 方法,即将画笔移动到某一点但并没有发生绘制动作,下面配合 L 进行讲解

  • L :画一条直线
 <pathData...省略一些代码android:pathData="M 20 50 L 80 50"/>


上面表示把画笔放在(20,50)位置,连直线到 80,50 点。
同时 L 后面还可以跟 H 或 V 指令来绘制水平、竖直线,后面的参数是 x 坐标(H 指令)或 y 坐标(V 指令),如下:

<pathData...省略一些代码android:pathData="M 20 50 L 80 50 V 80 H 20"/>


  • A :绘制一段弧线,且弧线不允许闭合,可以把弧线想象成椭圆的某一段,A 指令有以下 7 个参数:
  1. RX,RY 指所在椭圆的半轴大小

  2. XROTATION 指椭圆的 X 轴与水平方向的顺时针方向夹角,可以想象成一个水平的椭圆绕中心点顺时针旋转 XRORATION 的额角度

  3. FLAG1 只有俩个值,1 表示大角度弧线,0 表示小角度弧线

  4. FLAG2 只有俩个值,1 为顺时针,0 反之

  5. X,Y 为终点坐标

    看代码:

<pathData...省略一些代码android:pathData="M 50 50a 30 15 0 1 0 1 0"/>

再看图:

图一

上面表示把画笔放在(50,50)位置;30, 15 分别表示椭圆的 x,y 半轴大小;0 表示 x 轴不旋转;1 表示用大角度弧线绘制;0 表示顺时针:1,0 表示相对与以(50,50)为起始点的坐标轴的坐标,因为 a 是小写。

再看一段代码:

 <pathData...省略一些代码android:pathData="M 25 50a 25 25 0 1 0 50 0" />

再看图:

图二

可以看到这里显示了一个半圆,因为这里的 X,Y 轴大小相等。

再看一段代码:

 <pathData...省略一些代码android:pathData="M 25 50a 25 25 0 1 0 40 0" />

再看图:

图三

这里把终点 x 轴坐标改为 40,图中显示了圆的大部分。

看一段代码:

 <pathData...省略一些代码android:pathData="M 25 50a 25 25 0 0 0 40 0" />

再看图:

图四

这里把 FLAG1 改为 0,与图三相比,发现弧度变小了,因为用小弧度画。

看一段代码:

  <pathData...省略一些代码  android:pathData="M 25 50a 25 25 0 0 1 40 0" />

再看图:

图五

这里把 FLAG2 改为 1,与图四相比,图形翻转了,因为画的方向不一样了,把 A 指令的几个图结合看一下,就能弄懂 A 这个指令了。


关于贝塞尔指令的,这里就不过多介绍了,放出几个链接供大家学习:
贝塞尔曲线初探
SVG 讲解


VectorDrawable 和AnimatedVectorDrawable

Coogle 在 Android5.0X 中提供了俩个 API 来帮助支持 SVG:

  • VectorDrawable
  • AnimatedVectorDrawable 其中 VectorDrawable 用于创建 XML 文件的 SVG 图形即前面的 vector 标签,并结合 AnimatedVectorDrawable 来完成动画效果。

1、VectorDrawable

在 XML 中创建一个静态的 XMLSVG 图形,通常会形成如下的树形结构:

树形结构

path 是树形结构中最小的单位,而通过 Group 可以将不同的 path 进行组合,接下来我们使用 vector 标签创建 SVG 图形,代码如下:

<vector xmlns:android="http://schemas.android.com/apk/res/android"android:width="200dp"android:height="200dp"android:viewportWidth="100"android:viewportHeight="100"><groupandroid:name="line"><pathDataandroid:name="path1"android:strokeColor="@android:color/holo_green_dark"android:strokeWidth="5"android:strokeLineCap="round"android:pathData="M 20 20L 50 20 80 20"/><pathDataandroid:name="path2"android:strokeLineCap="round"android:strokeWidth="5"android:strokeColor="@android:color/holo_green_dark"android:pathData="M 20 80L 50 80 80 80"/></group>
</vector>

上面的代码画了俩条线,每条线由三个点控制,形成初始状态,下面立马通过 AnimatedVectorDrawable 来实现动画效果。

2、AnimatedVectorDrawable

AnimatedVectorDrawable 就是通过连接静态的 VectorDrawable 和动态的 objectAninmator 来为 VectorDrawable 提供动画效果,分几个步骤来使用:

    1. 在 XML 中通过 animated-vector 标签来声明对 AnimatedVectorDrawable 的使用,并指定它的 drawable 属性,target 标签中的 name 属性和 animation 属性
      代码如下:
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"android:drawable="@drawable/svg_path"><targetandroid:animation="@animator/anim_path1"android:name="path1"/><targetandroid:animation="@animator/anim_path2"android:name="path2"/>
</animated-vector>

android:drawable="@drawable/svg_path"指定了上面创建的 VectorDrawable 即画的俩条线;target 标签中的 name 指定了要作用动画的 path 或 Group 的 name, 即俩者的 name 要保持一致,这样系统才能找到要实现动画的元素;taret 标签中的 animation 指定了要作用的都动画。
在本例中,path1 的动画代码如下:

<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"android:duration="500"android:propertyName="pathData"android:valueType="pathType"android:valueFrom="M 20 20L 50 20 80 20"android:valueTo="M 20 20L 50 50 80 20"android:interpolator="@android:anim/bounce_interpolator">
</objectAnimator>

path2 的动画代码如下;

<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"android:duration="500"android:propertyName="pathData"android:valueType="pathType"android:valueFrom="M 20 80L 50 80 80 80"android:valueTo="M 20 80L 50 50 80 80"android:interpolator="@android:anim/bounce_interpolator">
</objectAnimator>

以上的俩个动画代码中都定义了一个 pathType 的属性动画,并指定了变换的初始值分别为:

//path1android:valueFrom="M 20 20L 50 20 80 20"
//path2android:valueFrom="M 20 80L 50 80 80 80"

结束值为:

//path1android:valueTo="M 20 20L 50 50 80 20"
//path2android:valueTo="M 20 80L 50 50 80 80"

这里要注意的是,SVG 的路径变换属性动画中,变换前后的节点数必须相同,这也是为什么前面需要使用三个点来绘制一条直线,因为后面需要中点进行动画变换。

  • 把 AnimatedVectorDrawable 的 XML 文件设置给 ImageView
 <ImageViewandroid:id="@+id/iv_path"android:src="@drawable/svg_path_anim".../>
  • 代码中启动 AnimatedVectorDrawable 动画
 ImageView ivPath;...ivPath = findViewById(R.id.iv_path);ivPath.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {Drawable drawable = ivPath.getDrawable();if(drawable instanceof Animatable){((Animatable)drawable).start();}}});

这样俩个 path 就实现了动画效果,如图:


在本文源码中还有俩个动画,就不贴代码了


) {
Drawable drawable = ivPath.getDrawable();
if(drawable instanceof Animatable){
((Animatable)drawable).start();
}
}
});

Java语言之动画的简单入门学习相关推荐

  1. 会java语言可以学seo吗_学习seo和java哪个更有前途?

    在网络搜索中我们发现这样一个问题,有人对于seo和java产生了更多的疑惑,任何一门技术,如果精通,都能为自己创造财富,创造价值,从这个角度来讲,seo也好,java也罢,没有哪个更好这一说法,只有哪 ...

  2. Java语言进阶:网络编程入门

    Java语言进阶:网络编程 网络编程入门 C/S C/S结构 :全称为Client/Server结构,是指客户端和服务器结构.常见程序有QQ.迅雷等软件. 特点: 客户端和服务器是分开的,需要下载客户 ...

  3. web开发的java语言步骤_java web开发入门一(servlet和jsp)基于eclispe

    servlet 用java语言开发动态资源网站的技术,在doGet方法中拼接显示html,在doPost方法中提交数据.类似于.net的ashx技术. servlet生成的class文件存放在tomc ...

  4. 【java开发系列】—— spring简单入门示例

    回顾 1 JDK安装 2 Struts2简单入门示例 前言 作为入门级的记录帖,没有过多的技术含量,简单的搭建配置框架而已.这次讲到spring,这个应该是SSH中的重量级框架,它主要包含两个内容:控 ...

  5. JS简单入门学习笔记一

    JS的HelloWorld 在页面中输出一个内容 document.write(); 向控制台输出一个内容 console.log(); /**1.JS中严格区分大小写*2.JS中每一条语句以分号结尾 ...

  6. MySQL数据库 sql语句的简单入门学习

    初步学习MySQL后的一些总结 MySQL简介 MySQL在过去由于性能高.成本低.可靠性好,已经成为最流行的开源数据库,因此被广泛地应用在Internet上的中小型网站中.随着MySQL的不断成熟, ...

  7. Linux简单入门学习

    文章目录 一.入门概述 1.我们为什么要学习Linux 2.Linux简介 3.Linux的发行版本 二.Linux安装 1.虚拟机安装(耗资源) 2.购买云服务器(推荐) 三. Linux文件系统 ...

  8. Java 官方性能测试工具 JMH 简单入门

    什么是 JMH JMH 是 Java Microbenchmark Harness 的缩写.中文意思大致是 "JAVA 微基准测试套件".首先先明白什么是"基准测试&qu ...

  9. Java语言制作动画

    为了使制作出来的满天星更加好看,采用随机数产生,对于产生的位置采用二维数组进行定义. 为了使动画动起来,通过改变横纵坐标的大小来实现(写这篇的目的是为了证明Java不是枯燥无味的) import ja ...

最新文章

  1. linux中readl()和writel()函数---用于读写寄存器
  2. 福利 | 放送AI华人库试用名额!专项代码找到领域专家
  3. 《Dreamweaver CS6完美网页制作——基础、实例与技巧从入门到精通》——1.3 常用网页设计软件...
  4. Redis进阶 - 因异常断电导致的Redis Cluster Fail故障处理
  5. Vue的Props属性概述
  6. java script创建对象_javascript笔记:深入分析javascript里对象的创建
  7. oracle脚本如何写,怎样写sql脚本
  8. Oracle 19c 新特性:自动化索引 Automatic indexing 实践
  9. springMVC ---- 异步调用
  10. Exchange 2010 Search Problem
  11. Win7系统不能拖动文件夹的问题怎么解决?
  12. SPSS、 Mplus下载安装包
  13. 证书-解决非对称加密的公钥信任问题
  14. MTK 6735/6739/6755/6763 android8.1 user版本打开root权限(adb root权限和 apk root权限)
  15. rapidminer java_在Java应用程序中集成RapidMiner
  16. Spark3.0核心调优参数小总结
  17. 微信小程序获取验证码
  18. CLOCs: Camera-LiDAR Object Candidates Fusion for 3D Object Detection(论文阅读笔记)
  19. 学习.NET ,提升.NET技能,这些公众号得关注
  20. DragonFly BSD 4.2发布

热门文章

  1. Fluent的入门、边界条件设置、求解器(Solver)设置、湍流模型(Models)设置、UDF、物理模型等
  2. 打通任督二脉,成为OI侠客的秘笈,在!这!里!
  3. 最大化参数 火车头_铁路大亨各火车头的性能参数
  4. Shell开发环境vim编辑器的配置文件vimrc的参数优化
  5. Lenovo Thinkpad T14电脑 Hackintosh 黑苹果efi引导文件
  6. ThinkpadT61安装Ubuntu启用Compiz无边框问题的解决
  7. 周杰伦《依然范特西》主打歌曲《千里之外》
  8. 驱动开发:内核特征码扫描PE代码段
  9. Javascript手把手教你做商品放大镜效果
  10. KMeans算法,采用肘部法则获取类簇中心个数K的值。