1. package com.loaderman.customviewdemo;
  2.  
  3. import android.animation.ValueAnimator;
  4. import android.content.Context;
  5. import android.graphics.*;
  6. import android.util.AttributeSet;
  7. import android.view.View;
  8.  
  9. public class GetSegmentView extends View {
  10.  
  11. private Path mCirclePath, mDstPath;
  12. private Paint mPaint;
  13. private PathMeasure mPathMeasure;
  14. private Float mCurAnimValue;
  15.  
  16. public GetSegmentView(Context context, AttributeSet attrs) {
  17. super(context, attrs);
  18. setLayerType(LAYER_TYPE_SOFTWARE, null);
  19.  
  20. mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
  21. mPaint.setStyle(Paint.Style.STROKE);
  22. mPaint.setStrokeWidth(4);
  23. mPaint.setColor(Color.BLACK);
  24.  
  25. mDstPath = new Path();
  26. mCirclePath = new Path();
  27. mCirclePath.addCircle(100, 100, 50, Path.Direction.CW);
  28.  
  29. mPathMeasure = new PathMeasure(mCirclePath, true);
  30.  
  31. ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
  32. animator.setRepeatCount(ValueAnimator.INFINITE);
  33. animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
  34. public void onAnimationUpdate(ValueAnimator animation) {
  35. mCurAnimValue = (Float) animation.getAnimatedValue();
  36. invalidate();
  37. }
  38. });
  39. animator.setDuration(2000);
  40. animator.start();
  41. }
  42.  
  43. @Override
  44. protected void onDraw(Canvas canvas) {
  45. super.onDraw(canvas);
  46. float length = mPathMeasure.getLength();
  47. float stop = length * mCurAnimValue;
  48. float start = (float) (stop - ((0.5 - Math.abs(mCurAnimValue - 0.5)) * length));
  49. mDstPath.reset();
  50. canvas.drawColor(Color.WHITE);
  51. mPathMeasure.getSegment(start, stop, mDstPath, true);//用于截取整个path中某个片段,通过参数startD和stopD来控制截取的长度,并将截取后的path保存到参数dst中,最后一个参数表示起始点是否使用moveTo将路径的新起始点移到结果path的起始点中,通常设置为true
  52.  
  53. // mPathMeasure.getSegment(0, stop, mDstPath, true);
  54. canvas.drawPath(mDstPath, mPaint);
  55. }
  56. }
  1. package com.loaderman.customviewdemo;
  2.  
  3. import android.animation.ValueAnimator;
  4. import android.content.Context;
  5. import android.graphics.Canvas;
  6. import android.graphics.Color;
  7. import android.graphics.Paint;
  8. import android.graphics.Path;
  9. import android.graphics.PathMeasure;
  10. import android.util.AttributeSet;
  11. import android.view.View;
  12.  
  13. public class AliPayView extends View {
  14. private Path mCirclePath, mDstPath;
  15. private Paint mPaint;
  16. private PathMeasure mPathMeasure;
  17. private Float mCurAnimValue;
  18. private int mCentX = 100;
  19. private int mCentY = 100;
  20. private int mRadius = 50;
  21.  
  22. public AliPayView(Context context, AttributeSet attrs) {
  23. super(context, attrs);
  24. setLayerType(LAYER_TYPE_SOFTWARE, null);
  25.  
  26. mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
  27. mPaint.setStyle(Paint.Style.STROKE);
  28. mPaint.setStrokeWidth(4);
  29. mPaint.setColor(Color.BLACK);
  30.  
  31. mDstPath = new Path();
  32. mCirclePath = new Path();
  33.  
  34. mCirclePath.addCircle(mCentX, mCentY, mRadius, Path.Direction.CW);
  35.  
  36. mCirclePath.moveTo(mCentX - mRadius / 2, mCentY);
  37. mCirclePath.lineTo(mCentX, mCentY + mRadius / 2);
  38. mCirclePath.lineTo(mCentX + mRadius / 2, mCentY - mRadius / 3);
  39.  
  40. mPathMeasure = new PathMeasure(mCirclePath, false);
  41.  
  42. ValueAnimator animator = ValueAnimator.ofFloat(0, 2);
  43. animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
  44. public void onAnimationUpdate(ValueAnimator animation) {
  45. mCurAnimValue = (Float) animation.getAnimatedValue();
  46. invalidate();
  47. }
  48. });
  49. animator.setDuration(4000);
  50. animator.start();
  51. }
  52.  
  53. boolean mNext = false;
  54.  
  55. @Override
  56. protected void onDraw(Canvas canvas) {
  57. super.onDraw(canvas);
  58. canvas.drawColor(Color.WHITE);
  59.  
  60. if (mCurAnimValue < 1) {
  61. float stop = mPathMeasure.getLength() * mCurAnimValue;
  62. mPathMeasure.getSegment(0, stop, mDstPath, true);
  63. } else {
  64. if (!mNext) {
  65. mNext = true;
  66. mPathMeasure.getSegment(0, mPathMeasure.getLength(), mDstPath, true);
  67. mPathMeasure.nextContour(); //跳转到下一条曲线函数
  68. }
  69. float stop = mPathMeasure.getLength() * (mCurAnimValue - 1);
  70. mPathMeasure.getSegment(0, stop, mDstPath, true);
  71. }
  72. canvas.drawPath(mDstPath, mPaint);
  73. }
  74. }
  1. package com.loaderman.customviewdemo;
  2.  
  3. import android.animation.ValueAnimator;
  4. import android.content.Context;
  5. import android.graphics.Bitmap;
  6. import android.graphics.BitmapFactory;
  7. import android.graphics.Canvas;
  8. import android.graphics.Color;
  9. import android.graphics.Matrix;
  10. import android.graphics.Paint;
  11. import android.graphics.Path;
  12. import android.graphics.PathMeasure;
  13. import android.util.AttributeSet;
  14. import android.view.View;
  15.  
  16. public class GetPosTanView extends View {
  17. private Path mCirclePath, mDstPath;
  18. private Paint mPaint;
  19. private PathMeasure mPathMeasure;
  20. private Float mCurAnimValue;
  21. private Bitmap mArrawBmp;
  22. private float[] pos = new float[2];
  23. private float[] tan = new float[2];
  24.  
  25. public GetPosTanView(Context context, AttributeSet attrs) {
  26. super(context, attrs);
  27. setLayerType(LAYER_TYPE_SOFTWARE, null);
  28. mArrawBmp = BitmapFactory.decodeResource(getResources(), R.drawable.arraw);
  29. mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
  30. mPaint.setStyle(Paint.Style.STROKE);
  31. mPaint.setStrokeWidth(4);
  32. mPaint.setColor(Color.BLACK);
  33.  
  34. mDstPath = new Path();
  35. mCirclePath = new Path();
  36. mCirclePath.addCircle(100, 100, 50, Path.Direction.CW);
  37.  
  38. mPathMeasure = new PathMeasure(mCirclePath, true);//true计算的path的闭合长度,false则测量当前path状态长度
  39.  
  40. ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
  41. animator.setRepeatCount(ValueAnimator.INFINITE);//无限循环
  42. animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
  43. public void onAnimationUpdate(ValueAnimator animation) {
  44. mCurAnimValue = (Float) animation.getAnimatedValue();
  45. invalidate();
  46. }
  47. });
  48. animator.setDuration(2000);
  49. animator.start();
  50. }
  51.  
  52. @Override
  53. protected void onDraw(Canvas canvas) {
  54. super.onDraw(canvas);
  55.  
  56. canvas.drawColor(Color.WHITE);
  57. float length = mPathMeasure.getLength(); //计算路径长度
  58. float stop = length * mCurAnimValue;
  59. mDstPath.reset();
  60.  
  61. mPathMeasure.getSegment(0, stop, mDstPath, true);
  62. canvas.drawPath(mDstPath, mPaint);
  63.  
  64. /**
  65. * 箭头旋转、位移实现方式一:
  66. */
  67.  
  68. //计算方位角
  69. // mPathMeasure.getPosTan(stop, pos, tan);//用于得到路径上某一长度的位置,以及位置的证正切值
  70. // float degrees = (float) (Math.atan2(tan[1], tan[0]) * 180.0 / Math.PI);
  71. // Matrix matrix = new Matrix();
  72. // matrix.postRotate(degrees, mArrawBmp.getWidth() / 2, mArrawBmp.getHeight() / 2);
  73. // matrix.postTranslate(pos[0] - mArrawBmp.getWidth() / 2, pos[1] - mArrawBmp.getHeight() / 2);
  74.  
  75. /**
  76. * 箭头旋转、位移实现方式一:
  77. */
  78. Matrix matrix = new Matrix();
  79. mPathMeasure.getMatrix(stop, matrix, PathMeasure.POSITION_MATRIX_FLAG | PathMeasure.TANGENT_MATRIX_FLAG);//用于的到路径上某一长度的位置以及该位置的正切值的矩阵
  80. matrix.preTranslate(-mArrawBmp.getWidth() / 2, -mArrawBmp.getHeight() / 2);
  81. canvas.drawBitmap(mArrawBmp, matrix, mPaint);
  82. }
  83.  
  84. }
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:orientation="vertical"
  4. android:layout_width="fill_parent"
  5. android:layout_height="fill_parent">
  6.  
  7. <com.loaderman.customviewdemo.GetSegmentView
  8. android:layout_width="match_parent"
  9. android:layout_height="80dp"/>
  10. <com.loaderman.customviewdemo.AliPayView
  11. android:layout_width="match_parent"
  12. android:layout_height="80dp"/>
  13. <com.loaderman.customviewdemo.GetPosTanView
  14. android:layout_width="match_parent"
  15. android:layout_height="150dp"/>
  16. </LinearLayout>

