LChart 完全解析 以面向?qū)ο蟮乃季S來繪制圖表

LChart

網(wǎng)友的使用經(jīng)驗

簡友gton的LChart中的折線圖在項目中的簡單使用

漂亮

正文前言

核心:面向?qū)ο?/strong>
面向?qū)ο筮@個名詞,對于我們廣大的程序員來說,應(yīng)該是再熟悉不過了。

多數(shù)人只是停留在熟悉名詞這個階段,
在遇到一些問題的時候,卻不知道采用面向?qū)ο蟮乃季S去解決它。
當(dāng)我們跳出老舊的思維枷鎖,很多問題也就迎刃而解了 :)

LChart的產(chǎn)生
我們在項目中,經(jīng)常使用圖表來展示數(shù)據(jù),這樣很形象直觀。在Android中,我們大多會使用如下常用的圖表庫:

  1. MPAndroidChart (展示豐富,性能好,但是使用較為麻煩,源碼難懂,定制起來很困難)
  2. HelloCharts(使用較為簡單,數(shù)據(jù)量較大的時候,性能差)

以上的圖表庫,都有著各自的優(yōu)缺點,項目對圖表要求不高的話,使用他們完全沒問題。但是要求高的話,這就麻煩了,最后的解決方法是自己重寫一個圖表 :(

既然項目的圖表要求高,那咱就自己寫個圖表庫唄:LChart就是這么產(chǎn)生的。
項目地址:https://github.com/linheimx/LChart

對于LChart,我是以面向?qū)ο蟮姆绞絹矸纸馑L制它的,整體來說思路清晰,易于使用。
也許LChart也不適應(yīng)于你的項目,但我想在這篇文章里面授之以漁,給你帶來一定的幫助。

LChart的組織結(jié)構(gòu)

面向圖譜中的對象

知道了一個東西由哪幾個部分組成,我們內(nèi)心對這個東西就有數(shù)了(不一定了如指掌,有了大概的輪廓也就可以啦)

我們先看一輛自行車的組成結(jié)構(gòu)(幫助我們尋找靈感)

Paste_Image.png

從上圖,我們大致看出自行車有如下結(jié)構(gòu):

  1. 車輪子
  2. 坐墊
  3. 車把

對比自行車的結(jié)構(gòu),那我們的LChart由那幾部分組成呢?

基本折線圖

組成部分

從上面基本的折線圖,我們大致可以看出LChart由如下幾個部分組成:

  1. 軸線
  2. 高亮
  3. 折線

限于篇幅,我只直觀的展示LChart的中3個主要部分,總體上有如下幾個部分:

關(guān)鍵組成部分

針對以上部分,在我們的代碼中,對應(yīng)為相關(guān)的類,這些類封裝了相關(guān)的信息:


有了這幾個對象信息,我們就該考慮繪圖了。

根據(jù)對象信息進(jìn)行繪制

LChart是一個自定義View,通過view中的Canvas來進(jìn)行繪制。

我們設(shè)計了幾個render來負(fù)責(zé)繪制LChart的幾個關(guān)鍵部分。
每個render都有著自己的職責(zé),它向我們封裝的對象 Axis,Line等來獲取信息,進(jìn)行各種各樣的繪制。

繪制結(jié)構(gòu)

render的體系結(jié)構(gòu)如下:

各種render

LChart的映射:將數(shù)據(jù)展現(xiàn)到屏幕上

我們的目的是將數(shù)據(jù)繪制到屏幕上,那么數(shù)據(jù)和屏幕之間有什么關(guān)系呢?

  1. 數(shù)據(jù)是有范圍的:表現(xiàn)在x方向上范圍和y方向上的范圍。
  2. 明確繪制圖譜在手機(jī)屏幕上的的區(qū)域

二者之間的聯(lián)系是等比例關(guān)系,如下圖:


等比例關(guān)系

在LChart中,我用MappingManager來維護(hù)管理這個關(guān)系:

考慮到對圖譜的縮放,移動,現(xiàn)將數(shù)據(jù)視圖具體分為:

  RectD _maxViewPort;  //當(dāng)前可見的數(shù)據(jù)范圍
  RectD _currentViewPort; //最大的數(shù)據(jù)范圍

MappingManager中具體的數(shù)值與像素轉(zhuǎn)換的代碼:

映射

知道了數(shù)據(jù)與手機(jī)屏幕中繪圖區(qū)域的關(guān)系。
隨便給你一個數(shù)據(jù),根據(jù)這個關(guān)系,你就可以知道這個點在屏幕中的位置了,知道了位置,你用canvas就隨便畫嘍。

LChart的性能優(yōu)化

1. 減少內(nèi)存分配
考慮到onDraw()的頻繁調(diào)用,盡量的減少內(nèi)存分配,也就是少new對象。
假設(shè)一條數(shù)據(jù)線上有非常多的點,對每個點都進(jìn)行映射到屏幕位置的計算,勢必要分配很多對象??紤]到是在單個線程:主線程繪制,我采用了單例來保留處理前后的結(jié)果。(MpAndroidChart采用對象池來處理內(nèi)存的分配問題)


2. 減少不必要的繪制
若你把圖譜放大:

上圖中:藍(lán)色區(qū)域為數(shù)據(jù)的范圍,黑色的區(qū)域為屏幕上圖譜的范圍。
很明顯,我們只能看到,手機(jī)屏幕中的圖譜區(qū)域顯示的部分?jǐn)?shù)據(jù)視圖。
所以在繪圖的時候,只選擇繪制可見的數(shù)據(jù)范圍是比較理智的。

3. 減少計算
計算是耗時的,當(dāng)你的計算非常耗時的時候,圖譜就顯的非常卡頓,所以減少計算是非常有必要的。
有這樣的一種情況:圖譜上有很多點,當(dāng)你點擊一個點的時候,要顯示這個點的信息。怎么確定是你點擊的那個點呢?一般來說是要遍歷你圖上所有的點,每個點距離你點擊的距離更近,那個點就是你想要的點了(HelloCharts是這么處理的),但經(jīng)驗證,這樣的計算是非常耗時的,點數(shù)稍微一多,譜圖就卡頓了。LChart采用二分查找法,快速的命中你想要的點,大大減少計算上的耗時,效果是很理想的。
代碼貼上來占據(jù)篇幅,地址在項目的data/line.java 這個類下,如有興趣,自行查看

最后但不是最后

關(guān)于LChart,關(guān)鍵的幾個地方我大致說了下,詳細(xì)的使用參見github上的demo。
也許你仍有很多疑惑,So,提出來,后續(xù)我也會逐漸的寫出來,完善它。

項目地址:https://github.com/linheimx/LChart,歡迎star,issue : )

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容