Android動畫 - PathMeasure打造不一樣的動畫

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

繪制的效果如下:


4041603852675_.pic_thumb.jpg

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

效果圖如下:


4011603795757_.pic_thumb.jpg

startWithMoveTo 為true
效果圖如下:


4021603795817_.pic_thumb.jpg
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)

加載動畫(一)

效果圖

LoadingCircleView.gif

主要利用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);

完整代碼地址:
有用記得點顆小星星


加載動畫化(二)

效果圖

LoadingArrowView.gif

思路

主要利用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動畫 - 仿抖音加載動畫

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市袄秩,隨后出現(xiàn)的幾起案子阵翎,更是在濱河造成了極大的恐慌,老刑警劉巖之剧,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件郭卫,死亡現(xiàn)場離奇詭異,居然都是意外死亡背稼,警方通過查閱死者的電腦和手機贰军,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人词疼,你說我怎么就攤上這事俯树。” “怎么了贰盗?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵许饿,是天一觀的道長。 經(jīng)常有香客問我舵盈,道長陋率,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任秽晚,我火速辦了婚禮瓦糟,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘赴蝇。我一直安慰自己菩浙,他們只是感情好,可當我...
    茶點故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布扯再。 她就那樣靜靜地躺著芍耘,像睡著了一般。 火紅的嫁衣襯著肌膚如雪熄阻。 梳的紋絲不亂的頭發(fā)上斋竞,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天,我揣著相機與錄音秃殉,去河邊找鬼坝初。 笑死,一個胖子當著我的面吹牛钾军,可吹牛的內(nèi)容都是我干的鳄袍。 我是一名探鬼主播,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼吏恭,長吁一口氣:“原來是場噩夢啊……” “哼拗小!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起樱哼,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤哀九,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后搅幅,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體阅束,經(jīng)...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年茄唐,在試婚紗的時候發(fā)現(xiàn)自己被綠了息裸。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,030評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖呼盆,靈堂內(nèi)的尸體忽然破棺而出年扩,到底是詐尸還是另有隱情,我是刑警寧澤宿亡,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布常遂,位于F島的核電站纳令,受9級特大地震影響挽荠,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜平绩,卻給世界環(huán)境...
    茶點故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一圈匆、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧捏雌,春花似錦跃赚、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至肤频,卻和暖如春叹括,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背宵荒。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工汁雷, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人报咳。 一個月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓侠讯,卻偏偏與公主長得像,于是被迫代替她去往敵國和親暑刃。 傳聞我的和親對象是個殘疾皇子厢漩,可洞房花燭夜當晚...
    茶點故事閱讀 44,976評論 2 355