效果

利用pathMeasure实现路径动画的更多相关文章

  1. 探秘神奇的运动路径动画 Motion Path

    CSS 中有一个非常有意思的模块 -- CSS Motion Path Module Level 1,翻译过来也就是运动路径.本文将对 motion path 一探究竟,通过本文,你可以了解到: 什么 ...

  2. SVG路径动画解密

    原文:SVG路径动画解密 原文链接:http://www.gbtags.com/gb/share/5581.htm SVG路径动画效果现在貌似越来越多网站都使用了,给我的感觉就像是一段时间的流行而已, ...

  3. (数据科学学习手札85)Python+Kepler.gl轻松制作酷炫路径动画

    本文示例代码.数据已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 Kepler.gl相信很多人都听说过,作为 ...

  4. DrawSVG - SVG 路径动画 jQuery 插件

    jQuery DrawSVG 使用了 jQuery 内置的动画引擎实现 SVG 路径动画,用到了 stroke-dasharray 和 stroke-dashoffset 属性.DrawSVG 是完全 ...

  5. osg 路径 动画 效果

    osg 路径 动画 效果 转自:http://blog.csdn.net/zhuyingqingfen/article/details/8248157 #include <osg/Group&g ...

  6. SVG的路径动画效果

    使用SVG animateMotion实现的一个动画路径效果,相关代码如下. 在线调试唯一地址:http://www.gbtags.com/gb/debug/c88f4099-5056-4ad7-af ...

  7. ArcGIS API for Silverlight 绘制降雨路径动画

    原文:ArcGIS API for Silverlight 绘制降雨路径动画 #region 降雨动画演示 2014-04-16 List<Graphic> graphics = new ...

  8. WPF动画之路径动画(3)

    XAML代码: <Window x:Class="路径动画.MainWindow" xmlns="http://schemas.microsoft.com/winf ...

  9. 利用GPU实现大规模动画角色的渲染

    0x00 前言 我想很多开发游戏的小伙伴都希望自己的场景内能渲染越多物体越好,甚至是能同时渲染成千上万个有自己动作的游戏角色就更好了. 但不幸的是,渲染和管理大量的游戏对象是以牺牲CPU和GPU性能为 ...

