Android 5.X SVG矢量动画案例

案例展示


 


一.矢量动画的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>
t2_anim_path_line.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="-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);
}

(2)实用控件AnimatorSvgView请参照源码




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值