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

绘制的效果如下:

c224e56730cd

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);

效果图如下:

c224e56730cd

4011603795757_.pic_thumb.jpg

startWithMoveTo 为true

效果图如下:

c224e56730cd

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。

实战

加载动画(一)

效果图

c224e56730cd

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);

加载动画化(二)

效果图

c224e56730cd

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);

往期文章地址

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