android矢量动画的使用&Path.java与pathData

背景

  • 位图:像素表示图像
  • 矢量图:数学方程表示图像 维基百科
  • 矢量动画:不断改变矢量图的属性(方程式)形成动画
  • 属性动画(ValueAnimator):在指定的时间内(Time),指定的变化速率下(TimeInterpolator),不断返回指定的(TypeEvaluator)中间值的"中间值生成器"

实现

  • Step1
创建'实现矢量动画需要的三个文件':矢量图、属性动画、助手类  
res/drawable/vector.xml  
res/animator/object_animator.xml  
res/drawable/animated_vector_drawable.xml  
  • Step2
    <ImageView
    android:src="@drawable/animated_vector_drawable"
    …/>
  • Step3
开始动画  
    mImageView.getDrawable().start();
 注1:助手类指 AnimatedVectorDrawable.java
     This class uses ObjectAnimator and AnimatorSet to animate the
  properties of a VectorDrawable to create an animated drawable.
 注2:Step1中的三个文件
     <!--矢量图 res/drawable/vector.xml -->
     <vector xmlns:android="http://schemas.android.com/apk/res/android"
             android:width="64dp"
             android:height="64dp"
             android:viewportWidth="64"
             android:viewportHeight="64">
         <group
             android:name="group_demo"
             android:pivotX="32"
             android:pivotY="32"
             >
             <path
                 android:name="path_demo"
                 android:pathData="M0,0 L32,32 L32,0 z"
                 android:strokeWidth="2"
                 android:strokeColor="#000000"/>
         </group>
     </vector>

     <!--属性动画 res/animator/object_animator.xml -->
     <objectAnimator
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:duration="1000"
            android:propertyName="rotation"
            android:valueFrom="0"
            android:valueTo="360"/>

     <!--助手类 res/drawable/animated_vector_drawable.xml -->
     <animated-vector
             xmlns:android="http://schemas.android.com/apk/res/android"
             //指定矢量图
             android:drawable="@drawable/vector">
             <target
                 //指定将要进行动画的group或path,该名称在vector.xml中定义
                 android:name="group_demo"
                 //指定动画类型
                 android:animation="@animator/object_animator"/>
     </animated-vector>
 注3:三个文件可合并写到一个文件,方式如下
     https://developer.android.google.cn/guide/topics/graphics/vector-drawable-resources

补充一:SVG与VectorDrawable

  • SVG
    可伸缩矢量图形(Scalable Vector Graphics),矢量图的一种表述形式,  
遵从XML语法,用文本格式的描述性语言来描述图像内容,文件后缀为".svg"
例如:
     test.svg
         <?xml version="1.0" standalone="no"?>
         <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
          "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
         <svg xmlns="http://www.w3.org/2000/svg" version="1.1">
           <circle cx="100" cy="50" r="40" stroke="black"
           stroke-width="2" fill="red" />
         </svg>
  • VectorDrawable
    安卓中使用矢量图,需将"xxx.svg"转换为上文中提到的res/drawable/vector.xml
的格式(即最终的VectorDrawable.java)
    SVG图片需要UI提供,也可以手动编写一些简单的vector.xml

补充二:VectorDrawable支持的元素、属性

  • VectorDrawable并没有支持所有的SVG规范,目前支持的元素、属性如下
        <vector>
            android:name
            //矢量图默认宽高
            android:width
            android:height
            //画布宽高
            android:viewportWidth
            android:viewportHeight
            android:tint
            android:tintMode
            android:autoMirrored
            android:alpha
        <group>
            android:name
            android:rotation
            //旋转、缩放一组path时的中心点,相对于画布宽高
            android:pivotX
            android:pivotY
            android:scaleX
            android:scaleY
            android:translateX
            android:translateY
        <path>
            android:name
            android:pathData
            android:fillColor
            android:strokeColor
            android:strokeWidth
            android:strokeAlpha
            android:fillAlpha
            android:trimPathStart
            android:trimPathEnd
            android:trimPathOffset
            android:strokeLineCap
            android:strokeLineJoin
            android:strokeMiterLimit
            android:fillType
        <clip-path>
            android:name
            android:pathData
   注1:放大缩小不失真是矢量图特性,矢量图需要有固有宽高的原因:
   android/frameworks/base/libs/hwui/VectorDrawable.h中提到  
   "VectorDrawables are drawn into bitmap caches first"

   注2:其余元素、属性的说明可查看
   https://developer.android.google.cn/reference/android/graphics/drawable/VectorDrawable  
   https://www.w3.org/TR/SVG11

