Android動畫 - PathMeasure打造不一樣的動畫
PathMeasures是什么
顧名思義案站,PathMeasure是一個用來測量Path的類
構(gòu)造函數(shù)
構(gòu)造函數(shù) | 方法描述 |
---|---|
PathMeasure() | 創(chuàng)建一個空的PathMeasure對象财剖。 |
PathMeasure(Path path, boolean forceClosed) | 創(chuàng)建與指定路徑對象(已經(jīng)創(chuàng)建并指定)關(guān)聯(lián)的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.構(gòu)造函數(shù)
無參構(gòu)造函數(shù):
PathMeasure()
創(chuàng)建一個空的PathMeasure喻喳,要使用它來測量路徑長度,或查找路徑的位置和切線伸辟,需要調(diào)用setPath簿姨。一旦路徑與測量對象相關(guān)聯(lián),Path進行了更改喇嘱,需要重新調(diào)用setPath方法茉贡。
有參構(gòu)造函數(shù)
PathMeasure(Path path, boolean forceClosed)
創(chuàng)建與指定路徑對象關(guān)聯(lián)的PathMeasure對象。現(xiàn)在者铜,測量對象可以返回路徑的長度以及路徑上任何位置的位置和切線腔丧。同上,一旦路徑與測量對象相關(guān)聯(lián)王暗,Path進行了更改悔据,需要重新調(diào)用setPath方法。
forceClosed:如果為true俗壹,該路徑也將被視為“閉合”科汗。
forceClosed不會影響Path本身的狀態(tài)。但是會影響測量結(jié)果绷雏。
下面我們舉個例子:
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
繪制的效果如下:
2.公共方法
getLength
返回當前Path的總長度头滔;如果沒有路徑與此度量對象關(guān)聯(lián),則返回0涎显。
isClosed
如果當前Path為close()坤检,則返回true。
setPath
Path與PathMeasure進行關(guān)聯(lián)期吓。
主要講一下以下幾個方法:
nextContour
public boolean nextContour()
獲取在路徑中下一個輪廓早歇,如果有下一個輪廓,則返回true讨勤,且PathMeasure切至下一個輪廓的數(shù)據(jù)箭跳;如果沒有下一個輪廓則返回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開頭咕缎。
參數(shù) | 作用 |
---|---|
startD | 開始截取的位置距離Path起點的距離 |
stopD | 結(jié)束截取的位置距離Path起點的距離 |
dst | 截取的Path會添加到dst中 |
startWithMoveTo | 起點是否啟用moveTo |
startD 和 stopD 的取值范圍 0 <= startD < stopD <= getLength
startWithMoveTo: 截取的片段的第一個點是否保持不變像寒;
設(shè)置為true:保持截取的片段不變,添加至dst路徑中喂江;
設(shè)置為false:會將截取的片段的起始點移至dst路徑中的最后一個點,讓dst路徑保持連續(xù)
舉個例子: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);
效果圖如下:
startWithMoveTo 為true
效果圖如下:
getPosTan
public boolean getPosTan(float distance, float pos[], float tan[])
參數(shù) | 作用 |
---|---|
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)
參數(shù) | 作用 |
---|---|
distance | 即需要的測量點與當前path起始位置的距離 |
matrix | 根據(jù) falgs 封裝好的matrix |
flags | 規(guī)定哪些內(nèi)容會存入到matrix中 |
flags 有POSITION_MATRIX_FLAG(位置) 和 ANGENT_MATRIX_FLAG(正切)兩種
其實這個方法就相當于getPosTan的封裝 matrix 的過程由 getMatrix 替我們做了尝哆,我們可以直接得到一個封裝好到 matrix。
實戰(zhàn)
加載動畫(一)
效果圖
主要利用PathMeasure的getSegment方法來截取路徑甜攀,繪制該動畫
思路
1.先勾勒出一個順時針的空心圓秋泄,然后生成pathMeasure對象
// 勾勒空心圓
path.addCircle(width / 2, height / 2, radius, Path.Direction.CW);
// 生成pathMeasure對象
pathMeasure.setPath(path, true);
2.截取的開始值和結(jié)束值
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);
完整代碼地址:
有用記得點顆小星星
加載動畫化(二)
效果圖
思路
主要利用getPosTan 獲取測量點的坐標和正余弦值,控制箭頭的方法和位置
1.先勾勒出一個順時針的空心圓谁撼,然后生成pathMeasure對象
// 勾勒空心圓
path.addCircle(width / 2, height / 2, radius, Path.Direction.CW);
// 生成pathMeasure對象
pathMeasure.setPath(path, true);
2.獲取繪制點的測量坐標和正余弦值歧胁,根據(jù)tan[0],tan[1]來計算箭頭旋轉(zhuǎn)的角度。
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計算方式自行查找墨榄,數(shù)學知識玄糟。
3.用Matrix對bitmap進行旋轉(zhuǎn)和平移
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動畫 - 仿抖音加載動畫