「概覽數(shù)據(jù)整體髓削,按需關(guān)注數(shù)據(jù)細(xì)節(jié)」是數(shù)據(jù)可視化的基本需求竹挡。前文講到的兩類圖表都是靜態(tài)圖表,數(shù)據(jù)結(jié)構(gòu)往往只有一層立膛。當(dāng)你的數(shù)據(jù)具有多個(gè)層次(樹(shù)形結(jié)構(gòu))揪罕,如數(shù)據(jù)按男女劃分之后梯码,對(duì)應(yīng)每個(gè)性別,會(huì)有進(jìn)一步的年齡層次的劃分好啰,對(duì)于各年齡層次轩娶,可能還會(huì)有城鄉(xiāng)戶籍、受教育程度的區(qū)分框往,多層次的信息很難在單一的靜態(tài)圖表中展示鳄抒。
本例中筆者將使用旭日?qǐng)D作為核心圖表,展示如何可視化多層次的數(shù)據(jù)椰弊。并且在最后许溅,筆者會(huì)做一個(gè)擴(kuò)展,演示如何聯(lián)動(dòng)兩類型圖表男应,更直觀地反映數(shù)據(jù)特征闹司,這一部分可能會(huì)涉及較復(fù)雜的編碼內(nèi)容,大家可以選擇性學(xué)習(xí)沐飘。
本例的數(shù)據(jù)由筆者隨機(jī)生成游桩,最終的頁(yè)面可以點(diǎn)擊鏈接查看。
正式開(kāi)始
-
數(shù)據(jù)獲取:
本例的數(shù)據(jù)也將直接給出耐朴,并且這部分?jǐn)?shù)據(jù)將不單獨(dú)保存在其他文件中借卧,而直接寫入到代碼。本例采用該方法筛峭,是因?yàn)樾袢請(qǐng)D的同一層次顯示類似于扇形圖铐刘,數(shù)據(jù)量并不大,寫入代碼中不會(huì)導(dǎo)致結(jié)構(gòu)過(guò)于混亂影晓。本手冊(cè)面向的是非編碼職業(yè)的讀者镰吵,我們采用這個(gè)不專業(yè)的方法,也是為了省去額外的解釋內(nèi)容挂签,將重點(diǎn)放在如何可視化數(shù)據(jù)上疤祭。
不過(guò),即便數(shù)據(jù)量不大饵婆,該部分仍舊占用了大量的空間勺馆。為了節(jié)省篇幅,除了最一開(kāi)始導(dǎo)入數(shù)據(jù)的步驟侨核,以及最終展示代碼全貌外草穆,其余的內(nèi)容將略去數(shù)據(jù)部分,望讀者注意搓译,避免錯(cuò)誤的粘貼導(dǎo)致圖表出錯(cuò)悲柱。
-
數(shù)據(jù)分析:
旭日?qǐng)D所需的數(shù)據(jù)結(jié)構(gòu),是字典型(數(shù)據(jù)對(duì)的集合)些己。我們展示一部分的數(shù)據(jù)豌鸡,如下所示:
var data = [{ name: '正式平臺(tái)', value: 9487, children: [{ name: '有地址', value: 9357, children: [{ name: '6選3', value: 2851, children: [{ name: '北京市', value: 2336 },{ name: '山東省', value: 425 },{ name: '天津市', value: 83 },{ name: '上海市', value: 7 }] },{ name:'3+1+2', value:5321 }] }] }]
如果讀者覺(jué)得直接看這個(gè)不甚明了跑芳,可以結(jié)合下方的圖示理解。
graph TB 正式平臺(tái)-->有地址-->6選3 6選3-->北京市 6選3-->山東省 6選3-->天津市 6選3-->上海市 有地址-->3+1+2
對(duì)于任意一個(gè)節(jié)點(diǎn)直颅,都包含三個(gè)信息:[name]博个,[value],[children]功偿,分別代表節(jié)點(diǎn)名稱盆佣、節(jié)點(diǎn)的值、子節(jié)點(diǎn)械荷,其中子節(jié)點(diǎn)中又是包含有這三個(gè)信息的節(jié)點(diǎn)排列共耍。
一個(gè)節(jié)點(diǎn)如果沒(méi)有子節(jié)點(diǎn),則不需要填入[children]信息吨瞎。特別的痹兜,對(duì)于Echarts,如果一個(gè)節(jié)點(diǎn)是父節(jié)點(diǎn)(存在子節(jié)點(diǎn))颤诀,可不為其填入[value]值字旭。在繪制圖表時(shí),value值將取子節(jié)點(diǎn)[value]值之和崖叫。
需要注意的是遗淳,父節(jié)點(diǎn)的[value]值可能不等于子節(jié)點(diǎn)的[value]值之和(可能存在數(shù)據(jù)缺失),所以出現(xiàn)該情況時(shí)心傀,務(wù)必錄入父節(jié)點(diǎn)的[value]值屈暗,保證圖表的正確性。
數(shù)據(jù)準(zhǔn)備全部完成脂男,接下來(lái)我們準(zhǔn)備繪制初始圖表养叛。
-
初始圖表:
有了前兩個(gè)案例的學(xué)習(xí),讀者應(yīng)當(dāng)了解了Echarts代碼的一些特點(diǎn)宰翅。本節(jié)將直接給出最初始圖表(帶有簡(jiǎn)單解釋)弃甥,然后逐步美化圖表顯示,最后增加交互效果堕油。進(jìn)度會(huì)稍有加快潘飘,但會(huì)更加凸顯重點(diǎn)肮之。
-
初始的圖表掉缺。我們直接給出代碼,讀者可以將其粘貼到[txt]文件中戈擒,保存后修改后綴為[.html]眶明,直接打開(kāi)即可看到當(dāng)前效果。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>ECharts</title> <!-- 引入 echarts.js --> <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts/dist/echarts.min.js"></script> <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts-gl/dist/echarts-gl.min.js"></script> <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts-stat/dist/ecStat.min.js"></script> <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts/dist/extension/dataTool.min.js"></script> <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts/map/js/china.js"></script> <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts/map/js/world.js"></script> <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts/dist/extension/bmap.min.js"></script> <script type="text/javascript" src="https://www.jb51.net/jslib/jquery/jquery.min.js"></script> </head> <body> <!-- 為ECharts準(zhǔn)備一個(gè)具備大锌鸶摺(寬高)的Dom --> <div id="sun1" style="width:100%;height:900px;float:left;"></div> <script type="text/javascript"> // 基于準(zhǔn)備好的dom搜囱,初始化echarts實(shí)例 var myChartSun1 = echarts.init(document.getElementById('sun1')); //旭日?qǐng)D所需數(shù)據(jù)結(jié)構(gòu) var data = [{ name: '正式平臺(tái)', value: 9487, children: [{ name: '有地址', value: 9357, children: [{ name: '6選3', value: 2851, children: [{ name: '北京市', value: 2336 },{ name: '山東省', value: 425 },{ name: '天津市', value: 83 },{ name: '上海市', value: 7 }] }, { name: '3+1+2', value: 5321, children: [{ name: '廣東省', value: 2068 },{ name: '福建省', value: 1582, //數(shù)據(jù)下可設(shè)置格式 // itemStyle: { // shadowBlur: 10, // shadowColor: '#99ffff' // }, },{ name: '重慶市', value: 718 },{ name: '江蘇省', value: 301 },{ name: '湖北省', value: 257 },{ name: '河北省', value: 222 },{ name: '湖南省', value: 116 },{ name: '遼寧省', value: 57 }] }, { name: '7選3-浙江', value: 28 }, { name: '未改革', value: 1157 , children:[{ name:'安徽省', value: 460 },{ name:'陜西省', value:286 },{ name:'四川省', value:126 },{ name:'新疆', value:114 },{ name:'云南省', value:66 },{ name:'廣西', value:34 },{ name:'江西省', value:27 },{ name:'甘肅省', value:17 },{ name:'河南省', value:14 },{ name:'山西省', value:13 }] }] }, { name: '無(wú)地址', value: 130 }] }, { name: '培訓(xùn)平臺(tái)', value: 3215, children: [{ name: '智校測(cè)試校', children: [{ name: '培訓(xùn)', value: 1449 }, { name: '排課', value: 1325 }] },{ name:'新課改培訓(xùn)', value: 441 }] }, { name: '測(cè)試+演示平臺(tái)', value: 1046, children: [{ name: '測(cè)試', value: 464 }, { name: '演示', value: 582 } ] }, { name: '職教+舊平臺(tái)', value: 1239 }]; var option = { backgroundColor:'#000', tooltip: { trigger: 'item', formatter: function (params) { return params.name + ' : ' + params.value; } }, visualMap: { min: 0, max: 2000, calculable: true, inRange: { color: ['#50a3ba', '#eac736', '#d94e5d'] }, textStyle: { color: '#fff' } }, series: [{ type: 'sunburst', id:'sunburst1', // highlightPolicy: 'ancestor', data: data, center:['50%','50%'], //旭日?qǐng)D半徑90%丑瞧,中心預(yù)留10像素 radius: [10, '90%'], //高亮當(dāng)前及其子區(qū)間 //highlightPolicy: 'descendant', label: { rotate: 'radial', fontSize: 15 } }] }; // 使用剛指定的配置項(xiàng)和數(shù)據(jù)顯示圖表。 myChartSun1.setOption(option); </script> </body> </html>
代碼中幾乎沒(méi)有新的內(nèi)容蜀肘,希望讀者可以舉一反三绊汹,自行了解下每部分代碼的效果。當(dāng)前圖表如下:
旭日?qǐng)D本身支持?jǐn)?shù)據(jù)下鉆扮宠,點(diǎn)擊任意環(huán)形塊西乖,都會(huì)呈現(xiàn)出以點(diǎn)擊節(jié)點(diǎn)為根節(jié)點(diǎn)(初始節(jié)點(diǎn))的新圖:
當(dāng)前的圖表不分主次地呈現(xiàn)了全部數(shù)據(jù),如果你將其展示給你的老板坛增,你應(yīng)該很難凸顯出圖表想要表達(dá)的數(shù)據(jù)特點(diǎn)获雕。實(shí)際上這樣的一張圖表,大多數(shù)人都無(wú)法理解它想表達(dá)的內(nèi)容收捣。
接下來(lái)筆者將介紹如何美化這張圖表届案,使其能夠更鮮明地體現(xiàn)數(shù)據(jù)。
-
-
逐步美化圖表:
-
讀者應(yīng)該能注意到罢艾,這張旭日?qǐng)D分四個(gè)層次楣颠,當(dāng)前各層次的厚度都相同。通常我們會(huì)減少最外層環(huán)的厚度(降維效果咐蚯,將面積信息轉(zhuǎn)化為長(zhǎng)度信息)球碉,并且增加中心空白(背景黑色)的半徑,代碼在[series]中添加仓蛆,新增的代碼如下:
series: [{ type: 'sunburst', id:'sunburst1', // highlightPolicy: 'ancestor', data: data, center:['50%','50%'], radius: [10, '90%'], //高亮當(dāng)前及其子區(qū)間 //highlightPolicy: 'descendant', label: { rotate: 'radial', fontSize: 15 }, //levels設(shè)置各層次環(huán)形寬度 levels: [{}, { //內(nèi)圈半徑 r0: '10%', //外圈半徑 r: '30%', itemStyle: { //邊框?qū)挾? borderWidth: 2 } }, { r0: '30%', r: '50%', itemStyle: { borderWidth: 2 } }, { r0: '50%', r: '70%', itemStyle: { borderWidth: 2 } }, { r0: '70%', r: '75%', label: { //文字顯示在外側(cè) position: 'outside', //距離環(huán)形的距離 padding: 3, }, itemStyle: { borderWidth: 3, //陰影半徑 shadowBlur: 10, //陰影顏色睁冬,當(dāng)前是亮色 shadowColor: '#99ffff' } }] }]
我們通過(guò)設(shè)置內(nèi)圈外圈的半徑,限制每一層環(huán)形的寬度看疙。最外層環(huán)形僅有5%的寬度豆拨,無(wú)法容納文字,所以我們選擇將文字內(nèi)容懸浮于圖形之外能庆。并且為了凸顯外圈內(nèi)容施禾,我們?cè)黾恿岁幱癧shadow]效果,并且選擇亮色搁胆,使其能在黑色背景下高亮最外圈內(nèi)容弥搞。
新增代碼后的圖表效果如下:
-
旭日?qǐng)D支持?jǐn)?shù)據(jù)下鉆,但除了點(diǎn)擊操作外渠旁,其他任何操作都不會(huì)影響圖表顯示攀例。我們接下來(lái)新增幾個(gè)焦點(diǎn)動(dòng)畫,使得鼠標(biāo)懸浮于節(jié)點(diǎn)之上時(shí)顾腊,可以強(qiáng)調(diào)當(dāng)前節(jié)點(diǎn)粤铭。代碼在[series]中添加,我們首先新增能強(qiáng)調(diào)當(dāng)前節(jié)點(diǎn)的部分代碼:
//選定區(qū)域 emphasis: { itemStyle: { //環(huán)形顏色 color: 'red', //邊框顏色 borderColor: '#fff', shadowBlur: 10, shadowColor: '#99ffff' } }, //高亮區(qū)域 highlight: { itemStyle: { color: 'orange', borderColor: '#fff', shadowBlur: 10, shadowColor: '#99ffff' } },
我們分別設(shè)置了當(dāng)前選定區(qū)域和高亮區(qū)域的焦點(diǎn)效果杂靶。你可能會(huì)有疑問(wèn)梆惯,這兩者的區(qū)別在哪里酱鸭?讀者已經(jīng)清楚了解到,旭日?qǐng)D的數(shù)據(jù)是樹(shù)狀的層級(jí)結(jié)構(gòu)垛吗,當(dāng)用戶選中父節(jié)點(diǎn)時(shí)凹髓,Echarts同時(shí)會(huì)高亮子節(jié)點(diǎn)。也就是說(shuō)怯屉,[emphasis]設(shè)置的是當(dāng)前選中區(qū)域的樣式扁誓,[highlight]設(shè)置的是子節(jié)點(diǎn)區(qū)域的樣式。
讀者可以自行觀察交互效果蚀之,更加便于理解蝗敢。當(dāng)前效果如下圖:
-
平心而論,你真的能很快注意到我們當(dāng)前選定的內(nèi)容么足删?很顯然是不能的寿谴。因?yàn)榉沁x定的區(qū)域也帶有多種顏色,一般讀者很難將兩者區(qū)分開(kāi)讶泰。所以除了強(qiáng)調(diào)選定節(jié)點(diǎn),非選定的節(jié)點(diǎn)我們需要弱化其顯示效果痪署。代碼在[series]中添加悯森,新增的代碼如下:
//非選定區(qū)域 downplay: { itemStyle: { color: '#1e1e1e', shadowBlur: 0, //透明度 opacity: 0.3 }, label: { //透明度 opacity: 0.3 } },
如代碼所示瓢姻,我們降低了非選定區(qū)域內(nèi)容的透明度音诈,調(diào)整了區(qū)域背景和邊框顏色幻碱,使得這部分內(nèi)容不容易被注意到。調(diào)整后的圖形如下:
我們選擇了相同的區(qū)域细溅,讀者可以對(duì)比前后兩張圖片褥傍。很顯然,調(diào)整后的圖片更加凸顯重點(diǎn)谒兄。并且得益于Echarts出色的動(dòng)畫漸變效果摔桦,切換選擇區(qū)域不會(huì)給用戶帶來(lái)很突兀的感覺(jué)社付。
現(xiàn)在給出最終的完整代碼承疲,讀者可以根據(jù)官方文檔自行修改邻耕,或者使用自己的數(shù)據(jù),生成自己的專屬圖表:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>ECharts</title> <!-- 引入 echarts.js --> <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts/dist/echarts.min.js"></script> <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts-gl/dist/echarts-gl.min.js"></script> <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts-stat/dist/ecStat.min.js"></script> <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts/dist/extension/dataTool.min.js"></script> <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts/map/js/china.js"></script> <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts/map/js/world.js"></script> <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts/dist/extension/bmap.min.js"></script> <script type="text/javascript" src="https://www.jb51.net/jslib/jquery/jquery.min.js"></script> </head> <body> <!-- 為ECharts準(zhǔn)備一個(gè)具備大醒喔搿(寬高)的Dom --> <div id="sun1" style="width:100%;height:900px;float:left;"></div> <script type="text/javascript"> // 基于準(zhǔn)備好的dom兄世,初始化echarts實(shí)例 var myChartSun1 = echarts.init(document.getElementById('sun1')); //旭日?qǐng)D所需數(shù)據(jù)結(jié)構(gòu) var data = [{ name: '正式平臺(tái)', value: 9487, children: [{ name: '有地址', value: 9357, children: [{ name: '6選3', value: 2851, children: [{ name: '北京市', value: 2336 },{ name: '山東省', value: 425 },{ name: '天津市', value: 83 },{ name: '上海市', value: 7 }] }, { name: '3+1+2', value: 5321, children: [{ name: '廣東省', value: 2068 },{ name: '福建省', value: 1582, //數(shù)據(jù)下可設(shè)置格式 // itemStyle: { // shadowBlur: 10, // shadowColor: '#99ffff' // }, },{ name: '重慶市', value: 718 },{ name: '江蘇省', value: 301 },{ name: '湖北省', value: 257 },{ name: '河北省', value: 222 },{ name: '湖南省', value: 116 },{ name: '遼寧省', value: 57 }] }, { name: '7選3-浙江', value: 28 }, { name: '未改革', value: 1157 , children:[{ name:'安徽省', value: 460 },{ name:'陜西省', value:286 },{ name:'四川省', value:126 },{ name:'新疆', value:114 },{ name:'云南省', value:66 },{ name:'廣西', value:34 },{ name:'江西省', value:27 },{ name:'甘肅省', value:17 },{ name:'河南省', value:14 },{ name:'山西省', value:13 }] }] }, { name: '無(wú)地址', value: 130 }] }, { name: '培訓(xùn)平臺(tái)', value: 3215, children: [{ name: '智校測(cè)試校', children: [{ name: '培訓(xùn)', value: 1449 }, { name: '排課', value: 1325 }] },{ name:'新課改培訓(xùn)', value: 441 }] }, { name: '測(cè)試+演示平臺(tái)', value: 1046, children: [{ name: '測(cè)試', value: 464 }, { name: '演示', value: 582 } ] }, { name: '職教+舊平臺(tái)', value: 1239 }]; var option = { backgroundColor:'#000', tooltip: { trigger: 'item', formatter: function (params) { return params.name + ' : ' + params.value; } }, visualMap: { min: 0, max: 2000, calculable: true, inRange: { color: ['#50a3ba', '#eac736', '#d94e5d'] }, textStyle: { color: '#fff' } }, series: [{ type: 'sunburst', id:'sunburst1', // highlightPolicy: 'ancestor', data: data, center:['50%','50%'], radius: [10, '90%'], //高亮當(dāng)前及其子區(qū)間 //highlightPolicy: 'descendant', label: { rotate: 'radial', fontSize: 15 }, //選定區(qū)域 emphasis: { itemStyle: { //環(huán)形顏色 color: 'red', //邊框顏色 borderColor: '#fff', shadowBlur: 10, shadowColor: '#99ffff' } }, //高亮區(qū)域 highlight: { itemStyle: { color: 'orange', borderColor: '#fff', shadowBlur: 10, shadowColor: '#99ffff' } }, //非選定區(qū)域 downplay: { itemStyle: { color: '#1e1e1e', shadowBlur: 0, //透明度 opacity: 0.3 }, label: { //透明度 opacity: 0.3 } }, //levels設(shè)置各層次環(huán)形寬度 levels: [{}, { //內(nèi)圈半徑 r0: '10%', //外圈半徑 r: '30%', itemStyle: { //邊框?qū)挾? borderWidth: 2 } }, { r0: '30%', r: '50%', itemStyle: { borderWidth: 2 } }, { r0: '50%', r: '70%', itemStyle: { borderWidth: 2 } }, { r0: '70%', r: '75%', label: { //文字顯示在外側(cè) position: 'outside', //距離環(huán)形的距離 padding: 3, }, itemStyle: { borderWidth: 3, //陰影半徑 shadowBlur: 10, //陰影顏色,當(dāng)前是亮色 shadowColor: '#99ffff' } }] }] }; // 使用剛指定的配置項(xiàng)和數(shù)據(jù)顯示圖表啊研。 myChartSun1.setOption(option); </script> </body> </html>
-
-
動(dòng)畫交互(選學(xué)御滩,但無(wú)疑是最吸引人的部分):
接下來(lái)筆者將介紹本章節(jié)最核心的部分。雖然是選學(xué)党远,但是筆者強(qiáng)烈希望讀者可以了解這部分內(nèi)容削解,并且將其應(yīng)用于自己的圖表中(即使不了解,你也可以通過(guò)修改數(shù)據(jù)使用它)沟娱。
旭日?qǐng)D類似于扇形圖氛驮,實(shí)際情況中很多人對(duì)這種扇形的面積信息很不敏感,無(wú)法從圖形中獲得各層次節(jié)點(diǎn)的數(shù)值分布济似。對(duì)于這個(gè)需求矫废,直方圖更加適合。于是筆者考慮砰蠢,能否將兩個(gè)圖表組合起來(lái)蓖扑,當(dāng)用戶選擇某節(jié)點(diǎn)時(shí),通過(guò)直方圖將子節(jié)點(diǎn)的數(shù)值信息展示出來(lái)台舱。
在本節(jié)中律杠,筆者將分三步介紹交互效果的實(shí)現(xiàn)過(guò)程:
- 在旭日?qǐng)D旁創(chuàng)建一個(gè)新的直方圖,顯示旭日?qǐng)D第一層級(jí)的數(shù)據(jù)竞惋;
- 新建一個(gè)[mouseover]事件俩功,當(dāng)用戶鼠標(biāo)懸浮于某節(jié)點(diǎn)時(shí),直方圖的數(shù)據(jù)更新為其子節(jié)點(diǎn)的[value]值碰声;
- 引入新維度的數(shù)據(jù)诡蜓。讀者可以結(jié)合業(yè)務(wù)需求選擇性學(xué)習(xí)該部分內(nèi)容。
接下來(lái)我們正式開(kāi)始胰挑。
-
創(chuàng)建直方圖:
創(chuàng)建直方圖的方式與前文所述的散點(diǎn)圖類似蔓罚,區(qū)別是直方圖的x軸類目相對(duì)較少,這部分不再贅述瞻颂。我們主要是調(diào)整旭日?qǐng)D的顯示位置豺谈,即令旭日?qǐng)D的容器寬度減半且左移,再右側(cè)新建一個(gè)容器贡这,以便展示直方圖茬末。此時(shí)的完整代碼如下:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>ECharts</title> <!-- 引入 echarts.js --> <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts/dist/echarts.min.js"></script> <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts-gl/dist/echarts-gl.min.js"></script> <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts-stat/dist/ecStat.min.js"></script> <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts/dist/extension/dataTool.min.js"></script> <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts/map/js/china.js"></script> <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts/map/js/world.js"></script> <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts/dist/extension/bmap.min.js"></script> <script type="text/javascript" src="https://www.jb51.net/jslib/jquery/jquery.min.js"></script> </head> <body> <!-- 為ECharts準(zhǔn)備一個(gè)具備大小(寬高)的Dom --> <!-- float設(shè)置浮動(dòng)方式,保證兩個(gè)div顯示在同一排(因?yàn)槲覀兊娜萜鲗挾仁亲赃m應(yīng)的) --> <div id="sun1" style="width:50%;height:900px;float:left;"></div> <div id="bar1" style="width:50%;height:900px;float:left;"></div> <script type="text/javascript"> // 基于準(zhǔn)備好的dom丽惭,初始化echarts實(shí)例 var myChartSun1 = echarts.init(document.getElementById('sun1')); var myChartBar1 = echarts.init(document.getElementById('bar1')); //旭日?qǐng)D所需數(shù)據(jù)結(jié)構(gòu) var data = [{ name: '正式平臺(tái)', value: 9487, children: [{ name: '有地址', value: 9357, children: [{ name: '6選3', value: 2851, children: [{ name: '北京市', value: 2336 },{ name: '山東省', value: 425 },{ name: '天津市', value: 83 },{ name: '上海市', value: 7 }] }, { name: '3+1+2', value: 5321, children: [{ name: '廣東省', value: 2068 },{ name: '福建省', value: 1582, //數(shù)據(jù)下可設(shè)置格式 // itemStyle: { // shadowBlur: 10, // shadowColor: '#99ffff' // }, },{ name: '重慶市', value: 718 },{ name: '江蘇省', value: 301 },{ name: '湖北省', value: 257 },{ name: '河北省', value: 222 },{ name: '湖南省', value: 116 },{ name: '遼寧省', value: 57 }] }, { name: '7選3-浙江', value: 28 }, { name: '未改革', value: 1157 , children:[{ name:'安徽省', value: 460 },{ name:'陜西省', value:286 },{ name:'四川省', value:126 },{ name:'新疆', value:114 },{ name:'云南省', value:66 },{ name:'廣西', value:34 },{ name:'江西省', value:27 },{ name:'甘肅省', value:17 },{ name:'河南省', value:14 },{ name:'山西省', value:13 }] }] }, { name: '無(wú)地址', value: 130 }] }, { name: '培訓(xùn)平臺(tái)', value: 3215, children: [{ name: '智校測(cè)試校', children: [{ name: '培訓(xùn)', value: 1449 }, { name: '排課', value: 1325 }] },{ name:'新課改培訓(xùn)', value: 441 }] }, { name: '測(cè)試+演示平臺(tái)', value: 1046, children: [{ name: '測(cè)試', value: 464 }, { name: '演示', value: 582 } ] }, { name: '職教+舊平臺(tái)', value: 1239 }]; var option = { backgroundColor:'#000', tooltip: { trigger: 'item', formatter: function (params) { return params.name + ' : ' + params.value; } }, visualMap: { min: 0, max: 2000, calculable: true, inRange: { color: ['#50a3ba', '#eac736', '#d94e5d'] }, textStyle: { color: '#fff' } }, series: [{ type: 'sunburst', id:'sunburst1', // highlightPolicy: 'ancestor', data: data, center:['50%','50%'], radius: [10, '90%'], //高亮當(dāng)前及其子區(qū)間 //highlightPolicy: 'descendant', label: { rotate: 'radial', fontSize: 15 }, //選定區(qū)域 emphasis: { itemStyle: { //環(huán)形顏色 color: 'red', //邊框顏色 borderColor: '#fff', shadowBlur: 10, shadowColor: '#99ffff' } }, //高亮區(qū)域 highlight: { itemStyle: { color: 'orange', borderColor: '#fff', shadowBlur: 10, shadowColor: '#99ffff' } }, //非選定區(qū)域 downplay: { itemStyle: { color: '#1e1e1e', shadowBlur: 0, //透明度 opacity: 0.3 }, label: { //透明度 opacity: 0.3 } }, //levels設(shè)置各層次環(huán)形寬度 levels: [{}, { //內(nèi)圈半徑 r0: '10%', //外圈半徑 r: '30%', itemStyle: { //邊框?qū)挾? borderWidth: 2 } }, { r0: '30%', r: '50%', itemStyle: { borderWidth: 2 } }, { r0: '50%', r: '70%', itemStyle: { borderWidth: 2 } }, { r0: '70%', r: '75%', label: { //文字顯示在外側(cè) position: 'outside', //距離環(huán)形的距離 padding: 3, }, itemStyle: { borderWidth: 3, //陰影半徑 shadowBlur: 10, //陰影顏色击奶,當(dāng)前是亮色 shadowColor: '#99ffff' } }] }] }; //另一個(gè)option,設(shè)置直方圖的圖表信息 var option1 = { backgroundColor:'#000', tooltip: { trigger: 'item', formatter: function (params) { return params.name + ' : ' + params.value; } }, visualMap: { min: 0, max: 2000, calculable: true, show: false, seriesIndex:0, inRange: { color: ['#50a3ba', '#eac736', '#d94e5d'] }, textStyle: { color: '#fff' } }, //柱形圖設(shè)置 legend:{ data:['調(diào)用次數(shù)','學(xué)校數(shù)','真實(shí)學(xué)校數(shù)'], textStyle:{ color:'#fff' }, top: '1%', selected:{ '調(diào)用次數(shù)':true, '學(xué)校數(shù)':false, '真實(shí)學(xué)校數(shù)':false } }, xAxis: { type: 'category', data:['正式平臺(tái)','培訓(xùn)平臺(tái)','職教+舊平臺(tái)','測(cè)試+演示平臺(tái)'], axisLine:{ lineStyle:{ type:'solid', color:'#fff', width:1 } }, //旋轉(zhuǎn)90度顯示 // axisLabel:{ // rotate:90 // } }, yAxis: [{ name:'調(diào)用次數(shù)', type: 'value', //坐標(biāo)內(nèi)分割線 splitLine:{ lineStyle:{ type:'dashed' } }, axisLine:{ lineStyle:{ color:'#fff', width:1,//這里是為了突出顯示加上的 } } },{//是否顯示數(shù)值分割線 splitLine:{ show:false }, //max:100, axisLine:{ lineStyle:{ color:'#fff', width:1,//這里是為了突出顯示加上的 } } }], grid: { left: '10%', right: '10%', bottom: '7%', containLabel: true }, series: { name:'調(diào)用次數(shù)', id: 'bar1', type: 'bar', //柱形圖添加邊框及陰影 itemStyle:{ normal:{ borderWidth: 1, borderColor: '#fff', shadowBlur: 5, shadowColor: '#99ffff' } }, data: data } }; // 使用剛指定的配置項(xiàng)和數(shù)據(jù)顯示圖表责掏。 myChartSun1.setOption(option); myChartBar1.setOption(option1); </script> </body> </html>
我們創(chuàng)建了初始的直方圖柜砾,顯示在旭日?qǐng)D右方。
Echarts更新動(dòng)畫的方式為重新繪制畫布换衬,而重新繪制畫布會(huì)導(dǎo)致旭日?qǐng)D當(dāng)前下鉆的效果被重置痰驱。如果將兩個(gè)圖表放在一個(gè)容器中,每次更新直方圖瞳浦,旭日?qǐng)D也會(huì)被重置為最初的狀態(tài)担映。只有將兩者分開(kāi),旭日?qǐng)D的下鉆狀態(tài)(根節(jié)點(diǎn)為某個(gè)子節(jié)點(diǎn))才會(huì)被保留叫潦。
當(dāng)前數(shù)據(jù)取自旭日?qǐng)D另萤,自動(dòng)顯示第一層的內(nèi)容。關(guān)于直方圖的坐標(biāo)軸美化方法诅挑,可以參考第一個(gè)故事中的散點(diǎn)圖的設(shè)置∷某ǎ現(xiàn)在的圖表如下所示:
好了,我們成功拼接了兩個(gè)圖表拔妥。接下來(lái)我們需要做的忿危,是將兩個(gè)圖表聯(lián)動(dòng)起來(lái)。
-
新建[mouseover]事件:
為了實(shí)現(xiàn)兩個(gè)圖表的聯(lián)動(dòng)没龙,我們需要新建一個(gè)[mouseover](鼠標(biāo)懸钙坛)事件。當(dāng)鼠標(biāo)懸浮在旭日?qǐng)D的某個(gè)節(jié)點(diǎn)上時(shí)硬纤,若其有子節(jié)點(diǎn)解滓,則根據(jù)其子節(jié)點(diǎn)數(shù)據(jù)重新繪制直方圖。
我們?cè)?lt;script>代碼塊中編碼筝家,寫入該事件洼裤,完整代碼如下:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>ECharts</title> <!-- 引入 echarts.js --> <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts/dist/echarts.min.js"></script> <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts-gl/dist/echarts-gl.min.js"></script> <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts-stat/dist/ecStat.min.js"></script> <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts/dist/extension/dataTool.min.js"></script> <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts/map/js/china.js"></script> <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts/map/js/world.js"></script> <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts/dist/extension/bmap.min.js"></script> <script type="text/javascript" src="https://www.jb51.net/jslib/jquery/jquery.min.js"></script> </head> <body> <!-- 為ECharts準(zhǔn)備一個(gè)具備大小(寬高)的Dom --> <!-- float設(shè)置浮動(dòng)方式溪王,保證兩個(gè)div顯示在同一排(因?yàn)槲覀兊娜萜鲗挾仁亲赃m應(yīng)的) --> <div id="sun1" style="width:50%;height:900px;float:left;"></div> <div id="bar1" style="width:50%;height:900px;float:left;"></div> <script type="text/javascript"> // 基于準(zhǔn)備好的dom腮鞍,初始化echarts實(shí)例 var myChartSun1 = echarts.init(document.getElementById('sun1')); var myChartBar1 = echarts.init(document.getElementById('bar1')); //旭日?qǐng)D所需數(shù)據(jù)結(jié)構(gòu) var data = [{ name: '正式平臺(tái)', value: 9487, children: [{ name: '有地址', value: 9357, children: [{ name: '6選3', value: 2851, children: [{ name: '北京市', value: 2336 },{ name: '山東省', value: 425 },{ name: '天津市', value: 83 },{ name: '上海市', value: 7 }] }, { name: '3+1+2', value: 5321, children: [{ name: '廣東省', value: 2068 },{ name: '福建省', value: 1582, //數(shù)據(jù)下可設(shè)置格式 // itemStyle: { // shadowBlur: 10, // shadowColor: '#99ffff' // }, },{ name: '重慶市', value: 718 },{ name: '江蘇省', value: 301 },{ name: '湖北省', value: 257 },{ name: '河北省', value: 222 },{ name: '湖南省', value: 116 },{ name: '遼寧省', value: 57 }] }, { name: '7選3-浙江', value: 28 }, { name: '未改革', value: 1157 , children:[{ name:'安徽省', value: 460 },{ name:'陜西省', value:286 },{ name:'四川省', value:126 },{ name:'新疆', value:114 },{ name:'云南省', value:66 },{ name:'廣西', value:34 },{ name:'江西省', value:27 },{ name:'甘肅省', value:17 },{ name:'河南省', value:14 },{ name:'山西省', value:13 }] }] }, { name: '無(wú)地址', value: 130 }] }, { name: '培訓(xùn)平臺(tái)', value: 3215, children: [{ name: '智校測(cè)試校', children: [{ name: '培訓(xùn)', value: 1449 }, { name: '排課', value: 1325 }] },{ name:'新課改培訓(xùn)', value: 441 }] }, { name: '測(cè)試+演示平臺(tái)', value: 1046, children: [{ name: '測(cè)試', value: 464 }, { name: '演示', value: 582 } ] }, { name: '職教+舊平臺(tái)', value: 1239 }]; var option = { backgroundColor:'#000', tooltip: { trigger: 'item', formatter: function (params) { return params.name + ' : ' + params.value; } }, visualMap: { min: 0, max: 2000, calculable: true, inRange: { color: ['#50a3ba', '#eac736', '#d94e5d'] }, textStyle: { color: '#fff' } }, series: [{ type: 'sunburst', id:'sunburst1', // highlightPolicy: 'ancestor', data: data, center:['50%','50%'], radius: [10, '90%'], //高亮當(dāng)前及其子區(qū)間 //highlightPolicy: 'descendant', label: { rotate: 'radial', fontSize: 15 }, //選定區(qū)域 emphasis: { itemStyle: { //環(huán)形顏色 color: 'red', //邊框顏色 borderColor: '#fff', shadowBlur: 10, shadowColor: '#99ffff' } }, //高亮區(qū)域 highlight: { itemStyle: { color: 'orange', borderColor: '#fff', shadowBlur: 10, shadowColor: '#99ffff' } }, //非選定區(qū)域 downplay: { itemStyle: { color: '#1e1e1e', shadowBlur: 0, //透明度 opacity: 0.3 }, label: { //透明度 opacity: 0.3 } }, //levels設(shè)置各層次環(huán)形寬度 levels: [{}, { //內(nèi)圈半徑 r0: '10%', //外圈半徑 r: '30%', itemStyle: { //邊框?qū)挾? borderWidth: 2 } }, { r0: '30%', r: '50%', itemStyle: { borderWidth: 2 } }, { r0: '50%', r: '70%', itemStyle: { borderWidth: 2 } }, { r0: '70%', r: '75%', label: { //文字顯示在外側(cè) position: 'outside', //距離環(huán)形的距離 padding: 3, }, itemStyle: { borderWidth: 3, //陰影半徑 shadowBlur: 10, //陰影顏色,當(dāng)前是亮色 shadowColor: '#99ffff' } }] }] }; var option1 = { backgroundColor:'#000', tooltip: { trigger: 'item', formatter: function (params) { return params.name + ' : ' + params.value; } }, visualMap: { min: 0, max: 2000, calculable: true, show: false, seriesIndex:0, inRange: { color: ['#50a3ba', '#eac736', '#d94e5d'] }, textStyle: { color: '#fff' } }, //柱形圖設(shè)置 legend:{ data:['調(diào)用次數(shù)','學(xué)校數(shù)','真實(shí)學(xué)校數(shù)'], textStyle:{ color:'#fff' }, top: '1%', selected:{ '調(diào)用次數(shù)':true, '學(xué)校數(shù)':false, '真實(shí)學(xué)校數(shù)':false } }, xAxis: { type: 'category', data:['正式平臺(tái)','培訓(xùn)平臺(tái)','職教+舊平臺(tái)','測(cè)試+演示平臺(tái)'], axisLine:{ lineStyle:{ type:'solid', color:'#fff', width:1 } }, //旋轉(zhuǎn)90度顯示 // axisLabel:{ // rotate:90 // } }, yAxis: [{ name:'調(diào)用次數(shù)', type: 'value', //坐標(biāo)內(nèi)分割線 splitLine:{ lineStyle:{ type:'dashed' } }, axisLine:{ lineStyle:{ color:'#fff', width:1,//這里是為了突出顯示加上的 } } },{//是否顯示數(shù)值分割線 splitLine:{ show:false }, //max:100, axisLine:{ lineStyle:{ color:'#fff', width:1,//這里是為了突出顯示加上的 } } }], grid: { left: '10%', right: '10%', bottom: '7%', containLabel: true }, series: { name:'調(diào)用次數(shù)', id: 'bar1', type: 'bar', //柱形圖添加邊框及陰影 itemStyle:{ normal:{ borderWidth: 1, borderColor: '#fff', shadowBlur: 5, shadowColor: '#99ffff' } }, data: data } }; //新建mouseover事件莹菱,且僅當(dāng)對(duì)象為series時(shí)啟發(fā)移国,并傳入回調(diào)函數(shù)parmas,parmas包含子節(jié)點(diǎn)的信息 myChartSun1.on('mouseover','series', function (params) { //僅當(dāng)選取對(duì)象為旭日?qǐng)DseriesType===sunburst時(shí)生效 if(params.seriesType === 'sunburst' ){ //新建一個(gè)空的橫坐標(biāo)類目的列表 var xAxisData = []; //存在子元素時(shí)道伟,直方圖顯示子元素結(jié)果 if(params.data.children){ //將橫坐標(biāo)類目push入 xAxisData 中 for(var i = 0; i < params.data.children.length; i++){ xAxisData.push(params.data.children[i].name); }; //重新繪制直方圖 myChartBar1.setOption({ xAxis:{ data:xAxisData }, series:[{ id:'bar1', data: params.data.children }] }) } } }); // 使用剛指定的配置項(xiàng)和數(shù)據(jù)顯示圖表迹缀。 myChartSun1.setOption(option); myChartBar1.setOption(option1); </script> </body> </html>
筆者用通俗語(yǔ)言簡(jiǎn)單解釋一下代碼內(nèi)容。這段代碼完成的工作相當(dāng)簡(jiǎn)單,就是當(dāng)事件觸發(fā)時(shí)祝懂,將當(dāng)前節(jié)點(diǎn)的全部子節(jié)點(diǎn) [name] 信息保存票摇,并傳入給直方圖的橫坐標(biāo),并且將 [data] 替換為全部子節(jié)點(diǎn)的 [value] 值嫂易。根據(jù)這些調(diào)整兄朋,Echarts將自動(dòng)選擇合理的動(dòng)畫效果掐禁,展示新的直方圖怜械。
最終的圖表效果如下:
-
引入新維度的數(shù)據(jù):
所謂引入新的數(shù)據(jù),實(shí)際上是擴(kuò)充直方圖每個(gè)類目下數(shù)據(jù)的項(xiàng)數(shù)傅事。如下圖所示缕允,對(duì)于每個(gè)類目,除了顯示引擎的調(diào)用次數(shù)外蹭越,我們還新增了[學(xué)校數(shù)]和[真實(shí)學(xué)校數(shù)]兩項(xiàng)障本,用以比較三個(gè)數(shù)據(jù)間的比例情況。
這里筆者不再給出完整代碼响鹃,具體的實(shí)現(xiàn)方式讀者可以自己思考驾霜。
-
圖表的意義-它述說(shuō)了怎樣的故事:
數(shù)據(jù)本身是虛擬出來(lái)的,不過(guò)我們可以嘗試分析下通過(guò)圖表能夠獲得的信息买置。
-
目前使用引擎的地區(qū)中粪糙,政策為‘3+1+2’的地區(qū)使用次數(shù)最多,‘6選3’次之忿项,‘未改革’地區(qū)最少蓉冈,說(shuō)明我們的排課引擎主要的用戶還是新高考改革地區(qū)。
‘3+1+2’地區(qū)雖然是改革的第一年轩触,但很快就超越了‘6選3’地區(qū)寞酿。之后的引擎改進(jìn),應(yīng)當(dāng)把‘3+1+2’地區(qū)的政策特征作為主要考慮的對(duì)象(之前主要滿足‘6選3’地區(qū)的需求)脱柱;
引擎的使用集中于幾個(gè)省份伐弹;
讀者可以自己思考下,通過(guò)圖表還可以獲得哪些信息(建議讀者更換自己的真實(shí)數(shù)據(jù)進(jìn)行分析)榨为。
-
故事結(jié)束
第三個(gè)故事主要講解旭日?qǐng)D的使用掸茅,以及如何聯(lián)動(dòng)兩個(gè)圖表。
我們都知道柠逞,扇形圖(旭日?qǐng)D)主要體現(xiàn)比例的分配昧狮,而直方圖主要體現(xiàn)具體的數(shù)值(包括最大值最小值),以及數(shù)值的分布板壮。顯然逗鸣,兩個(gè)圖表在數(shù)據(jù)的抽象化表達(dá)上是互補(bǔ)的。我們將兩個(gè)圖表結(jié)合,并且提供一定的聯(lián)動(dòng)效果撒璧,用戶通過(guò)自己的操作透葛,可以獲得相當(dāng)多的信息。
這種圖表組合其實(shí)代表了一種新的數(shù)據(jù)展示方式卿樱。我們不再生成靜態(tài)圖表僚害,而是引導(dǎo)用戶和圖表進(jìn)行交互。
這種做法保持了圖表的直觀性繁调,同時(shí)又允許讀者按自己的方法來(lái)探索數(shù)據(jù)萨蚕。
是的,在這里我們不僅扮演了數(shù)據(jù)導(dǎo)游的身份蹄胰,還將數(shù)據(jù)本身“玩具化”岳遥。任何一個(gè)用戶,不需要專業(yè)的知識(shí)裕寨,只通過(guò)簡(jiǎn)單的操作就可以去探索數(shù)據(jù)浩蓉。這種獨(dú)特的體驗(yàn),一般的靜態(tài)圖表是無(wú)法帶來(lái)的宾袜。
當(dāng)然捻艳,動(dòng)態(tài)的圖表無(wú)法被引用在ppt(或者所有只能引用靜態(tài)圖片的軟件)中。要么把這個(gè)圖表作為一個(gè)單獨(dú)的h5頁(yè)面庆猫,以超鏈接的形式引用认轨。要么,可以了解下hype4阅悍,應(yīng)用這個(gè)高保真原型繪制工具好渠,將圖表與h5頁(yè)面有機(jī)組合在一起(筆者有hype的操作手冊(cè)編寫計(jì)劃,但是時(shí)間未定)节视。