Highcharts是一个用纯JavaScript编写的一个图表库,能够很简单便捷的在web网站或是web应用程序添加有交互性的图表,并且免费提供给个人学习、个人网站和非商业用途使用(摘自百度百科)。另外HighCharts还有很好的兼容性,能够完美支持当前大多数浏览器,现在官方的最新版本为Highcharts-4.0.4。
问题来源
我在很早一篇使用PhantomJs对网页截图中就提到了Highcharts,那时用它在网页上绘制图表,然后用Phantomjs去截图,因为我想让服务端只负责生成数据,而让客户端去生成图表及图片。在那个项目中,所有的图表都是通过Ajax取来数据后,再调用Highcharts生成图表的。而常用的图表类型也无非那几种,每次都要先Ajax请求,然后构造highcharts的一堆配置参数。
1 | $.post( |
因为服务端只返回series
里要求的数据格式,尽量与highcharts的配置降低耦合,所以前台每次想要生成一个图表都要写一段上面类似的代码。因此我觉得有必要对highcharts做简单的包装,让它更加简单的配合Ajax和chart type。
接口设计
我们希望可以这样使用chart
1 | var chart1 = new AjaxChart({ |
传入图表的container元素和chart type,传入ajax url和params,且这里的params既可以是个值,也可以是个function。最后通过refresh()
接口生成图表。这样可以把chart1.refresh()
放到某个按钮的click
或change
事件里,以实现根据用户的选择动态刷新图表。
全局配置
针对几种常用的图表类型,折线图、饼图、柱状图、区域图,我们分别为此定义默认的Highcharts配置属性。
1 | var CHART_OPTIONS = { |
AjaxChart构造
根据上面的接口设计,我们可以写出这样的代码框架。
1 | var AjaxChart = function(config){ |
refresh
负责获取用户传入的参数,并请求Ajax,返回时再构造出Highcharts对象。这里我们需要写两个帮助方法。
1.获取用户参数
既然我们前面说“params既可以是个值,也可以是个function”,因此要写一个转化的过程,如果是function,则对function求值。
1 | AjaxChart.prototype._getAjaxParams = function(){ |
2.构造图表
这里根据前面的全局配置来构造Highcharts对象,参数result
是服务端返回的数据(即Highcharts配置里的series
)。
1 | AjaxChart.prototype._updateChart = function(result){ |
3.有了上面两个方法,refresh
就好办了。
1 | AjaxChart.prototype.refresh = function(){ |
注意这里有句var that = this;
,熟悉回调的朋友肯定对此不陌生,这是为了保存当前的context,因为在Ajax的回调函数执行时,this会指向xmlhttpresponse
,而不是当前的AjaxChart
对象。
扩展1:支持本地数据刷新
使用场景:当一个表格已经请求好了数据,并放在table
元素中了。此时图表元素需要做的就是根据表格中的数据生成chart,而并不需要再次向服务器请求数据。
我们为上面的refresh
方法添加一个参数。
1 | AjaxChart.prototype.refresh = function(chartData){ |
这里chartData
就是Highcharts配置里series
的格式,这样可以在本地生成符合格式的数据,然后直接refresh
。chartData
的格式可以参考ajaxdata.json或ajaxdata2.json。并且这里对ajax返回结果也做了一些判断,以支持JSON字符串或JSON对象。
扩展2:支持图表点击事件
使用场景:在柱状图或饼图中,经常需要点击一块时,能够得到相应的联动。比如在图上点击了一块,相应的表格数据过滤了,或是另一个图表也随之更新了等等。
还得为refresh
方法添加参数,干脆添加一个对象参数。
1 | AjaxChart.prototype.refresh = function(opts){ |
同时_updateChart
方法也得再添加一个参数。
1 | AjaxChart.prototype._updateChart = function(result, handler){ |
这里的handler
中可以获取到两个参数,一个是x坐标的分类值,一个是y坐标的值。应用层里可以这样写。
1 | chart1.refresh({ |
扩展3:支持自定义回调
使用场景:跟上面的点击事件差不多,只是这里在图表更新完成后,需要通知某些元素做出相应的处理。
代码也跟上面差不多,再为refresh
方法添加个参数。
1 | AjaxChart.prototype.refresh = function(opts){ |
如果需要支持更多的自定义事件,最好使用观察者模式,为AjaxChart.prototype
添加一个on
和fire
方法,并在对象中维持一个handlers
对象。这里就不给出代码了,可参考链接中的内容很容易写出类似的代码。
最后demo
参考资料
Highcharts官方网站:www.highcharts.com 中文网:www.hcharts.cn