随机推荐

  1. 列表推导式中的各个元素的id并不一样

    列表推导式中的各个元素在不同的内存中,id不一样 # 列表推导式的不同id值 ----------------------------------------------------- T = [] ...

  2. 1127 模型层orm表操作

    目录 昨日回顾 模型层 1.配置测试脚本 1.1 应用下tests文件 1.2 新建任意名称文件 2. 数据的增删改查 2.1 创建数据 2.2 修改数据 2.3 删除数据 2.4查询数据 十三门徒 ...

  3. 2018 Arab Collegiate Programming Contest (ACPC 2018) G. Greatest Chicken Dish (线段树+GCD)

    题目链接:https://codeforces.com/gym/101991/problem/G 题意:给出 n 个数,q 次询问区间[ li,ri ]之间有多少个 GCD = di 的连续子区间. ...

  4. git 廖雪峰博客笔记

    其他参考 http://www.softwhy.com/article-8498-1.html 本地模拟多用户来学习 参考   其实就是克隆两个目录,两个目录的git config 不同的名字和邮箱, ...

  5. Tcl在Vivado中的应用

    转载: https://blog.csdn.net/avrmcu1/article/details/43446529?utm_source=blogxgwz6

  6. java大文件上传解决方案

    最近遇见一个需要上传百兆大文件的需求,调研了七牛和腾讯云的切片分段上传功能,因此在此整理前端大文件上传相关功能的实现. 在某些业务中,大文件上传是一个比较重要的交互场景,如上传入库比较大的Excel表 ...

  7. C++类中静态数据成员MAP如何初始化

    conv_xxx.hpp class convolution { ... ... typedef std::map<int, std::string> ConvDtMap; static ...

  8. 第90节:Java中的Linux基础

    第90节:Java中的Linux基础 linux是装载虚拟机上面的: JDK依赖包: yum install glibc.i686 MYSQL依赖包: yum -y install libaio.so ...

  9. linux中清理旧内核

    执行update的时候会自动升级内核,开机启动的时候会好多内核选项.所以我们要清理不需要内核. 查看当前系统使用的内核版本 uname -a Linux localhost.localdomain 3 ...

  10. ROS手动编写服务端和客户端service demo(C++)

    service demo 原理和 topic 通信方式很像 点击打开链接,因此 1.srv : 进入 service_demo 创建 srv 文件夹,创建 Greeting.srv,将以下代码插入: ...