最近我一直在做数据可视化的前端工作,我用的最多的绘图工具是d3。d3有点像photoshop,功能很强大,例子也很多,但是学习成本也不低,做项目是需要较大人力投入的。3月底由在亚马逊工作的同学介绍下使用了一下echart,一个由百度前端发起的canvas国产类库(官网:http://echarts.baidu.com/index.html)。这个echart其实是在canvas类库zrender的基础上做的主题图库,优点有数据驱动,图例丰富,功能强大,支持数据拖拽重计算,数据区域漫游,全中文文档非常过瘾。跟同样是国产的前端脚手架fis一样(官网http://fis.baidu.com/),都是诚意满满的国产套餐,体现了现今国内不俗的前端开发实力。使用它们的感觉就像想自己做个平板电脑,去华强北一转,主板、CPU、屏幕等各种套餐一订购,东西就哗哗地组装起来了。极其高效,非常适合商业项目开发。而且,即使是为了研究,用这些也可以打一个很好的基础。

Echart图表库层次关系

1.引入目录

废话不多说了,看到好东西,第一步是从github上把相关文件全下下来,然后到build目录翻箱倒柜把东西找齐。新建目录如下:

echarts-1.3.8
—-zrender   //zrender是echart依赖的绘图库,官网要求下载,但是目前我的程序中并没有直接引用它,可以说普通情况下echart可以自己独立运行
——–zrender.js
—-excanvas_r3 //excanvas是实现IE7,8兼容canvas绘图的利器,实现了大部分canvas的API,在绘图方面其核心是通过IE的VML去实现的,效率较低
——–excanvas.js
—-echarts.js  //echarts主程序,包含除map以外所有的主题图库。注意这个是压缩过的,并且只能通过requirejs或者esl.js模块化加载;想用标签或sea.js加载请用echarts-plain.js
—-echarts-orginal.js  //没有压缩过的echarts.js
—-echarts-map.js  //echarts的map主题图库

2.在自己的项目中实现其demo

这个echart是百度前端做的,他们推荐使用模块式开发。好在我之前的项目,就是采用requirejs + angularjs开发的。所以引入比较容易。

首先,在requirejs的入口配置文件main.js里加上echart:

require.config({baseUrl:'application/views/frontEnd/build/',paths:{//这里省略若干配置信息...//echart及其组件,echarts: 'lib/echarts-1.3.8/echarts',"echarts/chart/line": 'lib/echarts-1.3.8/echarts',"echarts/chart/bar": 'lib/echarts-1.3.8/echarts','echarts/chart/scatter': 'lib/echarts-1.3.8/echarts','echarts/chart/k': 'lib/echarts-1.3.8/echarts','echarts/chart/pie': 'lib/echarts-1.3.8/echarts','echarts/chart/radar': 'lib/echarts-1.3.8/echarts','echarts/chart/map': 'lib/echarts-1.3.8/echarts','echarts/chart/chord': 'lib/echarts-1.3.8/echarts','echarts/chart/force': 'lib/echarts-1.3.8/echarts',zrender: 'lib/echarts-1.3.8/zrender/zrender'},priority:['angular']//,urlArgs:'v=1.1'
});

然后,在要引入echart的具体页面控制js文件里,加载相关依赖。

define(['echarts','echarts/chart/pie','d3'], function (ec) {function common_chart_staff_assess_ctrl($http, $scope) {// angularjs的控制器....}}return common_chart_staff_assess_ctrl;
});

以上两步,熟悉dojo或者requirejs的朋友应该都毫无压力,但是还是有很多朋友没用过这些,所以还是有必要说一下的。

接着就是把官网的例子放在自己的页面里实现。这里我选取了一个特别的千层饼图,点击这里去官网查看原图。

那么我们把例子里的静态数据(option对象)搬运到我们自己的JS文件中,然后仿照官网的例子写一个渲染&刷新函数

//渲染&刷新函数$scope.refresh = function(option,isBtnRefresh){if (isBtnRefresh) {needRefresh = true;if (needRefresh) {myChart.showLoading();setTimeout($scope.refresh(option), 500);}return;}needRefresh = false;if (myChart && myChart.dispose) {myChart.dispose();}myChart = ec.init(domMain);window.onresize = myChart.resize;myChart.setOption(option, true);domMessage.innerHTML = '';};//测试数据
$scope.option = {title : {text: '浏览器占比变化',subtext: '纯属虚构',x:'right',y:'bottom'},tooltip : {trigger: 'item',formatter: "{a} <br/>{b} : {c} ({d}%)"},legend: {orient : 'vertical',x : 'left',data:['Chrome','Firefox','Safari','IE9+','IE8-']},toolbox: {show : true,feature : {mark : {show: true},dataView : {show: true, readOnly: false},restore : {show: true},saveAsImage : {show: true}}},calculable : false,series : (function(){var series = [];for (var i = 0; i < 30; i++) {series.push({name:'浏览器(数据纯属虚构)',type:'pie',itemStyle : {normal : {label : {show : i > 28},labelLine : {show : i > 28, length:20}}},radius : [i * 4 + 40, i * 4 + 43],data:[{value: i * 128 + 80,  name:'Chrome'},{value: i * 64  + 160,  name:'Firefox'},{value: i * 32  + 320,  name:'Safari'},{value: i * 16  + 640,  name:'IE9+'},{value: i * 8  + 1280, name:'IE8-'}]})}series[0].markPoint = {symbol:'emptyCircle',symbolSize:series[0].radius[0],effect:{show:true,scaleSize:12,color:'rgba(250,225,50,0.8)',shadowBlur:10,period:30},data:[{x:'50%',y:'50%'}]};return series;})()
};
setTimeout(function(){var _ZR = myChart.getZrender();// 补充千层饼_ZR.addShape({shape : 'text',style : {x : _ZR.getWidth() / 2,y : _ZR.getHeight() / 2,color: '#666',text : '恶梦的过去',textAlign : 'center'}});_ZR.addShape({shape : 'text',style : {x : _ZR.getWidth() / 2 + 200,y : _ZR.getHeight() / 2,brushType:'fill',color: 'orange',text : '美好的未来',textAlign : 'left',textFont:'normal 20px 微软雅黑'}});_ZR.refresh();
}, 2000);

然后在页面上找个div,显示echart就可以了。

不过请注意一定要给这个div设置宽度高度,否则图显示不出来不要怪我。

<section class="span12">     <div id="graph" class="graph chart-area" style="height:500px"></div>
</section>

我这里用了bootstrap,宽度是按栅格系统的百分比值变化的,所以上面的代码中没有指定宽度。最后调试调试,没有问题我这里也可以显示。

3.定制

当然,仅仅停留在引用别人的例子是不能让我满意的。

首先,要进行数据绑定。

这里细分为3步:

  1. 分析数据格式(就是分析option对象,这一步需要注意把后台获取的数据和样式信息分开。故而我在代码里设置了$scope.option对象存储默认的样式配置信息,之后ajax获取数据后将二者再extend即可。)
  2. 在后台组装相应的数据(根据不同需求而异,我这里只取数值信息,不多言)
  3. 前台ajax获取真实数据(这一点相信大家都很纯熟,不过我的代码里是使用angularjs封装过的$.post对象来做到这一点的)
  4. //设置真实数据格式
    $scope.default_option = {title : {text: '故障类型时序变化年轮图',subtext: '本图由内向外展示了各种故障类型的出现频率所占百分比,及其随时间变化的规律',x:'right',y:'bottom'},tooltip : {trigger: 'item',formatter: "{a} <br/>{b} : {c} ({d}%)"},legend: {orient : 'vertical',x : 'left',selected: $scope.faultnameSelected,data:$scope.faultname},toolbox: {show : true,feature : {mark : true,dataView : {readOnly: false},restore : true,saveAsImage : true}},calculable : false,series : {}
    };$scope.ajaxChartData = function(dataname){ myChart.showLoading({text: '正在努力的读取数据中...',    //loading话术});  $http.post("index.php/main/readfaultnum", null).success(function(alldata){console.log(alldata);var option = $scope.default_option;option.series = $scope.setData(alldata);$scope.refresh(option,true);$scope.order = dataname;myChart.hideLoading();    }).error(function(){domMessage.innerHTML = '网络故障,获取数据失败';});};
    

5.进一步定制

虽然我使用了官网的例子实现了需求,但是我还有些自己的想法。

官网的千层饼图中,代表时间的年轮宽度是固定的。但是我们从后台读取的数据(以月为颗粒度)在时间上是变化的,随着系统使用时间增长而增长。这就导致一个问题,就是在只有一个月时,年轮只有小小一个,有50个月时,年轮多到超过了显示范围。这样很不美观,并且丧失了一定的可用性。

我决定要对其进行优化。当使用月份很少导致数据很少的时候,年轮会很宽;当使用月份很多导致数据很多的时候,年轮会很细——这样就可以同时避免数据量小的时候不美观和数据量大的时候丧失可用性的问题了。当然,如果数据量过大,年轮就会过细,同样会丧失可用性。因此我们要设置一个最大数据量的阈值,把超过的部分砍掉。

解决方案就是要对根据数据量对年轮宽度进行缩放,也就是使用比例尺函数。在echart里我暂时没有找到这样的比例尺函数。当然,线性比例尺很简单,函数可以自己写。但是其他类型的比例尺缩放就稍微要一些技巧了。好在之前我一直是使用d3类库来做可视化的,我知道d3里有这样的比例尺函数可以很容易地解决我的问题。那就是d3.scale对象,其中包含线性比例尺、平方比例尺、指数比例尺、集合比例尺,完全可以满足需要。我可以从开源的d3库中把比例尺函数抽取出来,也引入到这个页面。根据实际数据的测试结果,我选择了平方比例尺。那么接下来就很好写了:

var maxTime = 36; //本千层饼图最多显示60个月的数据(最多显示60个圈)
//原始数据的加工工厂函数
$scope.setData = function(data){//这是D3的平方比例尺函数,用于根据数据大小缩放环的宽度var rScale = d3.scale.sqrt().domain([maxTime, 1]).range([3, 30]).nice();console.log(rScale(1), rScale(12), rScale(36))//如果数据量超过60(即有60个月),则删除60个月之前的数据,只显示最近60个月的内容if(data.length > maxTime){data.splice(0, maxTime);}//经过D3比例尺计算的环的宽度var R = rScale(data.length);console.log(R);for(var i=0; i<data.length; i++){data[i]['type'] = 'pie';data[i]['radius'] = [i * R + 40, i * R + 40 + R];    //if(typeof($scope.times[i])!= null)data[i]['name'] = $scope.times[i];data[i]['itemStyle'] = {normal : {label : {show : i > (data.length-2)},labelLine : {show : i > (data.length-2), length:40,color : '#f0f',width : 10,type : 'dotted'}}};        }//显示中央文字setTimeout(function(){var myDate = new Date();var myMouth = myDate.getMonth()+1;var myYear = myDate.getFullYear();    //获取完整的年份(4位,1970-????)// 补充千层饼中央的说明文字var _ZR = myChart.getZrender();_ZR.addShape({shape : 'text',style : {x : _ZR.getWidth() / 2,y : _ZR.getHeight() / 2,color: 'orange',text : data.length + '个月前',textAlign : 'center'}});_ZR.addShape({shape : 'text',style : {x : _ZR.getWidth() / 2 + data.length * R +50,y : _ZR.getHeight() / 2,color: 'orange',strokeColor: 'pink',text : '今日 ' + myYear + "年" + myMouth + "月" ,textAlign : 'left',textFont:'normal 14px 微软雅黑'}});_ZR.refresh();}, 500);return data;
};

这样,无论数据量大小,年轮图都有可用性:

只有4个月数据时的年轮图

30个月的测试数据的年轮图

当然,做到这一步,虽然实现了需求,但毕竟是照着别人的例子修改,没有自己创作来的有深度。不过如何自己创作,就超过了本文的范畴,并且也不是这一篇博客所能包含得了的,日后再议。

5.浏览器兼容性:

最后必须一提浏览器兼容性问题。IE8、IE7浏览器不兼容canvas绘图(IE6请允许我直接无视),为了实现兼容需要引入excanvas_r3库。

1
2
3
4
5

<!--Le HTML5 shim,forIE6-8supportofHTML5elements-->
    <!--[ifltIE9]>
      <script src="application/views/frontEnd/build/lib/html5shiv.js"></script>
      <script src="application/views/frontEnd/build/lib/echarts-1.3.8/excanvas/excanvas.js"></script>
    <![endif]-->

有时IE8中绘图错位,加入以下代码启用IE7兼容模式即可解决:

1
2
3
4

<!--解决IE8中canvas绘图错位-->
    <!--[iflt IE9]>
    <meta http-equiv="X-UA-Compatible"content="IE=7"/>
    <![endif]-->

百度数据可视化图表套件echart实战相关推荐

  1. echart 数据视图_关于数据可视化图表的制作,你需要关注的30个小技巧

    优秀的数据可视化图表只是罗列.总结数据吗?当然不是!数据可视化其真正的价值是设计出可以被读者轻松理解的数据展示,因此在设计过程中,每一个选择,最终都应落脚于读者的体验,而非图表制作者个人. 今天就给大 ...

  2. 数据分析可视化04 图表组件:Echarts数据可视化图表基础

    本课时是课程的第二个模块,环境部署篇的第一个课时.在第一部分的基础理论篇,我向你介绍了数据可视化分析的概念定义.方法体系和关键技术.接下来,我会带你了解基于开源框架,如何部署数据可视化分析的开发环境, ...

  3. layui导入模板数据_数据可视化图表 教程echarts,第一讲

    1 我们写web项目,展示数据的地方,可能会使用到图表.今天就讲这个玩意. 本教程暂时定为 三讲:(随后情况,如果有新的研究,会有所更新!) 第一讲  饼图的使用 第二讲  柱状图的使用 第三讲  拆 ...

  4. 数据可视化——图表类型选择

    目录 图表类型选择的依据 图表的功能性总结 图表类型总结 比较类 柱状图​​​和柱状图变体 气泡图 色块图 雷达图 漏斗图 K线图 词云图 子弹图 分布类 箱形图(盒须图.盒式图.箱线图) 气泡图 色 ...

  5. axure图表_最好用的数据可视化图表制作工具推荐

    数据可是化在我们日常生活中越来越重要了,所以很多场合场景都需要通过可视化的一些数据来展示场景效果,那么这些可视化图表如何制作呢? 其实制作可视化图表是比较简单的,完全可以通过工具实现,下面小编给大家介 ...

  6. Unity数据可视化图表插件XCharts3.0发布

    Unity数据可视化图表插件XCharts3.0发布 历时8个多月,业余时间,断断续续,XCharts3.0 总算发布了.如果要打个满意度,我给 3.0 版本来个80分. 对于代码框架结构设计的调整改 ...

  7. python动态交互图表_Python 调用 matplotlib 实现交互式数据可视化图表案例

    交互式的数据可视化图表是 New IT 新技术的一个应用方向,在过去,用户要在网页上查看数据,基本的实现方式就是在页面上显示一个表格出来,的而且确,用表格的方式来展示数据,显示的数据量会比较大,但是, ...

  8. echarts legend颜色_echarts数据可视化图表(二):双柱状图

    echarts数据可视化图表(二):双柱状图 效果图: html js var loadEcharts09 = function () { var myChartss = echarts.init(d ...

  9. 【Python】20个小技巧,让数据可视化图表更专业!

    参考 uxdesign Taras Bakusevych 数据可视化是数据展示的常见方式,所谓一图抵千言,好的图表能高效传递信息,让观众一目了然,差的图表往往会不知所云. 人类大脑的一半完全是用于处理 ...

最新文章

  1. 关于std::string 在 并发场景下 __grow_by_and_replace free was not allocated 的异常问题
  2. 探索存储机制(1-9)
  3. 为什么说一次一密加是密抗窃听无条件安全的?
  4. futurejava前台_web前端页面与后端Java的数据交互
  5. Android使用adb命令安装应用-连接usb
  6. java实现字符逆序输出
  7. 【渝粤题库】陕西师范大学200991教育统计学作业(高起本)
  8. java 正则提取大于等于号_Java正则表达式
  9. 计算机图形学考试题及答案_中国大学 MOOC_计算机图形学_测试题及答案
  10. iOS开发UI篇—实现一个私人通讯录小应用(一)
  11. GIT : IDEA切换到某个tag
  12. 如何用anaconda创建python项目_PyCharm+cmd中使用Anaconda 与 新建Python环境(Windows)
  13. 用java实现编译器-算术表达式及其语法解析器的实现
  14. win7下还原快捷方式的打开方式
  15. Web App - MUI框架初体验
  16. R语言中5种正态性检验的方法
  17. Nutch抓取过程简析
  18. 兰州举行闹元宵焰火晚会 百万市民争相观看
  19. windows无法连接到打印机_同事的电脑无法访问,共享打印机连接不上,问题都在这...
  20. MockFlow线框图、原型软件

热门文章

  1. C++ morris inorder二叉树中序遍历(附完整源码)
  2. C++插入排序(附完整源码)
  3. android ndk 编译c++11,Android NDK的C++11标准支持
  4. solidworks重建模型好慢_兄弟只能帮你到这了,SOLIDWORKS卡顿或许秘密就在这些选项里...
  5. 「pip」常用pip镜像地址
  6. B02_NumPy数据属性(ndarray.ndim,ndarray.shape,ndarray.itemsize,ndarray.flags)
  7. Java中实现的各种排序算法
  8. MyEclipse8.x下安装freemarker ide插件
  9. 关于windows10用c++部署libtorch过程中遇到的一些问题
  10. .bash_profile和.bashrc的区别(如何设置生效)