Android动画<第十一篇>:矢量图动画

在完成矢量图动画之前,必须了解矢量图在Android中的代码表示。Android Studio也可以制作自带的矢量图,或者导入svg格式的图片生成矢量图的代码。

我在Android Studio神器之Vector Asset这篇文章上已经做了简单的介绍。其中最为关键之处就是看懂矢量图的代码了。

(1)使用Vector Asset工具随意生成一个矢量图代码

矢量图的代码如下:


    

图像如下:

图片.png

以上是使用Vector Asset工具生成的矢量图和矢量图代码。

android:width:表示是矢量图的宽度;
android:height:表示矢量图的高度;
android:viewportWidth:表示将矢量图的宽分成N等分,这里是分成24等分;
android:viewportHeight:表示将矢量图的高分成N等分,这里是分成24等分;
:表示一个路径
android:pathData:表示路径上的数据

可用的命令如下:

名称 解释
M = moveto(M X,Y) 将画笔移动到指定的坐标位置
L = lineto(L X,Y) 画直线到指定的坐标位置
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,large-arc-flag,sweep-flag,X,Y) 弧线
Z = closepath() 关闭路径

以上所有命令均允许小写字母。大写的字母是基于原点的坐标系(偏移量),即绝对位置;小写字母是基于当前点坐标系(偏移量),即相对位置。

(2)自己绘制一个矢量图

按照上面说到的path命令,我们完全可以自己绘制一个简单的矢量图



    


这是一条直线,如图:

图片.png

然而,更加复杂的矢量图绘制难度很大。

我们完全可以利用绘图工具制作一个SVG图片,然后使用AS生成代码,也可以使用AS自带的Vector Asset工具制作SVG图片。

然后,复杂的SVG生成的代码必然也是更加的复杂,这样就必须加深SVG的了解了。

(3)必须了解的API:VectorDrawable

VectorDrawable 一般是以 为根标签定义的 XML 文件,标签下还可以有三种标签,分别是:,下面分别贴出这几种标签对应的属性。

定义这个矢量图
android:name 矢量图的名字
android:width 矢量图的内部(intrinsic)宽度,支持所有Android系统支持的尺寸,通常使用dp
android:height 矢量图的内部(intrinsic)高度
android:viewportWidth 矢量图视图的宽度,视图就是矢量图path路径数据所绘制的虚拟画布
android:viewportHeight 矢量图视图的高度
android:tint 矢量图的tint颜色。默认是没有tint颜色的
android:tintMode 矢量图tint颜色的Porter-Duff混合模式,默认值为src_in。(src_in,src_over,src_atop,add,screen,multiply)
android:autoMirrored 设置当系统为RTL(right-to-left)布局的时候,是否自动镜像该图片。比如阿拉伯语
android:alpha 该图片的透明度属性
设置路径做动画的关键属性的
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值来指定的
路径
android:name 定义该path的名字,这样在其他地方可以通过名字来引用这个路径
android:pathData 和SVG中d元素一样的路径信息。
android:fillColor 定义填充路径的颜色,如果没有定义则不填充路径
android:strokeColor 定义如何绘制路径边框,如果没有定义则不显示边框
android:strokeWidth 定义路径边框的粗细尺寸
android:strokeAlpha 定义路径边框的透明度
android:fillAlpha 定义填充路径颜色的透明度
android:trimPathStart 从路径起始位置截断路径的比率,取值范围从0到1;注意从一半到起始动画为from-0.5-to-0
android:trimPathEnd 从路径结束位置截断路径的比率,取值范围从0到1;注意从一半到结束动画为from-0.5-to-1.0
android:trimPathOffset 设置路径截取的范围,取值范围从0到1
android:strokeLineCap 设置路径线帽的形状,取值为 butt, round, square.
android:strokeLineJoin 设置路径交界处的连接方式,取值为 miter,round,bevel.
android:strokeMiterLimit 设置斜角的上限
定义当前绘制的剪切路径。注意,clip-path 只对当前的 group 和子 group 有效
android:name 定义clip-path的名字
android:pathData android:pathData的取值一样。

查看以上标签属性,我们发现标签其实是为动画存在的,它本身对矢量图的绘制关系不大,而这个动画叫做矢量图动画

那么,这个动画到底怎么实现呢?这里还需要了解一个接口:AnimatedVectorDrawable

