android PathMeasure

转载自:http://www.jianshu.com/p/4bb16cefca23
http://blog.csdn.net/cquwentao/article/details/51436852
http://blog.csdn.net/u013831257/article/details/51565591

1.构造方法

方法名释义
PathMeasure()创建一个空的测量对象
PathMeasure(Path path, boolean forceClosed)创建一个与指定路径关联的测量对象

  • 不论 forceClosed 设置为何种状态(true 或者 false), 都不会影响原有Path的状态。
  • forceClosed为true,该路径将被视为“关闭”(起点终点闭合),即使其轮廓未明确关闭。

2.公共方法

方法名释义
setPath()关联一个path
getLength()返回当前path的总长度
getPosTan(float distance, float pos[], float tan[])获取path路径上distance长度的点, 点坐标的值给 pos(二维数组),点的正切值给 tan(二维数组)
getMatrix(float distance, Matrix matrix, int flags)得到path路径上某一长度的位置以及该位置的正切值的矩阵(个人理解不深)
getSegment(float startD, float stopD, Path dst, boolean startWithMoveTo)获取从path路径的startD位置到stopD位置的片段,由dst接收(第四个参数详解见下文)
isClosed用于判断 Path 是否闭合,但是如果你在关联 Path 的时候设置 forceClosed 为 true 的话,这个方法的返回值则一定为true
nextContour用于跳转到下一条曲线的方法,如果跳转成功,则返回 true,如果跳转失败,则返回 false

注意:

  • getSegment方法中如果 startD、stopD 的数值不在取值范围 [0, getLength] 内,或者 startD ==
    stopD 则返回值为 false,不会改变 dst 内容

getSegment的第四个参数startWithMoveTo

  • 若为true,相当于将dst的起点moveTo与pathMesure关联的path起点
  • 若为false,默认moveTo(0,0),之后怎么画,我没有找到规律,希望大神看到解答
    示例如下:白线为原path,黑线为截取的path
path.addRect(200, 200, 400, 400, Path.Direction.CW);

startWithMoveTo为true

        Path dstPath = new Path();
        PathMeasure pathMeasure = new PathMeasure(path, false);
        pathMeasure.getSegment(0, 300, dstPath, true);

        canvas.drawPath(dstPath, dstPaint);

        canvas.drawPath(path, this.paint);

startWithMoveTo为true

以下均为:startWithMoveTo为false

 pathMeasure.getSegment(0, 300, dstPath, false);

startWithMoveTo为false

pathMeasure.getSegment(0, 500, dstPath, false);

startWithMoveTo为false

pathMeasure.getSegment(400, 500, dstPath, false);

这里写图片描述

pathMeasure.getSegment(450, 500, dstPath, false);

这里写图片描述

光能使者阵:

public class PathView extends View {
    private Paint paint;
    private Path innerCircle;//内圆路径
    private Path outerCircle;//外圆路径
    private Path triangle1;//第一个三角形路径
    private Path triangle2;//第二个三角形路径
    private Path drawPath;//截取的路径
    private PathMeasure pathMeasure;
    private Handler mHandler;
    private State mCurrentState = State.CIRCLE_STATE;
    private ValueAnimator.AnimatorUpdateListener animatorUpdateListener;
    private Animator.AnimatorListener animatorListener;
    private float distance;//当前动画执行的百分比取值为0-1
    private ValueAnimator valueAnimator;
    private long duration = 3000;
    private float mViewWidth;
    private float mViewHeight;

    //三个阶段的枚举
    private enum State {
        CIRCLE_STATE,//圆形阶段
        TRANGLE_STATE,//截取阶段
        FINISH_STATE//完成阶段
    }


    public PathView(Context context) {
        this(context, null);
    }

