Android动画 - PathMeasure打造不一样的动画

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动画 - 仿抖音加载动画

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342