Path(路徑)這個知識點GcsSloop大神寫了大概三篇文章進行了詳細的講解,是一個挺重要的知識點。
先解釋一下Path(路徑)這個詞,Path這個詞解釋為路徑,也就是我們畫在屏幕上的圖像,之前我們見到的Canvas中都是畫一些固定的形狀,現(xiàn)在我們能用Path對象進行一些復雜圖形的繪制了,路徑可以隨便畫,不必再被特殊的圖形所限制。
Path封裝了由直線和曲線(二次,三次貝塞爾曲線)構(gòu)成的幾何路徑。你能用Canvas中的drawPath來把這條路徑畫出來(同樣支持Paint的不同繪制模式),也可以用于剪裁畫布和根據(jù)路徑繪制文字。我們有時會用Path來描述一個圖像的輪廓,所以也會稱為輪廓線(輪廓線僅是Path的一種使用方法,兩者并不等價)
Path 常用方法表
| 作用 | 相關(guān)方法 | 備注 |
|---|---|---|
| 移動起點 | moveTo |
移動下一次操作的起點位置 |
| 設(shè)置終點 | setLastPoint |
重置當前path中最后一個點位置,如果在繪制之前調(diào)用,效果和moveTo相同 |
| 連接直線 | lineTo |
添加上一個點到當前點之間的直線到Path |
| 閉合路徑 | close |
連接第一個點連接到最后一個點,形成一個閉合區(qū)域 |
| 添加內(nèi)容 |
addRect, addRoundRect, addOval, addCircle, addPath, addArc,arcTo
|
添加(矩形, 圓角矩形, 橢圓, 圓, 路徑, 圓弧) 到當前Path (注意addArc和arcTo的區(qū)別) |
| 是否為空 | isEmpty |
判斷Path是否為空 |
| 是否為矩形 | isRect |
判斷path是否是一個矩形 |
| 替換路徑 | set |
用新的路徑替換到當前路徑所有內(nèi)容 |
| 偏移路徑 | offset |
對當前路徑之前的操作進行偏移(不會影響之后的操作) |
| 貝塞爾曲線 |
quadTo, cubicTo
|
分別為二次和三次貝塞爾曲線的方法 |
| rXxx方法 |
rMoveTo, rLineTo,rQuadTo, rCubicTo
|
不帶r的方法是基于原點的坐標系(偏移量), rXxx方法是基于當前點坐標系(偏移量) |
| 填充模式 |
setFillType, getFillType, isInverseFillType, toggleInverseFillType
|
設(shè)置,獲取,判斷和切換填充模式 |
| 提示方法 | incReserve |
提示Path還有多少個點等待加入(這個方法貌似會讓Path優(yōu)化存儲結(jié)構(gòu)) |
| 布爾操作(API19) | op |
對兩個Path進行布爾運算(即取交集、并集等操作) |
| 計算邊界 | computeBounds |
計算Path的邊界 |
| 重置路徑 |
reset,rewind
|
清除Path中的內(nèi)容 reset不保留內(nèi)部數(shù)據(jù)結(jié)構(gòu),但會保留FillType.rewind會保留內(nèi)部的數(shù)據(jù)結(jié)構(gòu),但不保留FillType
|
| 矩陣操作 | transform | 矩陣變換 |
Path基礎(chǔ)
moveTo、 setLastPoint、 lineTo 和 close
path.moveTo(10,10);
path.lineTo(20,20);
moveTo()方法是指定從哪一點開始走路經(jīng),僅僅制定了路徑的起點。既然moveTo()指定了路徑的起點,那么lineTo()這個方法就是指定下一步往哪走。萬一提前沒有moveTo()方法,那么默認的起始點就是坐標系原點。
setLastPoint();方法是改變上一個點的位置:
canvas.translate(mWidth / 2, mHeight / 2); // 移動坐標系到屏幕中心
Path path = new Path(); // 創(chuàng)建Path
path.lineTo(200, 200); // lineTo
path.setLastPoint(200,100); // setLastPoint
path.lineTo(200,0); // lineTo
canvas.drawPath(path, mPaint); // 繪制Path

這個例子是從默認點出發(fā),走到
(200,200),然后調(diào)用setLastPoint(200,100)這個方法將路徑從上一個點改變到這一個點上,然后繼續(xù)走到(200,0)。如果在
linTo()之后調(diào)用moveTo()方法會怎樣呢?
canvas.translate(mWidth / 2, mHeight / 2); // 移動坐標系到屏幕中心
Path path = new Path(); // 創(chuàng)建Path
path.lineTo(200, 200); // lineTo
path.moveTo(200,100); // moveTo
path.lineTo(200,0); // lineTo
canvas.drawPath(path, mPaint); // 繪制Path

在
lineTo()方法之后調(diào)用moveTo(),相當于重新開始了一個路徑,重新設(shè)置了新路徑的起點。并不會連接上一個點。close()方法作用是連接起始點(moveTo()方法指定的點,如果沒有moveTo()方法指定,那就是坐標系原點。)和終點。
canvas.translate(mWidth/2,mHeight/2);
Path path = new Path();
path.lineTo(200,200);
path.lineTo(300,200);
path.moveTo(200,100);
path.lineTo(200,0);
path.lineTo(300,0);
path.close();
canvas.drawPath(path,paint);

