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); } }
-
网友评论