案例展示
源码地址:
或
一.矢量动画的xml实现
矢量动画的组成
矢量动画展示到控件上需要三个文件:
1.<vector>:
适量图形文件 位置:drawable文件夹
作用:图形原始形态
2.<objectAnimator>:
属性动画文件 位置:animator文件夹
作用:动画展示方案
3.<animator-vector>:
粘合剂文件 位置:drawable文件夹
作用:把2动画方案作用于1适量图形
五个xml案例展示图片:(详述其中三个)
案例一:摆锤
1.<vector>文件:t1_svg_demo.xml
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="200dp"
android:height="200dp"
android:viewportHeight="200"
android:viewportWidth="200">
<group
android:name="line1"
android:pivotX="100"
android:pivotY="0"
android:rotation="0">
<path
android:pathData="M 100,0 L 100,100"
android:strokeColor="@color/colorPrimaryDark"
android:strokeWidth="20"
android:strokeLineCap="round"/>
<group
android:name="test1"
android:pivotX="100"
android:pivotY="100"
android:rotation="0">
<path
android:pathData="M 50,100
A 50,50,0,1,1,150,100"
android:strokeColor="@color/colorAccent"
android:strokeWidth="20"
android:strokeLineCap="round"/>
</group>
</group>
</vector>
- <vector>
width,height属性代表实际展示宽度,
viewportWidth,viewportHeight属性代表把宽高等比例分成多少份
- <group>一个树形结构的图形组
内部包含<group>和<path>节点
pivotX,pivotY代表<group>中心点(属性动画如果是rotation,这个中心点为旋转的中心点,内部的group跟随外部的group移动(基于指定中心点))
rotation代表图形组起始角度
- <path>具体图形
strokeColor:空心图形
fillColor:实心图形
stokeLineCap:倒角
pathData:参数为具体绘图命令代码
- pathData
举例(android:pathData="M 50,100 A 50,50,0,1,1,150,100)
(M X,Y):将画笔移动到指定的坐标位置,但未发生绘制
(A RX,RY,//半径
XROTATION,//指椭圆的X轴于水平方向顺时针方向夹角)
FLAG1,//1表示大弧度,0表示小弧度
FLAG2,//1表示顺时针,0表示逆时针
X,Y)://A大写时为绝对坐标,a小写时为相对坐标 画各种情况下的圆弧
(L X,Y):画直线到指定的坐标位置
2.<objectAnimator>属性动画文件:t1_anim_path.xml (作用于锤)
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:propertyName="rotation"
android:valueFrom="100"
android:valueTo="260"
android:repeatMode="reverse"
android:repeatCount="60"
android:interpolator="@android:anim/accelerate_decelerate_interpolator">
</objectAnimator>
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:propertyName="rotation"
android:valueFrom="-10"
android:valueTo="10"
android:repeatMode="reverse"
android:repeatCount="60"
android:interpolator="@android:anim/accelerate_decelerate_interpolator">
</objectAnimator>
- propertyName
为rotation时,valueFrom和valueTo为起始角度,旋转的圆心为作用图形的<group>的中心点pivotX,pivotY。
- interpolator
插值器,动画播放的状态
3.<animator_vector>粘合剂文件:t1_anim_svg_demo.xml (作为控件的资源文件)
<?xml version="1.0" encoding="utf-8"?>
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/t1_svg_demo">
<target
android:animation="@animator/t1_anim_path"
android:name="test1" />
<target
android:animation="@animator/t1_anim_path_line"
android:name="line1" />
</animated-vector>
- <animated_vector>drawable属性指定对应的矢量图形
- <target>把动画作用于指定名字的<group>或<path>
4.控件引用对应的粘合剂文件:
<ImageView android:id="@+id/ivLoading" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/t1_anim_svg_demo" />
5.播放动画,停止动画
ivPendulum1 = (ImageView) findViewById(R.id.ivPendulum1); restart(ivPendulum1.getDrawable());
private void restart(Drawable drawable) { if (drawable instanceof Animatable) { Animatable animatable = (Animatable) drawable; if (animatable.isRunning()) animatable.stop(); animatable.start(); } }
案例二:返回按钮
1.<vector>文件:t4_svg_back.xml
<?xml version="1.0" encoding="utf-8"?> <vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="48dp" android:height="48dp" android:viewportHeight="100" android:viewportWidth="100"> <group android:name="back" android:pivotX="50" android:pivotY="50" android:rotation="0"> <path android:name="path1" android:pathData="M 30,30 L 70,30" android:strokeColor="@color/colorPrimaryDark" android:strokeLineCap="round" android:strokeWidth="5" /> <path android:name="path2" android:pathData="M 30,50 L 70,50" android:strokeColor="@color/colorPrimaryDark" android:strokeLineCap="round" android:strokeWidth="5" /> <path android:name="path3" android:pathData="M 30,70 L 70,70" android:strokeColor="@color/colorPrimaryDark" android:strokeLineCap="round" android:strokeWidth="5" /> </group> </vector>
2.<objectAnimator>属性动画文件:t4_anim_path1.xml , t4_anim_path3.xml , t4_anim_back.xml
<?xml version="1.0" encoding="utf-8"?> <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" android:duration="500" android:propertyName="pathData" android:valueFrom="M 30,30 L 70,30" android:valueTo="M 50,30 L 70,50" android:valueType="pathType"> </objectAnimator>
<?xml version="1.0" encoding="utf-8"?> <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" android:duration="500" android:propertyName="pathData" android:valueFrom="M 30,70 L 70,70" android:valueTo="M 50,70 L 70,50" android:valueType="pathType"> </objectAnimator>
<?xml version="1.0" encoding="utf-8"?> <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" android:duration="500" android:interpolator="@android:anim/accelerate_decelerate_interpolator" android:propertyName="rotation" android:valueFrom="0" android:valueTo="180"> </objectAnimator>
- propertyName="pathData"
此时valueType要设置成pathType
valueFrom和valueTo参照<path>标签的命令
3.<animator_vector>粘合剂文件:t4_anim_svg_back.xml (作为控件的资源文件)
<?xml version="1.0" encoding="utf-8"?> <animated-vector xmlns:android="http://schemas.android.com/apk/res/android" android:drawable="@drawable/t4_svg_back"> <target android:animation="@animator/t4_anim_path1" android:name="path1"/> <target android:animation="@animator/t4_anim_path3" android:name="path3"/> <target android:animation="@animator/t4_anim_back" android:name="back"/> </animated-vector>
4.5.同案例一
案例三:太阳系
1.<vector>文件:t3_svg_target.xml
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="400dp"
android:height="400dp"
android:viewportHeight="400"
android:viewportWidth="400">
<group>
<path android:fillColor="@color/sun"
android:pathData="M 190,200
a 10,10,0,1,0,20,0
a 10,10,0,1,0,-20,0" />
<group android:name="mercury"
android:pivotX="200"
android:pivotY="200"
android:rotation="0">
<path android:strokeColor="@color/path"
android:pathData="M 240,200
a 20,20,0,1,0,-80,0
a 20,20,0,1,0,80,0"/>
<path android:fillColor="@color/mercury"
android:pathData="M 236,200
a 4,4,0,1,0,8,0
a 4,4,0,1,0,-8,0"/>
</group>
<group android:name="venus"
android:pivotX="200"
android:pivotY="200"
android:rotation="0">
<path android:strokeColor="@color/path"
android:pathData="M 270,200
a 20,20,0,1,0,-140,0
a 20,20,0,1,0,140,0"/>
<path android:fillColor="@color/venus"
android:pathData="M 266,200
a 4,4,0,1,0,8,0
a 4,4,0,1,0,-8,0"/>
</group>
<group
android:name="earth"
android:pivotX="200"
android:pivotY="200"
android:rotation="0" >
<path android:strokeColor="@color/path"
android:pathData="M 300,200
a 20,20,0,1,0,-200,0
a 20,20,0,1,0,200,0"/>
<path android:fillColor="@color/earth"
android:pathData="M 295,200
a 5,5,0,1,0,10,0
a 5,5,0,1,0,-10,0"/>
<group android:name="moon"
android:pivotX="300"
android:pivotY="200"
android:rotation="0">
<path android:strokeColor="@color/path"
android:pathData="M 320,200
a 2,2,0,1,0,-40,0
a 2,2,0,1,0,40,0"/>
<path android:fillColor="@color/moon"
android:pathData="M 318,200
a 2,2,0,1,0,4,0
a 2,2,0,1,0,-4,0"/>
</group>
</group>
<group android:name="mars"
android:pivotX="200"
android:pivotY="200"
android:rotation="0">
<path android:strokeColor="@color/path"
android:pathData="M 360,200
a 20,20,0,1,0,-320,0
a 20,20,0,1,0,320,0"/>
<path android:fillColor="@color/mars"
android:pathData="M 356,200
a 4,4,0,1,0,8,0
a 4,4,0,1,0,-8,0"/>
</group>
</group>
</vector>
- pathData用法扩展(画整圆)
举例:android:pathData="M 356,200
a 4,4,0,1,0,8,0
a 4,4,0,1,0,-8,0 "
a小写时为相对坐标
通过(8,0)到底第一点后,在基于第一点通过(-8,0)到底第二点(也就是起始点)从而画出整圆
2.<objectAnimator>属性动画文件:t3_anim_mercury.xml , t3_anim_venus.xml , t3_anim_earth.xml,t3_anim_moon.xml,t3_anim_mars.xml
duration设置的是按比例缩小的公转周期
插值器采用的是线性插值器
<?xml version="1.0" encoding="utf-8"?> <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" android:duration="8770" android:propertyName="rotation" android:valueFrom="0" android:valueTo="360" android:repeatMode="restart" android:repeatCount="60" android:interpolator="@android:anim/linear_interpolator"/>
<?xml version="1.0" encoding="utf-8"?> <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" android:duration="22470" android:propertyName="rotation" android:valueFrom="0" android:valueTo="360" android:repeatMode="restart" android:repeatCount="60" android:interpolator="@android:anim/linear_interpolator"/>
<?xml version="1.0" encoding="utf-8"?> <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" android:duration="36900" android:propertyName="rotation" android:valueFrom="0" android:valueTo="360" android:repeatMode="restart" android:repeatCount="60" android:interpolator="@android:anim/linear_interpolator"/>
<?xml version="1.0" encoding="utf-8"?> <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" android:duration="2732" android:propertyName="rotation" android:valueFrom="0" android:valueTo="360" android:repeatMode="restart" android:repeatCount="3650" android:interpolator="@android:anim/linear_interpolator"/>
<?xml version="1.0" encoding="utf-8"?> <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" android:duration="68700" android:propertyName="rotation" android:valueFrom="0" android:valueTo="360" android:repeatMode="restart" android:repeatCount="60" android:interpolator="@android:anim/linear_interpolator"/>
3.<animator_vector>粘合剂文件:t3_anim_svg_target.xml (作为控件的资源文件)
<?xml version="1.0" encoding="utf-8"?> <animated-vector xmlns:android="http://schemas.android.com/apk/res/android" android:drawable="@drawable/t3_svg_target"> <target android:animation="@animator/t3_anim_mercury" android:name="mercury"/> <target android:animation="@animator/t3_anim_venus" android:name="venus"/> <target android:animation="@animator/t3_anim_earth" android:name="earth"/> <target android:animation="@animator/t3_anim_mars" android:name="mars"/> <target android:animation="@animator/t3_anim_moon" android:name="moon"/> </animated-vector>
4.5.同案例一
二.矢量动画的Java实现
1.通过SVG在线编辑器 自动生成路径
2.SVG在线编辑器使用方法:
(1)绘制基础图形
(2)Object->Convert to Path
(3)通过参数调整背景及图形
(4)View->Source 生成pathData字符串源码(选中的即为需要的路径数据)
3.svg for java 最简单实现步骤:
(1)SvgView控件实现
private void init() {
// 1.通过路径字符串生成路径Path
mPath = ExposedPathParser.createPathFromPathData(mPathData);
// 2.计算路径长度
PathMeasure pm = new PathMeasure(mPath, true);
mLength = pm.getLength();
// 3.设置开始时间
mStartTime = System.currentTimeMillis();
// 4.初始化Paint
mPaint = new Paint();
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(Color.RED);
mPaint.setAntiAlias(true);
mPaint.setStrokeWidth(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1, getResources().getDisplayMetrics()));
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mPath == null) return;
// 1.计算 绘制时间区间
long t = System.currentTimeMillis() - mStartTime;
// 2.根据 时间 计算当前相位
float phase = constrain(0, 1, t * 1f / mTraceTime);
// 3.根据 相位和总长 计算刷新的距离
float distance = INTERPOLATOR.getInterpolation(phase) * mLength;
// 4.设置 Paint 本次绘制效果
mPaint.setPathEffect(new DashPathEffect(new float[]{distance, mLength}, 0));
// 5.绘图
canvas.drawPath(mPath, mPaint);
// 6.判断是否完成,如果没有,继续刷新
if (t < mTraceTime)
ViewCompat.postInvalidateOnAnimation(this);
}