Gtihub傳送門 |
---|
在個人
Github
開源庫中,今天剛寫好了一個餅圖的繪製,這裏主要就是對餅圖繪製的一個講解了。ios
以前咱們講過了一個Path
,可是若是全用Path
去實現,也不是說不可以實現,可是並不適用於不少的場景狀況。git
這裏的話,咱們主要講的就是關於Canvas
的使用了。以前咱們在Path
中用到過這樣的一個函數moveTo
,也就是把路徑從當前的位置移動到新的座標上。那咱們的Canvas
是否有這樣的功能呢?github
天然是有的了,這裏直接做出一個解答,他的函數就是translate
,可是有一點要注意!!!這個函數是一個相對移動,而不是絕對移動。canvas
canvas?.translate(60f, 80f)
paint?.let { canvas?.drawCircle(0f, 0f, 100f, it) }
canvas?.translate(60f, 80f)paint?.color = Color.BLUE
paint?.let { canvas?.drawCircle(0f, 0f, 100f, it) }
複製代碼
上述就是實現代碼以及一個貼圖了。你能夠直觀的感覺到這個移動實際上是基於當前的基礎來完成的。可是讀者會說了,這種效果徹底可讓我經過Path
來完成啊,不必經過Canvas
,ok,確實能夠,你也能夠經過Path
來實現。函數
可是難點如今纔來,下圖的樣式該怎麼實現??工具
在知道怎麼寫代碼以前,那咱們要知道確定是他的組成成分究竟是什麼了。佈局
若是讓咱們直接去獲取絕對座標,而後進行繪製,那是否是會很是麻煩呢?因此這裏要引入一個Canavs
的操做方法。post
Canvas
操做在使用以前須要注意,畫布是須要保存的,否則畫布將不斷的保留上一次的狀態進行繪製,那總體就會呈現一種疊加混亂的局面。而這個方法就是save()
和restore()
的成對使用。學習
for (i in 0..2) {
canvas?.save()
paint?.color = Color.BLUE
canvas?.translate(60f, 80f)
canvas?.scale(0.5f, 0.5f)
paint?.let { canvas?.drawCircle(0f, 0f, 100f, it) }
canvas?.restore()
}
複製代碼
使用前 | 使用後 |
---|---|
![]() |
![]() |
你能夠把這個操做理解爲畫布歸位,或者說畫布重置。而這個重置對應的就是保存了save()
以前的操做過程。ui
Scale
這個效果再也不贅述了。
Rotate
和其餘的都是同樣的會有兩種畫布的操做函數
canvas?.save()
paint?.color = Color.BLUE
canvas?.translate(60f, 80f)
canvas?.rotate(45f)
// 以自身中心做爲圓點旋轉
// canvas?.rotate(45f,30f, 40f)
paint?.let { canvas?.drawRect(0f, 0f, 100f, 100f, it) }
canvas?.restore()
複製代碼
餅圖的實現其實就是基於這個函數來完成的。
Shew
和其餘的不一樣了,他並再也不經過咱們的座標圓心,而是對標咱們X
和Y
軸
canvas?.save()
paint?.color = Color.BLUE
canvas?.translate(60f, 80f)
canvas?.skew(0f, 1f)
paint?.let { canvas?.drawRect(0f, 0f, 100f, 100f, it) }
canvas?.restore()
複製代碼
傳入的數據其實就是分別與X
和Y
軸的正切值,經過截圖工具,你可以明顯的發現這個問題。畫了綠色框框的部分,你能夠看到的是正好一個45度的大小。
經過畫圖你也能夠這樣理解,就是Y
軸順時針方向旋轉45度。
基本就是以上問題,問題1我已經作出來回答,後續兩個問題將一個個做出解釋。
在個人代碼中,其實分爲兩塊,一是圓弧,一是介紹,這也是他們的繪製順序了。可是須要考慮一個問題:介紹線的位置肯定?
這個問題你須要看一下個人圖例了,你有沒有注意到,個人介紹線,好像都是關於單個圓弧居中的呢?
那咱們的方案其實就來了,上面咱們講到過了什麼?Rotate
還記得這個函數嘛!!經過數據運算,有了每一個圓弧的大小,那咱們還不能去進行繪製嘛?不就是先劃線,再旋轉嗎。而後旋轉就是這樣的一個公式要去計算。
// 旋轉角度 = 前面的弧度 + 當前弧度的一半
private fun getRatioSum(j: Int): Float {
var sum = 0f
for (i in 0 until j) {
sum += mRatios!![i]
}
return sum
}
private fun getRatioHalfSumDegrees(j: Int): Float {
var sum = getRatioSum(j)
sum += mRatios!![j] / 2
return sum * 360
}
複製代碼
跟前面的圓弧同樣,可是是一個個圓弧來組成圓,那這個時候,就是要知道前面的弧度,而後對當前的弧度的計算,也就是掃過的區間進行計算了。
private fun drawArc(canvas: Canvas) {
val drawArc = 360 * scale
for (i in mRatios!!.indices) {
mArcPaint?.color = mArcColors!![i]
mArcPaint?.let {
canvas.drawArc(
arcRect!!,
getRatioSum(i) * drawArc,
mRatios!![i] * drawArc,
true,
it
)
}
}
}
複製代碼
基本上就是靠上述的兩個來完成的,是否是仍是比較簡單的呢。沖沖衝,Demo
抄起來,你就有一份本身的餅圖繪製了。
以上就是個人學習成果,若是有什麼我沒有思考到的地方或是文章內存在錯誤,歡迎與我分享。
相關文章推薦: