美文网首页Android开发
Android中PathMeasure的使用

Android中PathMeasure的使用

作者: iflymoon | 来源:发表于2018-01-05 17:46 被阅读90次

    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);
            }
        }
        

    相关文章

      网友评论

        本文标题:Android中PathMeasure的使用

        本文链接:https://www.haomeiwen.com/subject/nriubxtx.html