百度数据可视化图表套件echart实战
最近我一直在做數(shù)據(jù)可視化的前端工作,我用的最多的繪圖工具是d3。d3有點(diǎn)像photoshop,功能很強(qiáng)大,例子也很多,但是學(xué)習(xí)成本也不低,做項(xiàng)目是需要較大人力投入的。3月底由在亞馬遜工作的同學(xué)介紹下使用了一下echart,一個(gè)由百度前端發(fā)起的canvas國(guó)產(chǎn)類庫(kù)(官網(wǎng):http://echarts.baidu.com/index.html)。這個(gè)echart其實(shí)是在canvas類庫(kù)zrender的基礎(chǔ)上做的主題圖庫(kù),優(yōu)點(diǎn)有數(shù)據(jù)驅(qū)動(dòng),圖例豐富,功能強(qiáng)大,支持?jǐn)?shù)據(jù)拖拽重計(jì)算,數(shù)據(jù)區(qū)域漫游,全中文文檔非常過(guò)癮。跟同樣是國(guó)產(chǎn)的前端腳手架fis一樣(官網(wǎng)http://fis.baidu.com/),都是誠(chéng)意滿滿的國(guó)產(chǎn)套餐,體現(xiàn)了現(xiàn)今國(guó)內(nèi)不俗的前端開發(fā)實(shí)力。使用它們的感覺就像想自己做個(gè)平板電腦,去華強(qiáng)北一轉(zhuǎn),主板、CPU、屏幕等各種套餐一訂購(gòu),東西就嘩嘩地組裝起來(lái)了。極其高效,非常適合商業(yè)項(xiàng)目開發(fā)。而且,即使是為了研究,用這些也可以打一個(gè)很好的基礎(chǔ)。
Echart圖表庫(kù)層次關(guān)系
1.引入目錄
廢話不多說(shuō)了,看到好東西,第一步是從github上把相關(guān)文件全下下來(lái),然后到build目錄翻箱倒柜把東西找齊。新建目錄如下:
echarts-1.3.8
—-zrender ? //zrender是echart依賴的繪圖庫(kù),官網(wǎng)要求下載,但是目前我的程序中并沒有直接引用它,可以說(shuō)普通情況下echart可以自己獨(dú)立運(yùn)行
——–zrender.js
—-excanvas_r3 //excanvas是實(shí)現(xiàn)IE7,8兼容canvas繪圖的利器,實(shí)現(xiàn)了大部分canvas的API,在繪圖方面其核心是通過(guò)IE的VML去實(shí)現(xiàn)的,效率較低
——–excanvas.js
—-echarts.js ?//echarts主程序,包含除map以外所有的主題圖庫(kù)。注意這個(gè)是壓縮過(guò)的,并且只能通過(guò)requirejs或者esl.js模塊化加載;想用標(biāo)簽或sea.js加載請(qǐng)用echarts-plain.js
—-echarts-orginal.js ?//沒有壓縮過(guò)的echarts.js
—-echarts-map.js ?//echarts的map主題圖庫(kù)
2.在自己的項(xiàng)目中實(shí)現(xiàn)其demo
這個(gè)echart是百度前端做的,他們推薦使用模塊式開發(fā)。好在我之前的項(xiàng)目,就是采用requirejs + angularjs開發(fā)的。所以引入比較容易。
首先,在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的具體頁(yè)面控制js文件里,加載相關(guān)依賴。
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的朋友應(yīng)該都毫無(wú)壓力,但是還是有很多朋友沒用過(guò)這些,所以還是有必要說(shuō)一下的。
接著就是把官網(wǎng)的例子放在自己的頁(yè)面里實(shí)現(xiàn)。這里我選取了一個(gè)特別的千層餅圖,點(diǎn)擊這里去官網(wǎng)查看原圖。
那么我們把例子里的靜態(tài)數(shù)據(jù)(option對(duì)象)搬運(yùn)到我們自己的JS文件中,然后仿照官網(wǎng)的例子寫一個(gè)渲染&刷新函數(shù)
//渲染&刷新函數(shù)$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 = '';};//測(cè)試數(shù)據(jù) $scope.option = {title : {text: '瀏覽器占比變化',subtext: '純屬虛構(gòu)',x:'right',y:'bottom'},tooltip : {trigger: 'item',formatter: "{a} <br/>{b} : {c} (ozvdkddzhkzd%)"},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:'瀏覽器(數(shù)據(jù)純屬虛構(gòu))',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();// 補(bǔ)充千層餅_ZR.addShape({shape : 'text',style : {x : _ZR.getWidth() / 2,y : _ZR.getHeight() / 2,color: '#666',text : '惡夢(mèng)的過(guò)去',textAlign : 'center'}});_ZR.addShape({shape : 'text',style : {x : _ZR.getWidth() / 2 + 200,y : _ZR.getHeight() / 2,brushType:'fill',color: 'orange',text : '美好的未來(lái)',textAlign : 'left',textFont:'normal 20px 微軟雅黑'}});_ZR.refresh(); }, 2000);然后在頁(yè)面上找個(gè)div,顯示echart就可以了。
不過(guò)請(qǐng)注意一定要給這個(gè)div設(shè)置寬度高度,否則圖顯示不出來(lái)不要怪我。
<section class="span12"> <div id="graph" class="graph chart-area" style="height:500px"></div> </section> 我這里用了bootstrap,寬度是按柵格系統(tǒng)的百分比值變化的,所以上面的代碼中沒有指定寬度。最后調(diào)試調(diào)試,沒有問(wèn)題我這里也可以顯示。3.定制
當(dāng)然,僅僅停留在引用別人的例子是不能讓我滿意的。
首先,要進(jìn)行數(shù)據(jù)綁定。
這里細(xì)分為3步:
5.進(jìn)一步定制
雖然我使用了官網(wǎng)的例子實(shí)現(xiàn)了需求,但是我還有些自己的想法。
官網(wǎng)的千層餅圖中,代表時(shí)間的年輪寬度是固定的。但是我們從后臺(tái)讀取的數(shù)據(jù)(以月為顆粒度)在時(shí)間上是變化的,隨著系統(tǒng)使用時(shí)間增長(zhǎng)而增長(zhǎng)。這就導(dǎo)致一個(gè)問(wèn)題,就是在只有一個(gè)月時(shí),年輪只有小小一個(gè),有50個(gè)月時(shí),年輪多到超過(guò)了顯示范圍。這樣很不美觀,并且喪失了一定的可用性。
我決定要對(duì)其進(jìn)行優(yōu)化。當(dāng)使用月份很少導(dǎo)致數(shù)據(jù)很少的時(shí)候,年輪會(huì)很寬;當(dāng)使用月份很多導(dǎo)致數(shù)據(jù)很多的時(shí)候,年輪會(huì)很細(xì)——這樣就可以同時(shí)避免數(shù)據(jù)量小的時(shí)候不美觀和數(shù)據(jù)量大的時(shí)候喪失可用性的問(wèn)題了。當(dāng)然,如果數(shù)據(jù)量過(guò)大,年輪就會(huì)過(guò)細(xì),同樣會(huì)喪失可用性。因此我們要設(shè)置一個(gè)最大數(shù)據(jù)量的閾值,把超過(guò)的部分砍掉。
解決方案就是要對(duì)根據(jù)數(shù)據(jù)量對(duì)年輪寬度進(jìn)行縮放,也就是使用比例尺函數(shù)。在echart里我暫時(shí)沒有找到這樣的比例尺函數(shù)。當(dāng)然,線性比例尺很簡(jiǎn)單,函數(shù)可以自己寫。但是其他類型的比例尺縮放就稍微要一些技巧了。好在之前我一直是使用d3類庫(kù)來(lái)做可視化的,我知道d3里有這樣的比例尺函數(shù)可以很容易地解決我的問(wèn)題。那就是d3.scale對(duì)象,其中包含線性比例尺、平方比例尺、指數(shù)比例尺、集合比例尺,完全可以滿足需要。我可以從開源的d3庫(kù)中把比例尺函數(shù)抽取出來(lái),也引入到這個(gè)頁(yè)面。根據(jù)實(shí)際數(shù)據(jù)的測(cè)試結(jié)果,我選擇了平方比例尺。那么接下來(lái)就很好寫了:
var maxTime = 36; //本千層餅圖最多顯示60個(gè)月的數(shù)據(jù)(最多顯示60個(gè)圈) //原始數(shù)據(jù)的加工工廠函數(shù) $scope.setData = function(data){//這是D3的平方比例尺函數(shù),用于根據(jù)數(shù)據(jù)大小縮放環(huán)的寬度var rScale = d3.scale.sqrt().domain([maxTime, 1]).range([3, 30]).nice();console.log(rScale(1), rScale(12), rScale(36))//如果數(shù)據(jù)量超過(guò)60(即有60個(gè)月),則刪除60個(gè)月之前的數(shù)據(jù),只顯示最近60個(gè)月的內(nèi)容if(data.length > maxTime){data.splice(0, maxTime);}//經(jīng)過(guò)D3比例尺計(jì)算的環(huán)的寬度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-????)// 補(bǔ)充千層餅中央的說(shuō)明文字var _ZR = myChart.getZrender();_ZR.addShape({shape : 'text',style : {x : _ZR.getWidth() / 2,y : _ZR.getHeight() / 2,color: 'orange',text : data.length + '個(gè)月前',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; }; 這樣,無(wú)論數(shù)據(jù)量大小,年輪圖都有可用性:只有4個(gè)月數(shù)據(jù)時(shí)的年輪圖
30個(gè)月的測(cè)試數(shù)據(jù)的年輪圖
當(dāng)然,做到這一步,雖然實(shí)現(xiàn)了需求,但畢竟是照著別人的例子修改,沒有自己創(chuàng)作來(lái)的有深度。不過(guò)如何自己創(chuàng)作,就超過(guò)了本文的范疇,并且也不是這一篇博客所能包含得了的,日后再議。
5.瀏覽器兼容性:
最后必須一提瀏覽器兼容性問(wèn)題。IE8、IE7瀏覽器不兼容canvas繪圖(IE6請(qǐng)?jiān)试S我直接無(wú)視),為了實(shí)現(xiàn)兼容需要引入excanvas_r3庫(kù)。
| 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]--> |
有時(shí)IE8中繪圖錯(cuò)位,加入以下代碼啟用IE7兼容模式即可解決:
| 1 2 3 4 | <!--解決IE8中canvas繪圖錯(cuò)位--> ????<!--[iflt?IE9]> ????<meta?http-equiv="X-UA-Compatible"content="IE=7"/> ????<![endif]--> |
總結(jié)
以上是生活随笔為你收集整理的百度数据可视化图表套件echart实战的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 在旅游城市买房是否划算
- 下一篇: vs2015 编译时错误列表中没有错误,