PathMeasure 轨迹动画神器

轨迹动画一般利用SVG来实现,或者使用属性动画,自定义估计值,根据两点之间的线性关系式计算坐标(复杂)
但是使用PathMeasure来进行绘制轨迹动画,so easy。

先看效果:

效果分析:
1、圆圈变成圆弧
2、圆弧不断的变小

实现
方式1:通过不断改变绘制圆弧的开始角度。 这个方法肯定是最先想到的方法,
因为api
drawArc(@NonNull RectF oval, float startAngle, float sweepAngle, boolean useCenter,
@NonNull Paint paint)用的最多

方式2:利用PathMeasure,不断截取路径。截取不断变小的圆弧,然后把截取到的path绘制出来就可以。

比较:两种方式相比PathMeasure并没有多大的优势,但是绘制圆弧可以使用 drawArc 来改变角度实现类似轨迹运动的效果,但是,如果path、不是一个圆形,问题就复杂了,PathMeasure的强大也就体现出来了。

学习PathMeasure的使用
查看源码,发现只有100多行,其实也就几个方法。但是确实非常流弊
1、setPath(Path path, boolean forceClosed)
要对path进行操作,首先需要设置一个path,也可以在构造函数中绑定,关键在第二个参数,是否关闭,如果是true,那么会给参数path,强制首尾闭合,因为path可能是一个非闭合的路径。

2、getLength
得到path路径的长度,很有用。

3、getPosTan(float distance, float pos[], float tan[])
得到distance,位置的点的坐标,和在个点与path进行切线的正切,分别放在pos[] 和tan[]中。
例如,distance==length/2,就是得到这条path路径的中间点,的坐标和正切

4、getMatrix(float distance, Matrix matrix, int flags)
这个就厉害了,直接返回得到矩阵,这个矩阵就包含了这个点移动的位置,和倾斜的角度,可以直接在这个点绘制
一个图片,利用这个matrix

5、getSegment(float startD, float stopD, Path dst, boolean startWithMoveTo)
从开始的距离,到结束的距离,截取一段path放在dst中,
startWithMoveTo 如果为true,这个dst会从截取点开始
如果为false,这个dst会从(0,0)作为开始点

使用PathMeasure来进行分析

接着圆弧动画完了,就是手柄的动画。把属性动画的0到1拆分,0到0.8,完成画的轨迹动画,0.8到1完成手柄的动画,手柄就是一条直线,再使用PathMeasure有点大炮打蚊子,直接不断改变手柄直线的结束点就可以了。

下面是具体的代码实现:

package com.lmj.searchview;import android.animation.Animator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathMeasure;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;/*** Created by limengjie* on 2017/5/25.14:37*/public class SearchView extends View {private Matrix mMatrix;private Paint mPaint;private Path mPath;private int mCircleX;private int mCircleY;private int mRadius = 50;//圆的半径private PathMeasure mPathMeasure;private float circleLength;private float startD;private float endD;private ValueAnimator mvalueAnimator_rotate;private ValueAnimator mvalueAnimator_path;private String Tag = "SearchView";private Path dstCircle;private int lineD = 0;private static final int Status_Normal = 1;//正常状态private static final int Status_PathAni = 2;//正在进行轨迹动画private static final int Status_RotateAni = 3;//正在旋转动画private int Status = Status_Normal;private int rotateNum;public SearchView(Context context) {this(context, null);init();}public SearchView(Context context, @Nullable AttributeSet attrs) {super(context, attrs);init();}private void init() {mMatrix = new Matrix();mPaint = new Paint();mPath = new Path();mPaint.setStyle(Paint.Style.STROKE);mPaint.setColor(Color.GREEN);mPaint.setStrokeWidth(2);mPaint.setAntiAlias(true);mPathMeasure = new PathMeasure();dstCircle = new Path();}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);mPath.reset();mCircleX = getWidth() / 2;mCircleY = getHeight() / 2;switch (Status) {case Status_Normal:drawNormal(canvas);break;case Status_PathAni:drawPathAni(canvas);break;case Status_RotateAni:drawRotateAni(canvas);break;}}private void drawNormal(Canvas canvas) {mPaint.setColor(Color.GREEN);mPath.addCircle(mCircleX, mCircleY, mRadius, Path.Direction.CW);canvas.save();canvas.drawPath(mPath, mPaint);canvas.rotate(45, mCircleX, mCircleY);canvas.drawLine(mCircleX + mRadius, mCircleY, mCircleX + mRadius * 2, mCircleY, mPaint);canvas.restore();}private void drawPathAni(Canvas canvas) {mPath.addCircle(mCircleX, mCircleY, mRadius, Path.Direction.CW);canvas.save();canvas.rotate(45, mCircleX, mCircleY);mPathMeasure.setPath(mPath, false);circleLength = mPathMeasure.getLength();endD = circleLength;dstCircle.reset();Log.i(Tag, "sd:" + startD + ",ed:" + endD);mPathMeasure.getSegment(startD, endD, dstCircle, true);
//        mPaint.setColor(Color.RED);canvas.drawPath(dstCircle, mPaint);//圆的动画canvas.drawLine(mCircleX + mRadius, mCircleY, mCircleX + mRadius * 2 - lineD, mCircleY, mPaint);canvas.restore();}private void drawRotateAni(Canvas canvas) {mPath.addCircle(mCircleX, mCircleY, mRadius, Path.Direction.CW);canvas.save();canvas.rotate(45+rotateNum, mCircleX, mCircleY);mPathMeasure.setPath(mPath, false);circleLength = mPathMeasure.getLength();dstCircle.reset();mPathMeasure.getSegment(0, 20, dstCircle, true);
//        mPaint.setColor(Color.RED);canvas.drawPath(dstCircle, mPaint);//圆的动画}private void startPathAni() {
//        if(null==mvalueAnimator){if (null != mvalueAnimator_path) {mvalueAnimator_path.cancel();}lineD = 0;mvalueAnimator_path = ValueAnimator.ofFloat(0, 1);mvalueAnimator_path.setDuration(1500);mvalueAnimator_path.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {//0-0.8,分割圆,0.8到1 分割手柄float fraction = animation.getAnimatedFraction();if (fraction <= 0.8f) {startD = circleLength * fraction / 0.7f;} else {startD = circleLength;lineD = (int) ((fraction - 0.8) * mRadius / 0.2f);}if(fraction==1f){lineD = mRadius;Status = Status_RotateAni;postInvalidate();startRotateAni();}postInvalidate();}});mvalueAnimator_path.start();
//        }}public void startRotateAni(){if (null != mvalueAnimator_rotate) {mvalueAnimator_rotate.cancel();}mvalueAnimator_rotate = ValueAnimator.ofInt(0, 360,0);mvalueAnimator_rotate.setDuration(3000);mvalueAnimator_rotate.setRepeatMode(ValueAnimator.RESTART);mvalueAnimator_rotate.setRepeatCount(-1);mvalueAnimator_rotate.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {rotateNum = (int) animation.getAnimatedValue();postInvalidate();}});mvalueAnimator_rotate.start();}public void startSearch() {Status = Status_PathAni;startPathAni();postInvalidate();}public void stopSearch() {Status = Status_Normal;if (null != mvalueAnimator_rotate) {mvalueAnimator_rotate.cancel();}if (null != mvalueAnimator_path) {mvalueAnimator_path.cancel();}postInvalidate();}}

总结,
只要我们有一个已知的path,就可以通过PathMeasure,来截取轨迹,根据距离来获取某个点的坐标和正切,所以有了path,轨迹动画就so easy了。

源码下载

————————————————
版权声明:本文为CSDN博主「按劳分配」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/lmj121212/article/details/72736316

PathMeasure 轨迹动画神器 路径动画相关推荐

  1. Threejs开发之移动动画、旋转动画、缩放动画和路径动画

    以下代码 示例了threejs的移动动画.旋转动画.缩放动画和路径动画 注意:引入three.js三维引擎的路径需要根据 自己的情况修改相应的路径,本示例采用引用外部模块的方式. 以下为完整代码: & ...

  2. SVG—初识4之描边动画和路径动画

    SVG-初识4 SVG描边动画 stroke-dashoffset DrawSVGPlugin插件 路径动画 CSS写路径动画 SVG写路径动画 使用 GreenSock 来实现自行车沿着路径运动的路 ...

  3. WPF 动画之路径动画DoubleAnimationUsingPath

    虽然一直在做WPF开发, 但是实际项目中很少用到动画,今天突然想要撸一撸,  于是便有了下面的代码 <Window.Resources><PathGeometry x:Key=&qu ...

  4. android svg路径动画,Svg 路径动画实现旋转进度条

    尝试使的候通现端数是制这.效合应近环大过这业据用 Svg 实现简易的动画效果.有关 Svg 的具体知识点不在此文赘述,仅就所举示例的需求点阐述实在重说道.础过学开概码数项遍间里哦行览屏屏定处..容标中 ...

  5. 三维场景中常用的路径动画

    三维场景中常用的路径动画 前言 在三维场景中,除了用逼近真实的模型代表现实中的设备.标识物外,通常还会使用一些动画来表示模型在现实中一些行为和作用.常见的动画比如路径动画.旋转动画.发光动画.流动动画 ...

  6. osgEarth AnimationPath路径动画

    目录 飞机飞行实例 路径动画暂停 路径动画继续 osgEarth 视角跟踪飞机飞行 相机跟踪飞机移动 视角移动到特定地点 osg::AnimationPath 封装了一个随时间变化的过程,可以用来更新 ...

  7. 咸鱼Maya笔记—路径动画

    咸鱼Maya笔记-路径动画 创建路径动画 动画的创建方式有很多种,路径动画是其中的一种,Key关键帧的方式并不适用于所有的情况,有些特定的情况下我们就需要用到路径动画,它的创建方法如下 创建路径动画 ...

  8. android文字轨迹动画,文字转化为路径动画 TextPathView

    介绍 大家新年快乐,TextPathView是一个把文字转化为路径动画然后展现出来的自定义控件.效果如上图: 使用 主要的使用流程就是输入文字,然后设置一些动画的属性,还有画笔特效,最后启动就行了. ...

  9. 【Python应用】Python+Kepler.gl轻松制作酷炫路径动画

    文章来源于Python大数据分析,作者费弗里 本文示例代码.数据已上传至Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 ...

最新文章

  1. python多线程编程(2): 使用互斥锁同步线程
  2. 全球及中国自卸车行业深度分析与“十四五”发展战略规划研究报告2022-2028年版
  3. python求最大连续子数组
  4. 如何突破Windows环境限制打开“命令提示符”
  5. 深入理解JVM虚拟机读书笔记【第十三章】线程安全与锁优化
  6. ai中如何插入签名_如何在PDF文档中插入文本框?
  7. 史上最烂 spring aop 原理分析
  8. halcon程序安装破解与VC6.0结合
  9. 如果你的天猫魔盒不能看了
  10. 如何完整的修改一个数据库的名称
  11. SpringBoot2.x 监听器详解
  12. 解决WiFi网速慢和防蹭笔记
  13. 应用深度学习function-loss-optimization 2020.8.24
  14. 使用anaconda 要用conda 方式更新各个软件,不要用pip
  15. windows驱动开发5:WDK Demo:avstream avscamera
  16. 使用vue+echarts快速进行全国地图与各省市地图联动(下钻地图), 引入省份js文件
  17. 【计算机视觉】INRIA 行人数据集 (INRIA Person Dataset)
  18. D-LINK DI-504路由器TELNET方法及命令运行查看方式
  19. 格斗手游服务器语言,steam上的油腻师姐移植手机,这是部有点“色”的横版格斗 新游酱每日游戏推荐...
  20. esxi license过期_Vcenter 和ESXi License过期解决办法

热门文章

  1. Oracle sql大于和小于号的转义写法
  2. margin外边距合并问题以及解决方式
  3. C语言求两个正整数的最小公倍数
  4. 思科新版ccna认证网工一定要知道的PIM技术概述
  5. Memcached分布式算法
  6. 最有效率的⽅法计算2乘以8
  7. 网易云歌单歌曲实时拉取
  8. SLC NAND FLASH的物理结构
  9. web 页面 常用分辨率(PC 移动端)
  10. 两中方式找出Excel中相同和不同的数据