(4)必须了解的API:AnimatedVectorDrawable

一般情况,表示一张矢量图不需要group标签,但是如果涉及到动画的话,可能就需要将一个或者多个路径进行分组。

AnimatedVectorDrawable通过ObjectAnimatorAnimatorSet对VectorDrawable的某个属性作一个矢量资源的动画。

AnimatedVectorDrawable就是矢量图动画,完成矢量图动画的要素有三,如下:

  • 一张矢量图,即以vector为标签的xml文件
  • 一个动画,objectAnimator或者AnimatorSet
  • AnimatedVectorDrawable,即以animated-vector为标签的xml文件
【举例】 实现左右箭头移动
41.gif

[第一步] 选择并自动生成一张矢量图

图片.png

生成的矢量图代码如下:


    

[第二步] 拆分矢量图的两个箭头

矢量图的路径一般以Z(z)为结尾,根据这个特性,将矢量图拆分,拆分后的代码如下:


    
        
    
    
        
    

[第三步] 准备好左右移动的动画

anim_left.xml




anim_right.xml




[第四步] animated-vector编写



    
    
    
    

其中,ic_swap_horiz_black_24dp为矢量图,animation为某动画,name和矢量图group标签的name对应。

[第五步] 设置src


这里需要注意的是,如果设置background动画是无效的,需要设置src才有动画效果。

[第六步] 在代码中执行动画

        case R.id.button:
            Drawable drawable = ((ImageView)findViewById(R.id.imageview)).getDrawable();
            if (drawable instanceof Animatable){
                ((Animatable)drawable).start();
            }
            break;

但是,我们发现,完成一个矢量图动画需要建立多个xml文件,为了解决这个问题,可以将矢量图所用到的xml合并。

合并之后的xml如下:




    

        
            
                
            
            
                
            
        

    

    
        
            
            
        
    
    

        
            
            
        

    

使用时,只要直接设置src并且执行动画即可。



    Drawable drawable = ((ImageView)findViewById(R.id.imageview)).getDrawable();
    if (drawable instanceof Animatable){
        ((Animatable)drawable).start();
    }
(5)Shape Shifter工具的基本使用

[第一步] 打开网页在线编辑

https://shapeshifter.design/

图片.png

[第二步] 文件导入

图片.png

在本地选择一个SVG格式的矢量图或者Vector Drawble,如下:

导入之后的图片如下:

图片.png

[第三步] 查看文件

图片.png

点击图中的path,可以查看路径代码

图片.png

我们可以对这个路径进行修改,比如修改颜色

图片.png

再看,图中的网状线条,其实就是给矢量图分成了24等份方便坐标表示,这里的pathData就是根据坐标绘制轨迹的。

[第四步] 设置动画时长

图片.png

默认时长为300ms,点击修改动画时长为1秒。

图片.png

[第五步] 考虑好自己想要完成的动画,比如让整个图片进行旋转

结合group标签的知识,group标签的功能有:设置锚点、旋转、缩放、平移。

所以这里的旋转动画可以使用group标签来完成。

[第六步] 添加group标签,并将path添加到group标签中

图片.png

点击图中的“+”,添加一个group图层

图片.png

并将path拖入group中

图片.png

[第七步] 为group添加旋转动画

图片.png

如图,修改group的初始值,将锚点调整到图片中央(图片分成了24等份)

图片.png

点击右上角的“闹钟”图标,添加“rotation”字段

图片.png

在时间线区域不自动生成一个绿色时间线,正好与字段“rotation”字段平行,选中绿色时间线,绿色时间线变为蓝色时间线,在屏幕右上角出现该时间线的属性:

图片.png

startTime:开始时间
endTime:结束时间
interpolator:动画插值器
fromValue:动画的初始旋转角度
toValue:动画的结束旋转角度

图片.png

将动画时间改为1000ms,任意选择动画插值器,将动画角度变化范围调整为0~360度。

[第八步] 播放动画

197.gif

[第九步] 导出矢量图动画文件

图片.png

最后,直接导出文件即可,点击Export-->Animated Vector Drawable。

生成的代码如下:


    
        
            
                
            
        
    
    
        
            
        
    

设置这个矢量图动画