    public PathView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public PathView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mViewWidth = w;
        mViewHeight = h;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawColor(ContextCompat.getColor(getContext(), R.color.colorPrimary));
        canvas.save();
        canvas.translate(mViewWidth / 2, mViewHeight / 2);
        switch (mCurrentState) {
            case CIRCLE_STATE:
                //画内圆
                drawPath.reset();
                pathMeasure.setPath(innerCircle, false);
                pathMeasure.getSegment(0, distance * pathMeasure.getLength(), drawPath, true);
                canvas.drawPath(drawPath, paint);
                //画外圆
                drawPath.reset();
                pathMeasure.setPath(outerCircle, false);
                pathMeasure.getSegment(0, distance * pathMeasure.getLength(), drawPath, true);
                canvas.drawPath(drawPath, paint);
                break;
            case TRANGLE_STATE:
                canvas.drawPath(innerCircle, paint);
                canvas.drawPath(outerCircle, paint);
                drawPath.reset();
                pathMeasure.setPath(triangle1, false);
                //结束点在path上从起点到终点移动
                float stopD = distance * pathMeasure.getLength();
                //开始点为结束点减去一段距离(先增后减)
                float startD = stopD - (0.5f - Math.abs(0.5f - distance)) * 200;
                pathMeasure.getSegment(startD, stopD, drawPath, true);
                canvas.drawPath(drawPath, paint);
                drawPath.reset();
                pathMeasure.setPath(triangle2, false);
                pathMeasure.getSegment(startD, stopD, drawPath, true);
                canvas.drawPath(drawPath, paint);
                break;
            case FINISH_STATE:
                canvas.drawPath(innerCircle, paint);
                canvas.drawPath(outerCircle, paint);
                drawPath.reset();
                pathMeasure.setPath(triangle1, false);
                pathMeasure.getSegment(0, distance * pathMeasure.getLength(), drawPath, true);
                canvas.drawPath(drawPath, paint);
                drawPath.reset();
                pathMeasure.setPath(triangle2, false);
                pathMeasure.getSegment(0, distance * pathMeasure.getLength(), drawPath, true);
                canvas.drawPath(drawPath, paint);
                break;

        }

        canvas.restore();
    }

    private void init() {
        initPaint();

        initPath();

        initHandler();

        initAnimatorListener();

        initAnimator();

        mCurrentState = State.CIRCLE_STATE;

        valueAnimator.start();
    }

    private void initAnimator() {
        valueAnimator = ValueAnimator.ofFloat(0, 1).setDuration(duration);

        valueAnimator.addUpdateListener(animatorUpdateListener);

        valueAnimator.addListener(animatorListener);
    }

    private void initAnimatorListener() {
        animatorUpdateListener = new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                distance = (float) animation.getAnimatedValue();
                invalidate();
            }
        };

        animatorListener = new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                mHandler.sendEmptyMessage(0);
            }

            @Override
            public void onAnimationCancel(Animator animation) {

            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        };
    }

    private void initHandler() {
        mHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                switch (mCurrentState) {
                    case CIRCLE_STATE:
                        mCurrentState = State.TRANGLE_STATE;
                        valueAnimator.start();
                        break;
                    case TRANGLE_STATE:
                        mCurrentState = State.FINISH_STATE;
                        valueAnimator.start();
                        break;
                }

            }
        };
    }

    private void initPath() {
        innerCircle = new Path();
        outerCircle = new Path();
        triangle1 = new Path();
        triangle2 = new Path();
        drawPath = new Path();

        innerCircle.addArc(-220, -220, 220, 220, 150, -359.9F);
        outerCircle.addArc(-280, -280, 280, 280, 60, -359.9F);

        pathMeasure = new PathMeasure();
        pathMeasure.setPath(innerCircle, false);

        float[] pos = new float[2];
        //获取path路径上distance长度的 point 值给 pos,point 点的正切值给 tan。
        pathMeasure.getPosTan(0, pos, null);
        triangle1.moveTo(pos[0], pos[1]);//三角形1的起点为内圆的终点
        pathMeasure.getPosTan((1f / 3f) * pathMeasure.getLength(), pos, null);

        triangle1.lineTo(pos[0], pos[1]);//从内圆起点到内圆1/3的点画线
        pathMeasure.getPosTan((2f / 3f) * pathMeasure.getLength(), pos, null);

        triangle1.lineTo(pos[0], pos[1]);//从内圆1/3到内圆2/3的点画线
        triangle1.close();//从内圆2/3的点到内圆终点画线

        pathMeasure.getPosTan((2f / 3f) * pathMeasure.getLength(), pos, null);
        Matrix matrix = new Matrix();
        matrix.postRotate(-180);
        triangle1.transform(matrix, triangle2);//triangle2的路径为triangle1的路径旋转180度
    }

    //初始化画笔
    private void initPaint() {
        paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setColor(Color.WHITE);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(5);
        paint.setStrokeCap(Paint.Cap.ROUND);//圆头线条
        paint.setStrokeJoin(Paint.Join.BEVEL);//拐角为平角
        paint.setShadowLayer(10, 0, 0,ContextCompat.getColor(getContext(),R.color.colorAccent));//绘制内容下加一层阴影
    }
}

这里写图片描述
自己仿做的:
这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值