补充三:path元素及pathData属性

  • 若把"元素path"看成Android中Path.java的对象(解析vector.xml构建对象时)
  • 那么"属性pathData"中的数据就代表了Path.java中相应的方法(构建对象时依据这些数据调用相应的方法)
例如:
      自定义View时,可以通过如下操作画出一个三角形
      public class XXX extends View {
          @Override
          protected void onDraw(Canvas canvas) {
              Path path = new Path();
              path.moveTo(0, 0);
              path.lineTo(32, 32);
              path.lineTo(32, 0);
              path.close();
              canvas.drawPath(path, getPaint());
          }
      }

      vector.xml中pathData配置如下亦代表三角形
      <vector >
          <path
              android:name="path_demo"
              android:pathData="M0,0 L32,32 L32,0 z"
            />
      </vector>

      pathData中数据“对应”Path.java中相应的方法
          M对应moveTo()
          L对应lineTo()
          z对应close()
   注1:pathData中M,L,Z...等的语法含义
         M:move to 落笔位置
         L:line to 划线
         Z:close 闭合
         A:elliptical arc 圆弧
    详情可参阅 https://www.w3.org/TR/SVG11/paths.html
   注2:附件VectorDemo有该例

补充四:path元素与Path.java

  • 补充三中不严谨的地方
    解析vector.xml时,<path>生成的是VFullPath对象而非Path.java的实例.但二者
  最终归宿都是/android/external/skia/src/core/SkPath.cpp
    从这点看,补充三中的类比虽不严谨,但不是很过分
  • "归宿都是SkPath"的依据
vector.xml中Path元素及pathData属性
    inflate()时
        android/frameworks/base/graphics/java/android/graphics/drawable/VectorDrawable.java
        nSetPathString(...)
        android/frameworks/base/core/jni/android_graphics_drawable_VectorDrawable.cpp
        setPathString(...)
        /android/frameworks/base/libs/hwui/VectorDrawable.h
        void setData(const Data& data)

    draw()时
        android/frameworks/base/graphics/java/android/graphics/drawable/VectorDrawable.java
        nDraw(...)
        android/frameworks/base/core/jni/android_graphics_drawable_VectorDrawable.cpp
        draw(...)
        android/frameworks/base/libs/hwui/VectorDrawable.cpp
        Tree::draw(...)
        Tree::drawStaging(...)
        Tree::updateBitmapCache(...)
        Group::draw(...)
        Path::draw(...)
        const SkPath& Path::getUpdatedPath() {
          VectorDrawableUtils::verbsToPath(&mSkPath, mProperties.getData());
          return mSkPath;
        }
Path.java及canvas.drawPath()
    构造Path时
        android/frameworks/base/graphics/java/android/graphics/Path.java
        public Path() {
              mNativePath = init1();
           }
        android/frameworks/base/core/jni/android/graphics/Path.cpp
        static jlong init1(JNIEnv* env, jobject clazz) {
            return reinterpret_cast<jlong>(new SkPath());
           }

    canvas.drawPath()时
        android/frameworks/base/graphics/java/android/graphics/Canvas.java
        public void drawPath(Path,Paint)
        android/frameworks/base/core/jni/android_graphics_Canvas.cpp
        static void drawPath(...) {
            const SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
            const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
            get_canvas(canvasHandle)->drawPath(*path, *paint);
        }

补充五:参考及Demo

  • 参考
  1.https://zh.wikipedia.org/wiki/%E7%9F%A2%E9%87%8F%E5%9B%BE%E5%BD%A2
  2.https://zh.wikipedia.org/wiki/%E5%8F%AF%E7%B8%AE%E6%94%BE%E5%90%91%E9%87%8F%E5%9C%96%E5%BD%A2
  3.https://www.w3.org/TR/SVG11/paths.html
  4.https://developer.android.google.cn/reference/android/graphics/drawable/VectorDrawable
  5.https://developer.android.google.cn/guide/topics/graphics/drawable-animation
  6.https://developer.android.google.cn/reference/android/graphics/drawable/AnimatedVectorDrawable#OneXML
  7.https://developer.android.google.cn/studio/write/vector-asset-studio
  8.https://www.androiddesignpatterns.com/2018/11/android-studio-svg-to-vector-cli.html
  9.属性动画机制不只是针对view来设计的allows you to animate almost anything,regardless of whether it draws to the screen or not.
    https://developer.android.google.cn/guide/topics/graphics/prop-animation
  10.文中开头提到的属性动画定义、矢量动画定义源自fyang,维基中没找到相关正式定义,百度中对矢量动画的定义有些"生硬"

猜你喜欢

转载自blog.csdn.net/yfbdxz/article/details/84592563