最后再代码中播放动画

    Drawable drawable = ((ImageView)findViewById(R.id.imageview)).getDrawable();
    if (drawable instanceof Animatable){
        ((Animatable)drawable).start();
    }

演示效果如下:

198.gif
(6)Shape Shifter工具的Group属性

group标签除了旋转动画之外以,还有pivotX、pivotY、scaleX、scaleY、translateX、translateY等属性可以设置动态变化。

下面来一一举例:

[pivotX][pivotY]:设置锚点

上面图形的旋转动画的锚点的取值是(12,12),这个值从动画开始到动画结束没有发生变化,下面将锚点也随着时间动画变化呢?

图片.png
199.gif

[scaleX][scaleY]:动态缩放

图片.png
200.gif

[translateX][translateY]:动态平移

【略】

(7)Shape Shifter工具的Path属性

可被设置动画的字段有,pathData、fillColor、fillAlpha、strokeColor、strokeAlpha、strokeWidth、trimPathStart、trimPathEnd、trimPathOffset。

pathData: 和SVG中d元素一样的路径信息,可以将路径设置为动画开始和结束的取值;

【略】

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

201.gif

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

202.gif

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

203.gif

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

【略】

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

【略】

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

204.gif

这里需要注意的是,截断的是路径,而非填充色,上图的路径加上了边框,这个边框就是轨迹。

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

205.gif

这里需要注意的是,截断的是路径,而非填充色,上图的路径加上了边框,这个边框就是轨迹。

trimPathOffset: 设置起点路径和终点路径偏移量的范围,取值范围从0到1

206.gif

这里需要注意的是,截断的是路径,而非填充色,上图的路径加上了边框,这个边框就是轨迹。

(8)Shape Shifter工具自带Demo解析

[Demo:Play to Pause]

207.gif
图片.png

如图所示,完成这个动画需要两个字段的动画:rotation、pathData

图片.png

旋转动画的字段在group标签上,取值范围是0~90度。

图片.png

路径动画的字段在path标签上,去世范围是:从M 8 5 L 8 12 L 19 12 L 19 12 L 8 5 M 8 12 L 8 19 L 19 12 L 19 12 L 8 12到M 5 6 L 5 10 L 19 10 L 19 6 L 5 6 M 5 14 L 5 18 L 19 18 L 19 14 L 5 14。

在右上角有一个编辑按钮,点击进入编辑界面

图片.png

编辑界面顶部有几个按钮:
加号按钮的作用是添加一个点
剪刀按钮的作用是画一条直线分割一个路径,使路径一分为二
双向箭头按钮的作用是匹配动画前后的路径
双向箭头后面的按钮的作用是将选中的路径上的点反转,动画前后的点必须一一对应,路径上的点反转之后动画也会发生改变;
左箭头按钮的作用是将路径的点依次向上移动一个单位
右箭头按钮的作用是将路径的点依次向下移动一个单位

总之,为了将两个毫不相关的路径完成动画效果,必须将两个路径紧密的联系在一起,这个编辑界面可以将两个毫不相关的路径紧密的联系在一起,最终完成动画。

代码如下:


    
        
            
                
            
        
    
    
        
            
        
    
    
        
            
        
    

接下来的几个Demo将直接贴出动画效果和代码。

[Demo:Search to Close]

动画效果如下:

208.gif

代码如下:


    
        
            
                
            
            
            
        
    
    
        
            
                
                
            
        
    
    
        
            
        
    
    
        
            
        
    
    
        
            
                
                
            
        
    

[Demo:Morphing animals]

动画效果如下:

209.gif

代码如下:


    
        
            
        
    
    
        
            
                
                
                
                
                
                
            
        
    

[Demo:Visibility strike]

动画效果如下:

210.gif

代码如下:


    
        
            
            
            
        
    
    
        
            
        
    
    
        
            
        
    
    
        
            
        
    

[Demo:Heart break]

动画效果如下:

211.gif

代码如下:


    
        
            
                
            
            
                
            
            
            
            
                
                
            
        
    
    
        
            
        
    
    
        
            
        
    
    
        
            
        
    
    
        
            
        
    
    
        
            
        
    
    
        
            
        
    
    
        
            
                
                
            
        
    
    
        
            
        
    

[本章完...]

你可能感兴趣的:(Android动画<第十一篇>:矢量图动画)