上邊我們看到,
close()只作用在了moveTo()方法開始的路徑,前邊的路徑?jīng)]有被閉合。說明moveTo()是新開了一條路徑。
addXxx()
第一類添加基本圖形。
這類方法主要是往path中添加圖形。
// 第一類(基本形狀)
// 圓形
public void addCircle (float x, float y, float radius, Path.Direction dir)
// 橢圓
public void addOval (RectF oval, Path.Direction dir)
// 矩形
public void addRect (float left, float top, float right, float bottom, Path.Direction dir)
public void addRect (RectF rect, Path.Direction dir)
// 圓角矩形
public void addRoundRect (RectF rect, float[] radii, Path.Direction dir)
public void addRoundRect (RectF rect, float rx, float ry, Path.Direction dir)
主要是添加矩形,橢圓等圖形,跟前面的操作區(qū)別不大。我們主要注意Path.Direction 這個參數(shù),
| 類型 | 解釋 | 翻譯 |
|---|---|---|
CW |
clockwise |
順時針 |
CCW |
counter-clockwise |
逆時針 |
這個參數(shù)主要是定義了圖形的閉合路徑,從左上角開始,是順時針閉合還是逆時針閉合。一個正常的矩形,不論順時針還是逆時針都沒什么區(qū)別,但是如果是不規(guī)則多邊形,順時針和逆時針就不同了。
canvas.translate(mWidth / 2, mHeight / 2); // 移動坐標系到屏幕中心
Path path = new Path();
path.addRect(-200,-200,200,200, Path.Direction.CW);
path.setLastPoint(-300,300); // <-- 重置最后一個點的位置
canvas.drawPath(path,mPaint);

canvas.translate(mWidth / 2, mHeight / 2); // 移動坐標系到屏幕中心
Path path = new Path();
path.addRect(-200,-200,200,200, Path.Direction.CCW);
path.setLastPoint(-300,300); // <-- 重置最后一個點的位置
canvas.drawPath(path,mPaint);

上邊兩個例子是一個相同路徑的順時針和逆時針的兩種表現(xiàn)形式。
Path.Direction不僅影響圖形的形狀,還會影響圖形的填充效果。下邊會講到。
第二類(addPath)
// 第二類(Path)
// path
public void addPath (Path src)
public void addPath (Path src, float dx, float dy)
public void addPath (Path src, Matrix matrix)
這個方法其實就是將兩個路徑合并到一塊。
第二個方法后邊兩個參數(shù)作用是將src進行位移之后添加到指定path中。
第三個方法是將src進行matrix變換之后添加到指定的path中。
第三類(addArc與arcTo)
// 第三類(addArc與arcTo)
// addArc
public void addArc (RectF oval, float startAngle, float sweepAngle)
// arcTo
public void arcTo (RectF oval, float startAngle, float sweepAngle)
public void arcTo (RectF oval, float startAngle, float sweepAngle, boolean forceMoveTo)
這是在當前path添加圓弧的方法。
| 參數(shù) | 摘要 |
|---|---|
| oval | 圓弧的外切矩形。 |
| startAngle | 開始角度 |
| sweepAngle | 掃過角度(-360 <= sweepAngle <360) |
| forceMoveTo | 是否強制使用MoveTo |
addArc()方法直接添加一個圓弧到指定path中,而arcTo()是將圓弧添加到path中,根據(jù)forceMoveTo參數(shù)值來判斷,如果forceMoveTo為true,則將圓弧移動,將圓弧的起點和path的終點連接起來,如果forceMoveTo為false,則將圓弧的起點和path的重點連接起來。
第3組:isEmpty、 isRect、isConvex、 set和 offset
isEmpty
判斷path中是否有內(nèi)容
isRect(RectF rect)
判斷path是不是一個矩形,如果是矩形,則將矩形信息存儲到rect中
set(Path path1)
將新的path復制給老的path
path.set(path1);
//等價于
path=path1;
offset
public void offset (float dx, float dy)
public void offset (float dx, float dy, Path dst)
這個方法就是將path進行位移
dst狀態(tài) |
效果 |
|---|---|
dst不為空 |
將當前path平移后的狀態(tài)存入dst中,不會影響當前path
|
dst為空(null) |
平移將作用于當前path,相當于第一種方法 |
canvas.translate(mWidth / 2, mHeight / 2); // 移動坐標系到屏幕中心
canvas.scale(1,-1); // <-- 注意 翻轉(zhuǎn)y坐標軸
Path path = new Path(); // path中添加一個圓形(圓心在坐標原點)
path.addCircle(0,0,100, Path.Direction.CW);
Path dst = new Path(); // dst中添加一個矩形
dst.addRect(-200,-200,200,200, Path.Direction.CW);
path.offset(300,0,dst); // 平移
canvas.drawPath(path,mPaint); // 繪制path
mPaint.setColor(Color.BLUE); // 更改畫筆顏色
canvas.drawPath(dst,mPaint); // 繪制dst

本來感覺沒多少內(nèi)容的,寫著寫著就變得那么多。。。。
總結(jié):
path就是一條路徑,我們可以調(diào)用Canvas的drawPath()方法將path繪制到屏幕上。path可以自己畫路徑,使用moveTo、lineTo、setLastPoint、close等方法。也可以addXxx添加矩形,橢圓等圖形到path中,也可以使用addPath添加path到指定path中,當然我們也可以判斷path是否為空,是否是矩形,也可以使用offset方法對path進行平移。