Android繪圖之PathEffect (8)
1 PathEffect 概念
Paint的setPathEffect函式用於設定繪製幾何時的路徑樣式(線條的輪廓),PathEffect從名字就可以知道主要作用於Path路徑,PathEffect是個基類,要實現具體功能需要利用具體的實現類。
PathEffect的實現類包括ComposePathEffect,CornerPathEffect,DashPathEffect,DiscretePathEffect,PathDashPathEffect,SumPathEffect。
各個實現類的作用:
ComposePathEffect和SumPathEffect用於組合兩種路徑效果,
CornerPathEffect設定路徑連線之間的夾角更加平滑,圓潤,
DashPathEffect,PathDashPathEffect虛線效果,動態改變會產生動畫效果,
DiscretePathEffect會產生一種離散效果,具體就是會在路徑上繪製許多雜點。
2 CornerPathEffect:
/**
- Transforms geometries that are drawn (either STROKE or FILL styles) by
- replacing any sharp angles between line segments into rounded angles of
- the specified radius.
- @param radius Amount to round sharp angles between line segments.
*/
將Path的各個連線線段之間的夾角用一種更平滑的方式連線,一般的,通過CornerPathEffect(float radius)指定一個具體的圓弧半徑來例項化一個CornerPathEffect。利用指定半徑圓的角替換多個線段之間的連線點,引數radius就是線段之間的圓角的圓滑程度(連線兩條直線所使用的圓的半徑)。
示例程式碼:
mPaint1 = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint1.setColor(Color.BLUE);
mPaint1.setStrokeWidth(10);
mPaint1.setStyle(Paint.Style.STROKE);
mPath1 = new Path();
mPath1.moveTo(150,250);
mPath1.lineTo(250,320);
mPath1.lineTo(300,300);
mPath1.lineTo(350,350);
mPath1.lineTo(420,270);
mPath1.lineTo(540,370) ;
mPath1.lineTo(560,300);
mPath1.lineTo(650,340);
mPath1.lineTo(750,270);
mPath1.lineTo(850,330);
mPath1.lineTo(950,240);
mPath1.lineTo(1050,290);
mPath1.lineTo(1150,350);
mPath1.lineTo(1250,230);
mPaint2 = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint2.setColor(Color.BLUE);
mPaint2.setStrokeWidth(10);
mPaint2.setStyle(Paint.Style.STROKE);
mPaint2.setPathEffect(new CornerPathEffect(30));
mPath2 = new Path();
mPath2.moveTo(150,550);
mPath2.lineTo(250,620);
mPath2.lineTo(300,600);
mPath2.lineTo(350,650);
mPath2.lineTo(420,570);
mPath2.lineTo(540,670);
mPath2.lineTo(560,600);
mPath2.lineTo(650,640);
mPath2.lineTo(750,570);
mPath2.lineTo(850,630);
mPath2.lineTo(950,540);
mPath2.lineTo(1050,590);
mPath2.lineTo(1150,650);
mPath2.lineTo(1250,530);
canvas.drawPath(mPath1,mPaint1);
canvas.drawPath(mPath2,mPaint2);
canvas.drawRect(200,800,700,1100,mPaint2);
mPaint2.setTextSize(130);
mPaint2.setStrokeWidth(5);
mPaint1.setTextSize(130);
mPaint1.setStrokeWidth(5);
canvas.drawText("歡迎,你好啊!",200,1400,mPaint1);
canvas.drawText("歡迎,你好啊!",200,1700,mPaint2);
從圖中可以明顯看到設定了CornerPathEffect的路徑更加的平滑,對繪製的矩形也有平滑作用,效果類似繪製圓角矩形,對文字沒有效果。
Paint的Style設定為Stroke和FILL_AND_STROKE時對線段和矩形都有圓滑作用,設定為FILL(沒有描邊)時只對直線有作用,對矩形沒有作用。
設定為FILL_AND_STROKE
設定為FILL:
3 DashPathEffect,PathDashPathEffect
/**
* The intervals array must contain an even number of entries (>=2), with
* the even indices specifying the "on" intervals, and the odd indices
* specifying the "off" intervals. phase is an offset into the intervals
* array (mod the sum of all of the intervals). The intervals array
* controls the length of the dashes. The paint's strokeWidth controls the
* thickness of the dashes.
* Note: this patheffect only affects drawing with the paint's style is set
* to STROKE or FILL_AND_STROKE. It is ignored if the drawing is done with
* style == FILL.
* @param intervals array of ON and OFF distances
* @param phase offset into the intervals array
*/
DashPathEffect將Path的線段虛線化,建構函式為DashPathEffect(float[] intervals, float offset),intervals:是間隔陣列,作為實線,虛線的開關,設定虛線實線的長度,該陣列的length必須大於等於2,如果設定兩個引數就按兩個引數迴圈,第一個引數為“實線長度”,第二個引數為“虛線長度”後面依次迴圈,還可以設定多個引數(如果是奇數個引數,最後一個引數無效,具體沒仔細驗證,如果用到大家仔細求證下)。這個PathEffect只對設定Stroke 或者FILL_AND_STROKE 樣式的Paint有效,Style為FILL時則失效。
phase為繪製時的偏移量,改變這個值可以實現類似虛實交換的動畫效果,phase改變的越大,則動畫效果越明顯。
程式碼示例:
float[] array1 = {50,20};
mPaint2.setPathEffect(new DashPathEffect(array1, 5));
動態修改phase:
PathDashPathEffect
PathDashPathEffect功能類似DashPathEffect,但是它是利用特定的Path形狀繪製路徑,只有Paint的style是 STROKE or STROKE_AND_FILL時起作用,strokeWidth不影響結果。
建構函式
PathDashPathEffect(Path shape, float advance, float phase,Style style)
引數說明:
shape:路徑上的形狀,Path內部新增路徑形狀,類似矩形,三角形等,
advance :兩個形狀間的距離,如果具體夠大可以放好多形狀,如果距離過小,只能放置一個形狀
phase:偏移距離,和DashPathEffect一樣,可以實現動畫效果。
style是每個形狀的排列方式)(特別是在轉角處),共有三種樣式,
TRANSLATE(0), //平移每個位置的形狀,就是改變印章的位置。
ROTATE(1), //繞著每個形狀的中心旋轉
MORPH(2); //每個點變換形狀, 並把直線變成曲線(在轉角處)
ROTATE的情況下,線段連線處的圖形轉換以旋轉到與下一段移動方向相一致的角度進行轉轉,MORPH時圖形會以發生拉伸或壓縮等變形的情況與下一段相連線,TRANSLATE時,圖形會以位置平移的方式與下一段相連線。
shape是有寬高的,不同的style形狀的繪製方式不同,所以如果advance間距過小,所有的形狀都會繪製在一起,就無法看出具體的形狀了,所以設定advance時要儘量大一點。
Path tPath = new Path();
tPath.addRect(0f,0f,20f,30f, Path.Direction.CW);
mPaint1.setPathEffect(new PathDashPathEffect(tPath,50,50,PathDashPathEffect.Style.ROTATE));
mPaint2.setPathEffect(new PathDashPathEffect(tPath,50,50,PathDashPathEffect.Style.TRANSLATE));
mPaint3.setPathEffect(new PathDashPathEffect(tPath,50,50,PathDashPathEffect.Style.MORPH));
在路徑上繪製矩形,分別設定不同style:
如果設定advance設定過小:
Path tPath = new Path();
tPath.addRect(0f,0f,20f,30f, Path.Direction.CW);
mPaint2.setPathEffect(new PathDashPathEffect(tPath,20,50,PathDashPathEffect.Style.TRANSLATE));
mPaint1.setPathEffect(new PathDashPathEffect(tPath,20,50,PathDashPathEffect.Style.ROTATE));
mPaint3.setPathEffect(new PathDashPathEffect(tPath,20,50,PathDashPathEffect.Style.MORPH));
設定advance過小,雖然看著不好看,但是可以看出style的效果,MORPH通過變形使線段更平滑,TRANSLATE靠平移,所有的形狀都不會變形且形狀整體在一條線上,ROTATE利用旋轉,跟平移有點相似,但是隻有旋轉中心在一條線上。
5 DiscretePathEffect
這個類的作用術語稱為離散路徑,使得在原來路徑的基礎上發生打散效果。
建構函式:
DiscretePathEffect(float segmentLength,float deviation)
segmentLength指定切割的段長,
deviation指定可偏移的距離(離原來的點),越大可偏移的距離越大。
將路徑分隔成定長的線段,然後將每條線段隨機偏移一段位置,就會產生打散的效果。
mPaint1.setPathEffect(new DiscretePathEffect(10,10));
mPaint2.setPathEffect(new DiscretePathEffect(10,30));
mPaint3.setPathEffect(new DiscretePathEffect(20,10));
segmentLength越長,線段被切割的分成的段越少,離散的點也就越少,
deviation 越大,線段偏移的越厲害,看著也不規則(毛刺比較多),
上面的例項程式碼mPaint1和mPaint2 segmentLength相同,deviation不同,
mPaint1和mPaint3 deviation相同,segmentLength不同。
6 ComposePathEffect與SumPathEffect
都是用來組合兩個PathEffect的但效果不同。
ComposePathEffect需要兩個PathEffect引數來構造一個例項,
/**
* Construct a PathEffect whose effect is to apply first the inner effect
* and the the outer pathEffect (e.g. outer(inner(path))).
*/
ComposePathEffect(PathEffect outerpe, PathEffect innerpe)
作用是先將outerpe的效果作用到路徑上,然後再在變換後的路徑上新增innerpe效果
SumPathEffect:
/**
* Construct a PathEffect whose effect is to apply two effects, in sequence.
* (e.g. first(path) + second(path))
*/
public SumPathEffect(PathEffect first, PathEffect second) ;
需要兩個PathEffect作為引數,但與ComposePathEffect不同的是,作用是會分別對兩個引數的效果各自獨立進行表現,然後將兩個效果簡單的重疊在一起顯示出來。
CornerPathEffect cornerPathEffect = new CornerPathEffect(30);
float[] array1 = {50,20};
DashPathEffect dashPathEffect = new DashPathEffect(array1, phase);
ComposePathEffect composePathEffect = new ComposePathEffect(dashPathEffect, cornerPathEffect);
SumPathEffect sumPathEffect = new SumPathEffect(dashPathEffect, cornerPathEffect);
mPaint1.setPathEffect(composePathEffect);
mPaint2.setPathEffect(sumPathEffect);
mPaint1先圓角,在虛線化。
mPaint2 圓角和虛線疊加效果。