簡(jiǎn)單說(shuō)說(shuō)
<p>
??Path是android中用來(lái)封裝幾何學(xué)路徑的一個(gè)類化漆,因?yàn)镻ath在圖形繪制上占的比重還是相當(dāng)大的切油,所以經(jīng)過(guò)學(xué)習(xí)后贫导,對(duì)Path中方法進(jìn)行總結(jié)使用與應(yīng)用
Path類的方法
<p>
Path中的方法相對(duì)較多烹玉,不對(duì)期進(jìn)行一一說(shuō)明叁幢,將平時(shí)用的較多的方法拿出來(lái)著重說(shuō)明
(1) 將路徑連接至某個(gè)坐標(biāo)點(diǎn)
lineTo(float x, float y)
**(2)改變起始點(diǎn)的位置 **
moveTo(float x, float y)
(3)閉合路徑
close()
(4)路徑重置
reset()
(5)畫弧形路徑
arcTo(float left, float top, float right, float bottom, RectF oval, float startAngle, float sweepAngle,boolean forceMoveTo)
arcTo (RectF oval, float startAngle, float sweepAngle)
arcTo (RectF oval, float startAngle, float sweepAngle, boolean forceMoveTo)
參數(shù)boolean forceMoveTo卖宠,當(dāng)值為true時(shí)將會(huì)把弧的起點(diǎn)作為Path的起點(diǎn)
(6)**addXXX方法 **直接往Path中添加一些曲線
添加矩形曲線
addRect(RectF rect,Direction dir)
addRect(float left, float top, float right, float bottom,Direction dir)
添加橢圓形曲線
addOval(RectF oval,Direction dir)
addOval(float left, float top, float right, float bottom,Direction dir)
添加圓形曲線
addCircle(float x, float y, floatradius,Direction dir)
添加弧形曲線
addArc(RectF oval, float startAngle, float sweepAngle)
addArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle)
添加圓角矩形曲線
addRoundRect(RectF rect, float rx, float ry,Direction dir)
addRoundRect(float left, float top, float right, float bottom, float rx, float ry,Direction dir)
addRoundRect(RectF rect, float[] radii,Direction dir)
addRoundRect(float left, float top, float right, float bottom, float[] radii,Direction dir)
添加path
addPath(Path src, float dx, float dy)
addPath(Path src)
addPath(Path src,Matrix matrix)
而上面這些方法搭配一起就會(huì)碰撞出奇妙的火花
<p>
比如
亦或這個(gè)
還有這個(gè)
好吧我承認(rèn)這個(gè)是我畫的巍杈,確實(shí)比例有問(wèn)題。扛伍。筷畦。
也許很多人會(huì)覺得利用Path來(lái)繪制圖像代碼量很大而且需要計(jì)算的數(shù)據(jù)也很多,但是我覺得的基本用法還是需要了解也熟練使用的
接下來(lái)要介紹的則是Path中的大招刺洒,這個(gè)方法會(huì)帶來(lái)很多很贊的體驗(yàn)與設(shè)計(jì)
(7)貝塞爾曲線
<p>
什么是貝塞爾曲線就不做概述了鳖宾,簡(jiǎn)單說(shuō)就是只需要一個(gè)起點(diǎn)、一個(gè)終點(diǎn)和至少零個(gè)控制點(diǎn)則可定義一個(gè)貝賽爾曲線
<p>
一階貝賽爾曲線
其中B(t)為時(shí)間為t時(shí)點(diǎn)的坐標(biāo)逆航,P0為起點(diǎn)鼎文、Pn為終點(diǎn),曲線圖如下
二階貝塞爾曲線
二階貝賽爾曲線的一個(gè)明顯特征是其擁有一個(gè)控制點(diǎn)因俐,通過(guò)控制點(diǎn)來(lái)控制曲線的走向
對(duì)應(yīng)的二階曲線圖如下
在Android Path中存在對(duì)應(yīng)的方法來(lái)實(shí)現(xiàn)二階貝塞爾曲線
quadTo(float x1, floaty1, float x2, float y2) 其中x1,y1為控制點(diǎn)拇惋,x2,y2為終點(diǎn)
利用好二階貝塞爾曲線其實(shí)可以玩轉(zhuǎn)出一些比較贊的效果了
比如下面的波浪效果
代碼實(shí)現(xiàn)角度也很簡(jiǎn)單
<p>
/*
* 設(shè)置Path起點(diǎn)
* 注意我將Path的起點(diǎn)設(shè)置在了控件的外部看不到的區(qū)域
* 如果我們將起點(diǎn)設(shè)置在控件左端x=0的位置會(huì)使得貝塞爾曲線變得生硬
* 至于為什么剛才我已經(jīng)說(shuō)了
* 所以我們稍微讓起點(diǎn)往“外”走點(diǎn)
*/
mPath.moveTo(-1 / 4F * vWidth, waveY);
/*
* 以二階曲線的方式通過(guò)控制點(diǎn)連接位于控件右邊的終點(diǎn)
* 終點(diǎn)的位置也是在控件外部
* 我們只需不斷讓ctrX的大小變化即可實(shí)現(xiàn)“浪”的效果
*/
mPath.quadTo(ctrX, ctrY, vWidth + 1 / 4F * vWidth, waveY);
// 圍繞控件閉合曲線
mPath.lineTo(vWidth + 1 / 4F * vWidth, vHeight);
mPath.lineTo(-1 / 4F * vWidth, vHeight);
mPath.close();
canvas.drawPath(mPath, mPaint);
/*
* 當(dāng)控制點(diǎn)的x坐標(biāo)大于或等于終點(diǎn)x坐標(biāo)時(shí)更改標(biāo)識(shí)值
*/
if (ctrX >= vWidth + 1 / 4F * vWidth) {
isInc = false;
}
/*
* 當(dāng)控制點(diǎn)的x坐標(biāo)小于或等于起點(diǎn)x坐標(biāo)時(shí)更改標(biāo)識(shí)值
*/
else if (ctrX <= -1 / 4F * vWidth) {
isInc = true;
}
// 根據(jù)標(biāo)識(shí)值判斷當(dāng)前的控制點(diǎn)x坐標(biāo)是該加還是減
ctrX = isInc ? ctrX + 20 : ctrX - 20;
/*
* 讓“水”不斷減少
*/
if (ctrY <= vHeight) {
ctrY += 2;
waveY += 2;
}
mPath.reset();
// 重繪
invalidate();
主要通過(guò)控制控制點(diǎn)與終點(diǎn)的位置不斷的重繪產(chǎn)生波浪的形狀
同樣的某些下拉刷新的效果也是通過(guò)這樣的方法去產(chǎn)生的比如
另外QQ“一鍵下班”功能其實(shí)也是基于二階貝塞爾曲線實(shí)現(xiàn)的
三階貝塞爾曲線
三階貝賽爾曲線則是擁有兩個(gè)控制點(diǎn),通過(guò)控制點(diǎn)來(lái)控制曲線的走向
對(duì)應(yīng)的三階曲線圖如下
在Android Path中存在對(duì)應(yīng)的方法來(lái)實(shí)現(xiàn)二階貝塞爾曲線
cubicTo(float x1, float y1, float x2, float y2, float x3, float y3)
其中x1,y1為第一個(gè)控制點(diǎn)抹剩,x2,y2為第二個(gè)控制點(diǎn)撑帖,x3,y3為終點(diǎn)
利用好三階貝塞爾曲線其實(shí)可以有更多的效果了,在很多的App其實(shí)都有運(yùn)用到了
比如百度貼吧的下拉刷新吧兔,美圖的下拉刷新磷仰,Chrome的下拉刷新,慕課網(wǎng)的下拉刷新境蔼,其實(shí)都是基于三階貝塞爾曲線來(lái)實(shí)現(xiàn)的
簡(jiǎn)單說(shuō)下三階貝塞爾運(yùn)用的
第一種,和上述的二階貝塞爾曲線一樣伺通,作為波浪使用
<p>
代表例子:慕課App的下拉刷新
這種實(shí)現(xiàn)其實(shí)與二階波浪實(shí)現(xiàn)是一致的箍土,控制好兩個(gè)控制點(diǎn)即可以實(shí)現(xiàn),不做代碼的贅述
第二種則是通過(guò)閉合的路徑產(chǎn)生特殊的效果
<p>
比如說(shuō)下面這個(gè)例子
這個(gè)效果怎么實(shí)現(xiàn)的呢罐监?
<p>
后面給出相關(guān)實(shí)現(xiàn)的代碼
(8)PathMeasure
<p>
PathMeasure其實(shí)是測(cè)量Path的一個(gè)類吴藻,通過(guò)PathMeasure可以實(shí)現(xiàn)一些比較復(fù)雜的路徑運(yùn)動(dòng)效果
mPathMeasure = new PathMeasure(mPath, true);
//設(shè)置運(yùn)動(dòng)的路徑點(diǎn)
mCurrentPosition = new float[2];
ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, mPathMeasure.getLength());
valueAnimator.setDuration(duration);
valueAnimator.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float value = (Float) animation.getAnimatedValue();
// 獲取當(dāng)前點(diǎn)坐標(biāo)封裝到mCurrentPosition
mPathMeasure.getPosTan(value, mCurrentPosition, null);
postInvalidate();
}
});
valueAnimator.start();
通過(guò)PathMeasure可以實(shí)現(xiàn)如下的效果
到此Path中的大部分方法與使用應(yīng)用都已經(jīng)描述到了,由于是本人學(xué)習(xí)筆記弓柱,所以大部分的效果圖都是來(lái)自于網(wǎng)絡(luò)的分享沟堡,感謝各位大牛的分享
Reference
1.自定義控件其實(shí)很簡(jiǎn)單5/12From AigeStudio
2.Android 用Canvas 畫幾何圖形侧但,畫出小黃人From 山言兩語(yǔ)
3.Android雷達(dá)圖(蜘蛛網(wǎng)圖)繪制 From crazy__chen
4.慕課網(wǎng)app下拉刷新圖標(biāo)填充效果的實(shí)現(xiàn)From 安卓弟
5.【Android開源項(xiàng)目解析】QQ“一鍵下班”功能實(shí)現(xiàn)解析From 裸奔的凱子哥
6.四步實(shí)現(xiàn)ChromeLikeSwipeLayout效果From 我是Asha
7.三次貝塞爾曲線練習(xí)之彈性的圓From shadev
8.Path特效之PathMeasure打造萬(wàn)能路徑動(dòng)效From 學(xué)問(wèn)積年而成
9.【Android開源項(xiàng)目解析】仿支付寶付款成功及"天女散花"效果實(shí)現(xiàn)From 裸奔的凱子哥