Android动画 - PathMeasure打造不一样的动画
PathMeasures是什么
顾名思义,PathMeasure是一个用来测量Path的类
构造函数
构造函数 | 方法描述 |
---|---|
PathMeasure() | 创建一个空的PathMeasure对象。 |
PathMeasure(Path path, boolean forceClosed) | 创建与指定路径对象(已经创建并指定)关联的PathMeasure对象。 |
公共方法
返回值 | 方法名称 |
---|---|
float | getLength() |
boolean | getMatrix(float distance, Matrix matrix, int flags) |
boolean | getPosTan(float distance, float[] pos, float[] tan) |
boolean | getSegment(float startD, float stopD, Path dst, boolean startWithMoveTo) |
boolean | isClosed() |
boolean | nextContour() |
void | setPath(Path path, boolean forceClosed) |
接下来分别介绍下以上的方法
1.构造函数
无参构造函数:
PathMeasure()
创建一个空的PathMeasure,要使用它来测量路径长度,或查找路径的位置和切线,需要调用setPath。一旦路径与测量对象相关联,Path进行了更改,需要重新调用setPath方法。
有参构造函数
PathMeasure(Path path, boolean forceClosed)
创建与指定路径对象关联的PathMeasure对象。现在,测量对象可以返回路径的长度以及路径上任何位置的位置和切线。同上,一旦路径与测量对象相关联,Path进行了更改,需要重新调用setPath方法。
forceClosed:如果为true,该路径也将被视为“闭合”。
forceClosed不会影响Path本身的状态。但是会影响测量结果。
下面我们举个例子:
canvas.translate(mWidth/2,mHeight/2);
Path path = new Path();
path.lineTo(0,200);
path.lineTo(200,200);
path.lineTo(200,0);
PathMeasure measure1 = new PathMeasure(path,false);
PathMeasure measure2 = new PathMeasure(path,true);
Log.e("TAG", "forceClosed=false---->"+measure1.getLength());
Log.e("TAG", "forceClosed=true----->"+measure2.getLength());
canvas.drawPath(path,mDeafultPaint);
log如下:
E/TAG: forceClosed=false---->600.0
E/TAG: forceClosed=true----->800.0
绘制的效果如下:
4041603852675_.pic_thumb.jpg
2.公共方法
getLength
返回当前Path的总长度;如果没有路径与此度量对象关联,则返回0。
isClosed
如果当前Path为close(),则返回true。
setPath
Path与PathMeasure进行关联。
主要讲一下以下几个方法:
nextContour
public boolean nextContour()
获取在路径中下一个轮廓,如果有下一个轮廓,则返回true,且PathMeasure切至下一个轮廓的数据;如果没有下一个轮廓则返回false。
我的理解一次moveTo增加一个轮廓。
getSegment
public boolean getSegment(float startD,float stopD,Path dst,boolean startWithMoveTo)
给定起点和终点的距离,请返回中间的路段。如果段的长度为零,则返回false,否则返回true。startD和stopD固定取值范围(0,getLength())。如果startD> = stopD,则返回false(并保持dst不变)。如果startWithMoveTo为true,则以moveTo开头。
参数 | 作用 |
---|---|
startD | 开始截取的位置距离Path起点的距离 |
stopD | 结束截取的位置距离Path起点的距离 |
dst | 截取的Path会添加到dst中 |
startWithMoveTo | 起点是否启用moveTo |
startD 和 stopD 的取值范围 0 <= startD < stopD <= getLength
startWithMoveTo: 截取的片段的第一个点是否保持不变;
设置为true:保持截取的片段不变,添加至dst路径中;
设置为false:会将截取的片段的起始点移至dst路径中的最后一个点,让dst路径保持连续
举个例子:startWithMoveTo 为flase
canvas.translate(width/2,height/2);
Path mPath = new Path();
Path mDst = new Path();
PathMeasure mPathMeasure = new PathMeasure();
// 顺时针画 半径为400px的圆
mPath.addCircle(0,0, 400, Path.Direction.CW);
mPathMeasure.setPath(mPath, false);
// 画直线
mDst.moveTo(110, 0);
mDst.lineTo(200, 300);
// 截取 0.25 到 0.5 距离的圆弧放置dst中
mPathMeasure.getSegment(mPathMeasure.getLength() * 0.25f,
mPathMeasure.getLength() * 0.5f,
mDst,
false);
canvas.drawPath(mDst, paint);
效果图如下:
4011603795757_.pic_thumb.jpg
startWithMoveTo 为true
效果图如下:
4021603795817_.pic_thumb.jpg
getPosTan
public boolean getPosTan(float distance, float pos[], float tan[])
参数 | 作用 |
---|---|
distance | 即需要的测量点与当前path起始位置的距离 |
pos | 测量点的坐标,pos[0]为x坐标,pos[1]为y坐标 |
tan | 测量点的正余弦值,tan[0]为cos,即余弦值或称为单位圆的x坐标;tan[1]为sin,即正弦值或称为单位圆的y坐标; |
distance 取值范围:0<=distance<=getLength()
A(x,y)原点为O,cos = OA/OB,sin = OA/AB
getMatrix
public boolean getMatrix(float distance, Matrix matrix, int flags)
参数 | 作用 |
---|---|
distance | 即需要的测量点与当前path起始位置的距离 |
matrix | 根据 falgs 封装好的matrix |
flags | 规定哪些内容会存入到matrix中 |
flags 有POSITION_MATRIX_FLAG(位置) 和 ANGENT_MATRIX_FLAG(正切)两种
其实这个方法就相当于getPosTan的封装 matrix 的过程由 getMatrix 替我们做了,我们可以直接得到一个封装好到 matrix。
实战
加载动画(一)
效果图
LoadingCircleView.gif主要利用PathMeasure的getSegment方法来截取路径,绘制该动画
思路
1.先勾勒出一个顺时针的空心圆,然后生成pathMeasure对象
// 勾勒空心圆
path.addCircle(width / 2, height / 2, radius, Path.Direction.CW);
// 生成pathMeasure对象
pathMeasure.setPath(path, true);
2.截取的开始值和结束值
stop = mAnimatorValue * mLength;
start = (float) (stop - ((0.5 - Math.abs(mAnimatorValue - 0.5)) * mLength));
mAnimatorValue 的取值为(0,1) ,当mAnimatorValue为0或1时,两个值相等。
3.截取路径后绘制路径
pathMeasure.getSegment(start, stop, dst, true);
canvas.drawPath(dst, paint);
完整代码地址:
有用记得点颗小星星
加载动画化(二)
效果图
LoadingArrowView.gif思路
主要利用getPosTan 获取测量点的坐标和正余弦值,控制箭头的方法和位置
1.先勾勒出一个顺时针的空心圆,然后生成pathMeasure对象
// 勾勒空心圆
path.addCircle(width / 2, height / 2, radius, Path.Direction.CW);
// 生成pathMeasure对象
pathMeasure.setPath(path, true);
2.获取绘制点的测量坐标和正余弦值,根据tan[0],tan[1]来计算箭头旋转的角度。
measure.getPosTan(measure.getLength() * mAnimatorValue, pos, tan);
float angle = (float) (Math.atan2(tan[1], tan[0]) * 180 / Math.PI);
mAnimatorValue 的取值为(0,1) ,当mAnimatorValue为0或1时,两个值相等。
angle计算方式自行查找,数学知识。
3.用Matrix对bitmap进行旋转和平移
mMatrix.postRotate(angle,mBitmap.getWidth()/2,mBitmap.getHeight()/2);
mMatrix.postTranslate(pos[0] - mBitmap.getWidth() / 2,pos[1] - mBitmap.getHeight() / 2);
4.绘制bitmap
canvas.drawBitmap(mBitmap,mMatrix,mPaint);
完整代码地址:
有用记得点颗小星星
往期文章地址
Android动画 - 仿花束直播加载动画
Android动画 - 仿58同城加载动画
Android动画 - 仿抖音加载动画
网友评论