Android繪圖之Path總結
Path作為Android中一種相對複雜的繪圖方式,官方文件中的有些解釋並不是很好理解,這裡作一個相對全面一些的總結,供日後檢視,也分享給大家,共同進步。
1.基本繪圖方法
- addArc(RectF oval, float startAngle, float sweepAngle)
繪製弧線,配合Paint的Style可以實現不同的填充效果 - addCircle(float x, float y, float radius, Path.Direction dir)
繪製圓形,其中第dir
引數用來指定繪製時是順時針還是逆時針 - addOval(RectF oval, Path.Direction dir)
繪製橢圓形,其中oval
作為橢圓的外切矩形區域 - addRect(RectF rect, Path.Direction dir)
繪製矩形 - addRoundRect(RectF rect, float rx, float ry, Path.Direction dir)
繪製圓角矩形 - lineTo(float x, float y)
繪製直線 - addPath(Path src)
新增一個新的Path到當前Path - arcTo(RectF oval, float startAngle, float sweepAngle, boolean forceMoveTo)
與addArc
方法相似,但也有區別,下文細述。 - quadTo(float x1, float y1, float x2, float y2)
繪製二次貝塞爾曲線
,其中 (x1,y1)為控制點,(x2,y2)為終點 - cubicTo(float x1, float y1, float x2, float y2, float x3, float y3)
繪製三次貝塞爾曲線
,其中(x1,y1),(x2,y2)為控制點,(x3,y3)為終點
2.rXXX方法
上面的lineTo,MoveTo,QuadTo,CubicTo方法都有與之對應的rXXX
方法:
- rLineTo(float dx, float dy)
- rMoveTo(float dx, float dy)
- rQuadTo(float dx1, float dy1, float dx2, float dy2)
- rCubicTo(float x1, float y1, float x2, float y2, float x3, float y3)
這些方法與之對應的原方法相比,惟一的區別在於:r方法是基於當前繪製開始點的offest,比如當前paint位於 (100,100)處,則使用rLineTo(100,100)
方法繪製出來的直線是從(100,100)到(200,200)的一條直接,由此可見rXXX
方法方便用來基於之前的繪製作連續繪製。
3.Path.op方法
//原型 op(Path path, Path.Op op) //eg path1.op(path2,Path.Op.DIFFERENCE);
此方法用於對兩個Path物件做相應的運算組合(combine),具體的說是根據不同的op
引數及path2引數來影響path1物件,有點類似於數學上的集合運算。請看下面的例子:
Path path1 = new Path(); path1.addCircle(150, 150, 100, Path.Direction.CW); Path path2 = new Path(); path2.addCircle(200, 200, 100, Path.Direction.CW); path1.op(path2, Path.Op.DIFFERENCE); canvas.drawPath(path1, paint1);
效果如下:
通過不斷修改path1.op的第二個引數依次可以得到如下效果:
Path.Op.INTERSECT
效果:
Path.Op.UNION
效果:
Path.Op.REVERSE_DIFFERENCE
效果:
Path.Op.XOR
效果:
總結:
- Path.Op.DIFFERENCE 減去path1中path1與path2都存在的部分;
path1 = (path1 – path1 ∩ path2) - Path.Op.INTERSECT 保留path1與path2共同的部分;
path1 = path1 ∩ path2 - Path.Op.UNION 取path1與path2的並集;
path1 = path1 ∪ path2 - Path.Op.REVERSE_DIFFERENCE 與DIFFERENCE剛好相反;
path1 = path2 – (path1 ∩ path2) - Path.Op.XOR 與INTERSECT剛好相反;
path1 = (path1 ∪ path2) – (path1 ∩ path2)
4.setFillType
設定path的填充模式.網上關於path的FillType的介紹很少,實際上在官方ApiDemos
裡就有個很好的例子:
/** * Created by ghui on 10/25/15. */ public class PathFillTypeView extends View { private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); private Path mPath; public PathFillTypeView(Context context) { super(context); setFocusable(true); setFocusableInTouchMode(true); mPath = new Path(); mPath.addCircle(40, 40, 45, Path.Direction.CCW); mPath.addCircle(80, 80, 45, Path.Direction.CCW); mPath.addCircle(120, 120, 45, Path.Direction.CCW); } private void showPath(Canvas canvas, int x, int y, Path.FillType ft, Paint paint) { canvas.save(); canvas.translate(x, y); canvas.clipRect(0, 0, 160, 160); canvas.drawColor(Color.WHITE); mPath.setFillType(ft); canvas.drawPath(mPath, paint); canvas.restore(); } @Override protected void onDraw(Canvas canvas) { Paint paint = mPaint; paint.setColor(Color.RED); canvas.drawColor(0xFFCCCCCC); canvas.translate(20, 20); paint.setAntiAlias(true); showPath(canvas, 0, 0, Path.FillType.WINDING, paint); showPath(canvas, 160 * 2, 0, Path.FillType.EVEN_ODD, paint); showPath(canvas, 0, 160 * 2, Path.FillType.INVERSE_WINDING, paint); showPath(canvas, 160 * 2, 160 * 2, Path.FillType.INVERSE_EVEN_ODD, paint); } }
效果如下:
(上面的例子在官方ApiDemo的基礎上做了適當的修改)
總結:
所謂填充指的就是填充內部,setFillType
就是用來界定哪裡算內部的演算法。在計算機圖形學中界定一個點是不是在多邊形內部有兩種演算法:
- 非零環繞數規則(Nonzero-rule)
- 奇偶規則(Even–odd rule)
關於這兩種演算法這裡不作詳細介紹。
5.易混淆的方法
1. addArc 與 arcTo
前者指定在某處畫一條弧線,僅此而已,不會受當前paint的位置所影響。而arcTo方法有兩種形式:
- arcTo(RectF oval, float startAngle, float sweepAngle, boolean forceMoveTo)
- arcTo(RectF oval, float startAngle, float sweepAngle)對於第一種形式的方法,若forceMoveTo引數為false,則與第二種形式的方法沒區別,繪製成的最終圖形會受到落筆點的影響;
若forceMoveTo引數值為true,則繪製效果與addArc
方法沒有區別。
//程式碼1 Path path = new Path(); path.moveTo(100, 100); path.addArc(200, 200, 400, 400, 0, 150); canvas.drawPath(path, paint);
程式碼1效果如下圖:
//程式碼2 Path path = new Path(); path.moveTo(100, 100); path.arcTo(200, 200, 400, 400, 0, 150, false); canvas.drawPath(path,paint);
程式碼2效果如下圖:
若將程式碼2中的arcTo方法的引數修改為true則繪製的效果與程式碼1相同。
2. reset 與 rewind
reset
清除path上的內容,重置path到 path = new Path()的初始狀態。
rewind
清除path上的內容,但會保留path上相關的資料結構,以高效的複用。
其它方法
- moveTo(float x,float y)
移動畫筆到 (x,y) 處 - offset(float dx, float dy)
平移當前path,在此path上繪製的任何圖形都會受到影響 - close()
閉合當前路徑 (系統會自動從起點到終點繪製一條直線,使當前路徑閉合) - reset()
重置path,但不會重置fill-type
設定 - rewind()
重置path,但會保留內部資料結構 - set(Path src)
設定新的Path到當前物件 - setLastPoint(float x,float y)
設定當前path的終點 - transform(Matrix matrix)
矩陣變換
相關文章
- 【Android自定義View】繪圖之Path篇(二)AndroidView繪圖
- Android繪製(三):Path結合屬性動畫,讓圖示動起來!Android動畫
- 【Android繪圖】繪圖之基礎篇(一)Android繪圖
- Android的Paint、Canvas和Path基本使用總結AndroidAICanvas
- MPAndroidChart繪製曲線圖、柱狀圖總結Android
- 微信小程式 canvas 繪圖問題總結微信小程式Canvas繪圖
- android截圖方法總結Android
- Android 繪圖——CanvasAndroid繪圖Canvas
- canvas在H5中的繪圖總結CanvasH5繪圖
- 【Android自定義View】繪圖之文字篇(三)AndroidView繪圖
- Android 中 Canvas 繪圖之 Shader 使用圖文詳解AndroidCanvas繪圖
- Android中Canvas繪圖之Shader使用圖文詳解AndroidCanvas繪圖
- Android原生繪圖之炫酷倒數計時Android繪圖
- Android 繪圖基礎Android繪圖
- Android螢幕截圖方式總結Android
- Android UI 繪圖基礎AndroidUI繪圖
- 我要做Android之要點總結Android
- Android總結之Gzip/Zip壓縮Android
- android開發之svg全面總結AndroidSVG
- Android資源res之向量圖完全指南(加SVG-path命令分析)AndroidSVG
- markdown 繪圖利器之granphviz繪圖
- canvas繪圖之鐘表Canvas繪圖
- python中繪圖的圖表和曲線樣式總結(GPT直出)Python繪圖GPT
- Android原生繪圖之讓你瞭解View的運動Android繪圖View
- Android 之 GPU過度繪製與圖形渲染優化AndroidGPU優化
- Android 中 Canvas 繪圖之 PorterDuffXfermode 使用及工作原理詳解AndroidCanvas繪圖
- Android中Canvas繪圖之PorterDuffXfermode使用及工作原理詳解AndroidCanvas繪圖
- Android中Canvas繪圖之MaskFilter圖文詳解(附原始碼下載)AndroidCanvas繪圖Filter原始碼
- Android 截圖與 WebView 長圖分享經驗總結AndroidWebView
- Android利用AChartEngine繪製圖表Android
- Android之SpannableString、SpannableStringBuilder總結AndroidUI
- Android小白之2017年終總結Android
- Android總結之鏈式呼叫(方法鏈)Android
- Android混合開發之WebView使用總結AndroidWebView
- Android UI 之 Tab型別介面總結AndroidUI型別
- 繪製層次結構圖
- python繪圖之matplotlibPython繪圖
- Qt之自繪製餅圖QT