百度数据可视化图表套件echart实战
最近我一直在做数据可视化的前端工作,我用的最多的绘图工具是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>
3.定制
当然,仅仅停留在引用别人的例子是不能让我满意的。
首先,要进行数据绑定。
这里细分为3步:
- 分析数据格式(就是分析option对象,这一步需要注意把后台获取的数据和样式信息分开。故而我在代码里设置了$scope.option对象存储默认的样式配置信息,之后ajax获取数据后将二者再extend即可。)
- 在后台组装相应的数据(根据不同需求而异,我这里只取数值信息,不多言)
- 前台ajax获取真实数据(这一点相信大家都很纯熟,不过我的代码里是使用angularjs封装过的$.post对象来做到这一点的)
//设置真实数据格式
$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实战的更多相关文章
- Webstorm+Webpack+echarts构建个性化定制的数据可视化图表&&两个echarts详细教程(柱状图,南丁格尔图)
Webstorm+Webpack+echarts ECharts 特性介绍 ECharts,一个纯 Javascript 的图表库,可以流畅的运行在 PC 和移动设备上,兼容当前绝大部分浏览器(I ...
- ECharts-基于Canvas,纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据可视化图表
ECharts http://ecomfe.github.com/echarts 基于Canvas,纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据可视化图表.创新的拖拽重计算 ...
- Python调用matplotlib实现交互式数据可视化图表案例
交互式的数据可视化图表是 New IT 新技术的一个应用方向,在过去,用户要在网页上查看数据,基本的实现方式就是在页面上显示一个表格出来,的而且确,用表格的方式来展示数据,显示的数据量会比较大,但是, ...
- 数据可视化图表ECharts
介绍: ECharts是一个基于ZRender(轻量级Canvas类库)的纯javascript图表库,提供可交互.个性化的数据可视化图表. ECharts提供了折线图.柱状图.散点图.饼图.K线图, ...
- Excel数据可视化图表设计需要注意的几个问题
大数据发展迅速的时代,数据分析驱动商业决策.对于庞大.无序.复杂的数据要是没经过合适的处理,价值就无法体现. 可以想象一本没有图片的教科书.没有图表.图形或是带有箭头和标签的插图或流程图,那么这门学 ...
- 数据分析 | 数据可视化图表,BI工具构建逻辑
本文源码:GitHub·点这里 || GitEE·点这里 一.数据可视化 1.基础概念 数据可视化,是关于数据视觉表现形式的科学技术研究.其中,这种数据的视觉表现形式被定义为,一种以某种概要形式抽取出 ...
- CSDN开源夏令营 百度数据可视化实践 ECharts(4)
ECharts知识点总结: 在应用过程中总会遇到一些难以理解的概念和属性,这里就总结了一下比較难的知识点,方便理解概念.进而更好的掌握ECharts. (1)1. 一个完整的option包括什么?能 ...
- CSDN开源夏令营 百度数据可视化实践 ECharts(8)问题分析
ECharts问题描写叙述: 问题就是折线图上的点是显示的,有人问能不能一開始不显示,当你点击的时候或者是当鼠标移动到上面的时候,折线上的点才显示? 例如以下图所看到的: 分析:让折线上的点不显示能够 ...
- 【数据可视化-Echarts】Echart基础
林峰老师Echart基础课程笔记
随机推荐
- web项目知识整理
一.div居中 1.margin:auto 2.left:50%:margin-left:div宽度的一半 二.一般处理程序操作session 引using System.Web.SessionSta ...
- Entity Framework 中的Code First 中引入数据库函数
1,在项目中添加CodeFirstStoreFunctions包: Install-Package EntityFramework.CodeFirstStoreFunctions 2,注册注册函数,F ...
- 从“黑掉Github”学Web安全开发
Egor Homakov(Twitter: @homakov 个人网站: EgorHomakov.com)是一个Web安全的布道士,他这两天把github给黑了,并给github报了5个安全方面的bu ...
- 【IScroll深入学习】突破移动端黑暗的利器(上)
前言 在去年,我们对IScroll的源码进行了学习,并且分离出了一段代码自己使用,在使用学习过程中发现几个致命问题: ① 光标移位 ② 文本框找不到(先让文本框获取焦点,再滑动一下,输入文字便可重现) ...
- asp.net mvc 中 一种简单的 URL 重写
asp.net mvc 中 一种简单的 URL 重写 Intro 在项目中想增加一个公告的功能,但是又不想直接用默认带的那种路由,感觉好low逼,想弄成那种伪静态化的路由 (别问我为什么不直接静态化, ...
- iOS 支付宝的使用
支付宝相关资源下载地址:支付宝开放平台 在移动支付功能处下载. 一.使用官方的Demo 需要配置基本信息: 打开“APViewController.m”文件,对以下三个参数进行编辑. 二.集成支付宝 ...
- C#读取ini文件的方法
最近项目用到ini文件,读取ini文件,方法如下: using System; using System.Collections.Generic; using System.Linq; using S ...
- centos虚拟机复制移动后网络配置无效
移植Centos虚拟机后无法联网解决1.迁移以后,会存在其中一个网卡无法启动(eth0 or eth1) [root@ ~]# ifup eth0 WARNING: Deprecated config ...
- android四大组件(简单总结)
activity 一个Activity通常就是一个单独的屏幕(窗口) Activity之间通过Intent进行通信 android应用中每一个Activity都必须要在AndroidManifest. ...
- 点击ViewGroup时其子控件也变成pressed状态的原因分析及解决办法
这个问题,当初在分析touch事件处理的时候按理应该分析到的,可是由于我当时觉得这块代码和touch的主题不是那么紧密, 就这么忽略掉了,直到后来在这上面遇到了问题.其实这个现象做Android开发的 ...