Android中PathMeasure的使用

PathMeasure使用介绍

  • 介绍

    AndroidSDK提供的一个非常有用的API来对一个Path路径点的坐标追踪,它可以认为是一个Path的坐标计算器。

  • 使用
    • 初始化
      构造方法共有两个:PathMeasure(),PathMeasure(Path path, boolean forceClosed)
      1、默认无参构造方法

      PathMeasure pathMeasure = new PathMeasure();
      

      初始化PathMeasure后,可以通过PathMeasure.setPath(Path path, boolean forceClosed)的方式来将Path和PathMeasure进行绑定。被关联的Path必须是已经创建好的,如果关联之后Path内容进行了更改,则需要使用setPath方法重新关联。
      2、有参构造方法

      PathMeasure pathMeasure = new PathMeasure(path, false);
      

      同样,被关联的Path也必须是已经创建好的,如果关联之后Path内容进行了更改,则需要使用setPath方法重新关联。关于第二个参数forceClosed,不论forceClosed设置为何种状态(true或者false), 都不会影响原有Path的状态,即Path与PathMeasure关联之后,之前的的Path不会有任何改变。forceClosed的设置状态会影响测量结果,如果Path未闭合但在与PathMeasure关联的时候设置forceClosed为true时,测量结果可能会比Path实际长度稍长一点,获取到的是该Path闭合时状态的长度。同样如果Path闭合但在与PathMeasure关联的时候设置forceClosed为false时,测量结果可能会比Path实际长度稍短一点,就是说forceClosed的设置只会影响测量的结果。

    • 方法
      1、float getLength():
      这个方法的使用比较广泛,其作用就是获取计算的路径长度。
      2、boolean getSegment(float startD, float stopD, Path dst, boolean startWithMoveTo):
      用于获取Path的一个片段。参数解释如下:
      startD:开始截取位置距离Path起点的长度
      stopD:结束截取位置距离Path起点的长度
      dst:截取的Path将会添加到dst中
      startWithMoveTo:起始点是否使用moveTo
      3、boolean getPosTan(float distance, float pos[], float tan[]):
      用于得到路径上某一长度的位置以及该位置的正切值
      distance:获取点距离起点的长度
      pos:获取点的坐标
      tan:获取点的正切值,tan是tangent的缩写,即中学中常见的正切,其中tan[0]是邻边边长,tan[1]是对边边长,而Math中atan2方法是根据正切是数值计算出该角度的大小,得到的单位是弧度,所以上面又将弧度转为了角度。
      4、boolean nextContour():
      Path可以由多条曲线构成,但不论是getLength,getgetSegment或者是其它方法,都只会在其中第一条线段上运行,而这个nextContour就是用于跳转到下一条曲线到方法,如果跳转成功,则返回true, 如果跳转失败,则返回false。
      5、boolean getMatrix(float distance, Matrix matrix, int flags):
      用于得到路径上某一长度的位置以及该位置的正切值的矩阵
      distance:距离Path起点的长度
      matrix:根据falgs封装好的matrix
      flags:规定哪些内容会存入到matrix中,POSITION_MATRIX_FLAG(位置)、ANGENT_MATRIX_FLAG(正切值)

    • 应用

      示例1效果图(getPosTan方法应用):

      实现代码:

      public class PathMeasureView extends View {
      
          private Paint mPaint;
          private Path path;
          private PathMeasure mPathMeasure;
          private float mAnimatorValue;
          private float mLength;
          private float[] pos;
          private float[] tan;
          private Bitmap bitmap;
      
          public PathMeasureView(Context context, AttributeSet attrs) {
              super(context, attrs);
              mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
              mPaint.setStyle(Paint.Style.STROKE);
              mPaint.setColor(Color.RED);
              mPaint.setStrokeWidth(5);
              mPaint.setStrokeCap(Paint.Cap.ROUND);
              mPaint.setAntiAlias(true);
              path = new Path();
              path.moveTo(0, 0);
              path.quadTo(100, 200, 200, 0);
              path.quadTo(300, -200, 400, 0);
              mPathMeasure = new PathMeasure(path, false);
              mLength = mPathMeasure.getLength();
              pos = new float[2];
              tan = new float[2];
              bitmap = BitmapFactory.decodeResource(context.getResources(), R.mipmap.timg);
      
              ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1);
              valueAnimator.setDuration(5000);
              valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                  @Override
                  public void onAnimationUpdate(ValueAnimator animation) {
                      mAnimatorValue = (float) animation.getAnimatedValue();
                      postInvalidate();
                  }
              });
              valueAnimator.setInterpolator(new LinearInterpolator());
              valueAnimator.setRepeatCount(ValueAnimator.INFINITE);
              valueAnimator.start();
          }
      
          @Override
          protected void onDraw(Canvas canvas) {
              super.onDraw(canvas);
              canvas.save();
              canvas.translate(200, 400);
              canvas.drawPath(path, mPaint);
              mPathMeasure.getPosTan(mLength * mAnimatorValue, pos, tan);
              float degrees = (float) (Math.atan2(tan[1], tan[0]) * 180.0 / Math.PI);
              canvas.rotate(degrees, pos[0], pos[1]);
              canvas.drawBitmap(bitmap, pos[0] - bitmap.getWidth()/2, pos[1] - bitmap.getHeight(), mPaint);
              canvas.restore();
          }
      }
      

      示例2效果(getSegment应用):


      gaollg2.GIF

      实现代码:

      public class PathMeasureView extends View {
      
          private Paint mPaint;
          private Path path;
          private PathMeasure mPathMeasure;
          private float mAnimatorValue;
          private Path mDst;
          private float mLength;
      
          public PathMeasureView(Context context, AttributeSet attrs) {
              super(context, attrs);
              mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
              mPaint.setStyle(Paint.Style.STROKE);
              mPaint.setColor(Color.RED);
              mPaint.setStrokeWidth(5);
              mPaint.setStrokeCap(Paint.Cap.ROUND);
              mPaint.setAntiAlias(true);
              path = new Path();
              path.addCircle(0, 0, 100, Path.Direction.CW);
              mPathMeasure = new PathMeasure(path, false);
              mDst = new Path();
              mLength = mPathMeasure.getLength();
      
              ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 2);
              valueAnimator.setDuration(5000);
              valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                  @Override
                  public void onAnimationUpdate(ValueAnimator animation) {
                      mAnimatorValue = (float) animation.getAnimatedValue();
                      postInvalidate();
                  }
              });
              valueAnimator.setInterpolator(new LinearInterpolator());
              valueAnimator.setRepeatCount(ValueAnimator.INFINITE);
              valueAnimator.start();
          }
      
          @Override
          protected void onDraw(Canvas canvas) {
              super.onDraw(canvas);
      
              mDst.reset();
              float start, stop;
              if (mAnimatorValue <= 1) {
                  start = 0;
                  stop = mLength * mAnimatorValue;
              } else {
                  start = (mAnimatorValue - 1) * mLength;
                  stop = mLength;
              }
              mPathMeasure.getSegment(start, stop, mDst, true);
              canvas.translate(200, 400);
              canvas.drawPath(mDst, mPaint);
          }
      }
      
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,542评论 6 504
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,822评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,912评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,449评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,500评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,370评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,193评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,074评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,505评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,722评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,841评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,569评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,168评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,783评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,918评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,962评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,781评论 2 354

推荐阅读更多精彩内容