LChart 完全解析 以面向对象的思维来绘制图表

LChart

网友的使用经验

简友gton的LChart中的折线图在项目中的简单使用

漂亮

正文前言

核心:面向对象
面向对象这个名词,对于我们广大的程序员来说,应该是再熟悉不过了。

多数人只是停留在熟悉名词这个阶段,
在遇到一些问题的时候,却不知道采用面向对象的思维去解决它。
当我们跳出老旧的思维枷锁,很多问题也就迎刃而解了 :)

LChart的产生
我们在项目中,经常使用图表来展示数据,这样很形象直观。在Android中,我们大多会使用如下常用的图表库:

  1. MPAndroidChart (展示丰富,性能好,但是使用较为麻烦,源码难懂,定制起来很困难)
  2. HelloCharts(使用较为简单,数据量较大的时候,性能差)

以上的图表库,都有着各自的优缺点,项目对图表要求不高的话,使用他们完全没问题。但是要求高的话,这就麻烦了,最后的解决方法是自己重写一个图表 :(

既然项目的图表要求高,那咱就自己写个图表库呗:LChart就是这么产生的。
项目地址:https://github.com/linheimx/LChart

对于LChart,我是以面向对象的方式来分解它,绘制它的,整体来说思路清晰,易于使用。
也许LChart也不适应于你的项目,但我想在这篇文章里面授之以渔,给你带来一定的帮助。

LChart的组织结构

面向图谱中的对象

知道了一个东西由哪几个部分组成,我们内心对这个东西就有数了(不一定了如指掌,有了大概的轮廓也就可以啦)

我们先看一辆自行车的组成结构(帮助我们寻找灵感)

Paste_Image.png

从上图,我们大致看出自行车有如下结构:

  1. 车轮子
  2. 坐垫
  3. 车把

对比自行车的结构,那我们的LChart由那几部分组成呢?

基本折线图

组成部分

从上面基本的折线图,我们大致可以看出LChart由如下几个部分组成:

  1. 轴线
  2. 高亮
  3. 折线

限于篇幅,我只直观的展示LChart的中3个主要部分,总体上有如下几个部分:

关键组成部分

针对以上部分,在我们的代码中,对应为相关的类,这些类封装了相关的信息:


有了这几个对象信息,我们就该考虑绘图了。

根据对象信息进行绘制

LChart是一个自定义View,通过view中的Canvas来进行绘制。

我们设计了几个render来负责绘制LChart的几个关键部分。
每个render都有着自己的职责,它向我们封装的对象 Axis,Line等来获取信息,进行各种各样的绘制。

绘制结构

render的体系结构如下:

各种render

LChart的映射:将数据展现到屏幕上

我们的目的是将数据绘制到屏幕上,那么数据和屏幕之间有什么关系呢?

  1. 数据是有范围的:表现在x方向上范围和y方向上的范围。
  2. 明确绘制图谱在手机屏幕上的的区域

二者之间的联系是等比例关系,如下图:


等比例关系

在LChart中,我用MappingManager来维护管理这个关系:

考虑到对图谱的缩放,移动,现将数据视图具体分为:

  RectD _maxViewPort;  //当前可见的数据范围
  RectD _currentViewPort; //最大的数据范围

MappingManager中具体的数值与像素转换的代码:

映射

知道了数据与手机屏幕中绘图区域的关系。
随便给你一个数据,根据这个关系,你就可以知道这个点在屏幕中的位置了,知道了位置,你用canvas就随便画喽。

LChart的性能优化

1. 减少内存分配
考虑到onDraw()的频繁调用,尽量的减少内存分配,也就是少new对象。
假设一条数据线上有非常多的点,对每个点都进行映射到屏幕位置的计算,势必要分配很多对象。考虑到是在单个线程:主线程绘制,我采用了单例来保留处理前后的结果。(MpAndroidChart采用对象池来处理内存的分配问题)


2. 减少不必要的绘制
若你把图谱放大:

上图中:蓝色区域为数据的范围,黑色的区域为屏幕上图谱的范围。
很明显,我们只能看到,手机屏幕中的图谱区域显示的部分数据视图。
所以在绘图的时候,只选择绘制可见的数据范围是比较理智的。

3. 减少计算
计算是耗时的,当你的计算非常耗时的时候,图谱就显的非常卡顿,所以减少计算是非常有必要的。
有这样的一种情况:图谱上有很多点,当你点击一个点的时候,要显示这个点的信息。怎么确定是你点击的那个点呢?一般来说是要遍历你图上所有的点,每个点距离你点击的距离更近,那个点就是你想要的点了(HelloCharts是这么处理的),但经验证,这样的计算是非常耗时的,点数稍微一多,谱图就卡顿了。LChart采用二分查找法,快速的命中你想要的点,大大减少计算上的耗时,效果是很理想的。
代码贴上来占据篇幅,地址在项目的data/line.java 这个类下,如有兴趣,自行查看

最后但不是最后

关于LChart,关键的几个地方我大致说了下,详细的使用参见github上的demo。
也许你仍有很多疑惑,So,提出来,后续我也会逐渐的写出来,完善它。

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容