Android动画进阶PathMeasure

作者: Rayhaha | 来源:发表于2017-04-04 00:20 被阅读472次

    PathMeasure

    作用:测量并获取Path的信息,用于绘制Path路径实现动画效果

    ValueAnimator在这里不会讲解,不过至关重要,是动画的发动机!

    基本路径绘制

    预览:

    普通路径绘制.mp4_1491231595.gif
    1. 生成完整的目标路径
    2. 初始化PathMeasure对象
    3. PathMeasure.setPath(targetPath,true) 测量路径
    4. mPathMeasure.getLength(); 获取路径的总长度
    5. 初始化动态的路径 mDstPath
    6. mPathMeasure.getSegment(startD, stopD, mDstPath, true); : 根据传入的起始值终止值(相当于要截取路径的部分),将路径赋值给mDstPath
    7. 使用ValueAnimator产生一个增长值来控制 终止值 如:float stopD = mAnimatedValue * mLength;
    8. 最后将 mDstPath 绘制出来,就可以实现路径的逐步绘制效果了
    //完整的圆的路径
            mCirclePath = new Path();
            //路径绘制每段截取出来的路径
            mDstPath = new Path();
    
            mCirclePath.addCircle(0, 0, 200, Path.Direction.CW);
    
            //路径测量类
            mPathMeasure = new PathMeasure();
            //测量路径
            mPathMeasure.setPath(mCirclePath, true);
    
            //获取被测量路径的总长度
            mLength = mPathMeasure.getLength();
    
            mValueAnimator = ValueAnimator.ofFloat(0, 1);
            mValueAnimator.setDuration(2000);
            mValueAnimator.setRepeatCount(ValueAnimator.INFINITE);
            mValueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
            mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    //获取从0-1的变化值
                    mAnimatedValue = (float) animation.getAnimatedValue();
                    //不断刷新绘图,实现路径绘制
                    invalidate();
                }
            });
    
    
    @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            //必须要有lineTo(0,0)才可以实现路径的完整绘制
            mDstPath.reset();
            mDstPath.lineTo(0, 0);
            float stopD = mAnimatedValue * mLength;
            float startD = 0;
    
            //获取当前进度的路径,同时赋值给传入的mDstPath
            mPathMeasure.getSegment(startD, stopD, mDstPath, true);
    
            canvas.save();
            canvas.translate(300, 300);
            canvas.drawPath(mDstPath, mPaint);
            canvas.restore();
        }
    
    
    

    Windows风格加载动画绘制

    预览:

    windows路径绘制.mp4_1491231732.gif
    • 实现这种效果只要在上面的基础上动态改变我们所截取的startD就可以了
      只要加上这一句代码
     //通过设置其实位置的变化来实现Window加载风格
                startD = (float) (stopD - ((0.5 - Math.abs(mAnimatedValue - 0.5)) * mLength));
    

    获取路径点的坐标和角度

    预览:

    箭头路径绘制.mp4_1491231817.gif

    主要涉及mPathMeasure.getPosTan(float distance, float pos[], float tan[]) 这个API

    • distance : 这个参数就是确定要获取路径上那个位置的点
    • pos[] : 根据distance返回 点的坐标信息并保存在传入的pos[]内, X保存在pos[0], Y则在pos[1]
    • tan[] : 根据distance返回 点的角度信息并保存传入tan[]内 ,主要结合float degree = (float) (Math.atan2(mTan[1], mTan[0]) * 180 / Math.PI);
      这个公式 就可以求得当前点的切线和X正半轴的角度

    具体绘制:

      if (mIsArrow) {
                //mPos是当前路径点的坐标
                //mTan通过下面公式可以得到当前点的切线角度
                mPathMeasure.getPosTan(mAnimatedValue * mLength, mPos, mTan);
                float degree = (float) (Math.atan2(mTan[1], mTan[0]) * 180 / Math.PI);
                Log.e("lzh", "onDraw:  degree=" + degree);
                canvas.save();
                canvas.translate(300, 300);
                canvas.drawCircle(mPos[0], mPos[1], 10, mPaint);
                canvas.rotate(degree);
                //绘制切线
                canvas.drawLine(0, -200, 200, -200, mPaint);
                canvas.restore();
    
            }
    

    最后:
    PathMeasure大大简化了我们去实现一个复杂路径的成本,只需要绘制好一个Path,剩下的就都交给PathMeasure搞定!
    当然,其实动画本身最可贵的还是源于一个好的想法。
    如果觉有有用,可以点赞鼓励一下哈O(∩_∩)O~~

    附上:代码Github

    相关文章

      网友评论

        本文标题:Android动画进阶PathMeasure

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