PathMeasure
作用:测量并获取Path的信息,用于绘制Path路径实现动画效果
ValueAnimator在这里不会讲解,不过至关重要,是动画的发动机!
基本路径绘制
预览:
- 生成完整的目标路径
- 初始化PathMeasure对象
-
PathMeasure.setPath(targetPath,true)
测量路径 -
mPathMeasure.getLength();
获取路径的总长度 - 初始化动态的路径
mDstPath
-
mPathMeasure.getSegment(startD, stopD, mDstPath, true);
: 根据传入的起始值和终止值(相当于要截取路径的部分),将路径赋值给mDstPath
- 使用ValueAnimator产生一个增长值来控制 终止值 如:
float stopD = mAnimatedValue * mLength;
- 最后将
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风格加载动画绘制
预览:
- 实现这种效果只要在上面的基础上动态改变我们所截取的
startD
就可以了
只要加上这一句代码
//通过设置其实位置的变化来实现Window加载风格
startD = (float) (stopD - ((0.5 - Math.abs(mAnimatedValue - 0.5)) * mLength));
获取路径点的坐标和角度
预览:
主要涉及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