ECharts是一個由百度開發的純 Javascript 的圖表庫,pyecharts是某三位大佬將ECharts移植到Python項目中的產物,在Python網站中可以更輕松的接入圖表,但是個人感覺pyecharts比ECharts還是局限很大的,pyecharts0.5.x版本就更為縮水了,由於項目之前用的是pyecharts0.5.11版本,圖表比較少,不足以解決問題,甚至自己用js實現了兩個圖表來使用,美觀度比ECharts還是遜色不少,如果將項目遷移到新版pyecharts v1.0.0則更為麻煩,就直接在原來的項目中引入echarts庫來混合使用,pyecharts v1.0.0雖然完善了不少問題,但是加入了新的配置規則,學習起來增加了不少負擔,靈活度也沒有echarts好,個人建議如果項目中使用的圖表不是很復雜,數據靜態的可以使用pyecharts,復雜點的還是盡量使用echarts比較方便,下面開始進入主題:
1. 安裝pyecharts:
pip install pyecharts==0.5.11 #0.5.x的舊版,我目前使用的這個,要用pyecharts的話建議安裝下面的最新版
pip install pyecharts #安裝最新版
pyecharts使用圖表可以直接在視圖代碼里面構建圖表,Django會將其渲染到前端模板頁面中:
# 主體圖-1 def visualPage(request): template = loader.get_template('visualModule/visualPage.html') #載入模板文件 parseArgData() data3D1,weights3D1,bar = drawBar() #得到圖表數據 context = dict( #context添加在模板中要渲染的數據 myechart = bar.render_embed(), #圖表數據 host = DEFAULT_HOST, script_list = bar.get_js_dependencies(), #由pyecharts引入需要用到的js代碼文件 guestSetArgs=startArgsSet, warningdata=argList, data3D=data3D1, weights3D=weights3D1, ) return HttpResponse(template.render(context, request))#
構建圖表函數,這里只粘貼了圖表的接口代碼,數據處理和邏輯代碼略去:
def drawBar(): #繪制 x_axis = ['','','','','','','','','','','',''] #X軸 y_axis = [0,1,2,3,4,5,6,7,8,9,10,11] data = [ #閉源5個 dict( name = "", value=[so[0], sor[0], projects[0][0][""]], itemStyle=dict(color=getColorstr2(0,weights[0])) ), dict( name="", value=[so[4], sor4[2], projects[4][2][""]], itemStyle=dict(color=getColorstr2(4,weights[18])) ), ... ] bar3d = Bar3D("", width=1000, height=500) bar3d.add("",x_axis,y_axis, data, is_visualmap=False, is_xaxis_show=True, is_yaxis_show=False, is_splitline_show=False, xaxis3d_name =' ', yaxis3d_name =' ', #is_label_show =True, mark_point_symbol='circle', is_more_utils=True, mark_point=['max','min'], mark_line=['average'], zaxis3d_name ='評分', xaxis3d_interval =0, grid3d_width=150, grid3d_depth=100, grid3d_shading='realistic', is_grid3d_ratate = True, grid3d_rotate_speed=180, tooltip_formatter=formatter) bar3d.on(MOUSE_CLICK, on_click) return data,weights,bar3d
<!-- 模板代碼--> <div> {{ myechart|safe }} <br> {{radarChart|safe}} </div>
這樣就可以在前端顯示柱狀圖圖表了

另外項目中還使用了一個折線圖也是同樣做法:

其他圖表也是類似添加,可以參考pyecharts官網教程:
https://pyecharts.org/#/
2. 接下來在項目中再引入echarts來使用,和pyecharts混合使用互不影響
安裝可參考echarts官網:
https://www.echartsjs.com/zh/
去https://github.com/apache/incubator-echarts下載echarts源碼包,解壓出來的文件夾里的 dist 目錄里可以找到最新版本的 echarts 庫,直接在前端頁面中引入即可使用echarts圖表,
1 {% for jsfile_name in script_list %} 2 <script src="{{ host }}/{{ jsfile_name }}.js"></script> 3 {% endfor %} 4 5 <script src="{% static 'js/dist/echarts.min.js' %}"></script> 6 <script src="{% static 'js/dist/echarts-gl.js' %}"></script>
<div id="container3" style="height: 800px"></div>
<script type="text/javascript">
//echarts柱狀圖
var dom3 = document.getElementById("container3");
var myChart3 = echarts.init(dom3);
var app = {};
option = null;
var hours = [];
var days = [];
$.get("{% static 'json/eachBar3dData.json' %}",function (json_data) {
var jdata=[];
$(json_data.items).each(function(i,ite){
jdata.push(ite)
})
rectSize=Math.sqrt(json_data.length);
for(var i=0;i<rectSize;i++)
{
hours.push('');
days.push('');
}
option = {
title: {
text: '所有代碼子模塊代碼數量3D柱狀圖',
subtext: '可顯示代碼數量,缺陷情況',
left: 'leafDepth'
},
tooltip: {
formatter:function(params)
{
var errors=0;
for(var i =0;i< json_data.length;i++)
{
if (json_data[i][3]==params.name)
{
errors=json_data[i][4];
break;
}
}
return "<div >"+"文件路徑:"+params.name+'<br>'+
"代碼行數:"+params.value[2]+'<br>'+
"缺陷數量:"+errors+
"</div>";
},
},
visualMap: {
max: 4000,
inRange: {
color: ['#313695', '#4575b4', '#74add1', '#abd9e9', '#e0f3f8', '#ffffbf', '#fee090', '#fdae61', '#f46d43', '#d73027', '#a50026']
}
},
xAxis3D: {
type: 'category',
data: hours,
name: ''
},
yAxis3D: {
type: 'category',
data: days,
name:''
},
zAxis3D: {
type: 'value',
name:'代碼數量'
},
grid3D: {
boxWidth: 200,
boxDepth: 180,
viewControl: {
// projection: 'orthographic'
},
light: {
main: {
intensity: 1.2,
shadow: true
},
ambient: {
intensity: 0.3
}
}
},
/* dataset: {
dimensions: [
'Income',
'Life Expectancy',
'Population',
'Country',
{name: 'Year', type: 'ordinal'}
],
source: json_data
},
*/
series: [{
type: 'bar3D',
data: json_data.map(function (item) {
return {
name:item[3],
value: [item[1], item[0], item[2]],
}
}),
shading: 'lambert',
label: {
textStyle: {
fontSize: 16,
borderWidth: 0
}
},
emphasis: {
label: {
textStyle: {
fontSize: 20,
color: '#900'
}
},
itemStyle: {
color: '#900'
}
}
}]
};
myChart3.setOption(option, true);
});
if (option && typeof option === "object") {
myChart3.setOption(option, true);
}
</script>
</div>
顯示效果:

另外項目中還用到樹形圖表用來表示文件目錄結構:

可鑽入的矩形樹圖:


由於pyecharts0.5.x中不存在這個圖表,pyecharts v1.0.0和echarts中沒有添加還是我沒有認真看也沒有發現這個,就自己實現了和這個類似的鑽入樹形圖表:


同時為了練手也自己實現了一個條形圖表:

圖形條數和形狀是根據數據變化來做適應的,但是美觀度比echarts還是遜色不少
3 . echarts事件交互的使用
項目中使用到一個雷達圖,需要鼠標點擊便簽進入便簽的子圖,也是一個類似的鑽入圖形,邏輯代碼部分較多,省略了getOption( argName)函數中的部分邏輯代碼:
<div id="container" style="height: 800px"></div>
<script type="text/javascript">
var dom = document.getElementById("container");
var myChart = echarts.init(dom);
var app = {};
var weight=1000; //權重的倍數
var weight1=800;
function getOption( argName){
var ardData=[];
if(argName=="閉源特性"){ //判斷點擊文字
var weightBuf= [{{weights3D.0}},{{weights3D.1}},{{weights3D.2}},{{weights3D.3}},{{weights3D.4}},
];
var weightBuf1=[];
weightBuf.forEach(myFunction);
function myFunction(value, index, array) {
weightBuf1.push(value*weight1);
}
ardData=[
{
value : [{{data3D.0.value.2}},{{data3D.1.value.2}},{{data3D.2.value.2}},{{data3D.3.value.2}},{{data3D.4.value.2}},
],
name : '評分'
},
{
value : weightBuf1,
name : '權重'
}
];
option = null;
option = {
title: {
text: '雷達圖',
subtext: '點擊文字要素返回頂層屬性雷達圖',
},
tooltip: {
formatter:function(params)
{
namelist=['正確性', '可靠性', '安全性', '可理解性','代碼熵']
var eachli=params.value;
if (params.name=='權重')
eachli=weightBuf;
return "<div >"+params.name+'<br>'+
namelist[0]+':'+eachli[0]+'<br>'+
namelist[1]+':'+eachli[1]+'<br>'+
namelist[2]+':'+eachli[2]+'<br>'+
namelist[3]+':'+eachli[3]+'<br>'+
namelist[4]+':'+eachli[4]+
"</div>";
},
},
legend: {
data: ['評分(scole)', '權重(weight)']
},
radar: {
// shape: 'circle',
name: {
textStyle: {
color: '#000',
backgroundColor: '#dee',
borderRadius: 3,
padding: [3, 5]
}
},
indicator: [
{ name: '正確性', max: 100},
{ name: '可靠性', max: 100},
{ name: '安全性', max: 100},
{ name: '可理解性', max: 100},
{ name: '代碼熵', max: 100},
],
triggerEvent:true
},
series: [{
name: '評分 vs 權重',
type: 'radar',
// areaStyle: {normal: {}},
data : ardData
}]
};;
}
return option;
}
option=getOption("root");
if (option && typeof option === "object") {
myChart.setOption(option, true);
myChart.on('click', function (params) {
console.log(params);
// alert(params.name);
myChart.setOption(getOption(params.name), true);
});
}
</script>
主要是用
myChart.on('click', function (params) { console.log(params); // alert(params.name); myChart.setOption(getOption(params.name), true); });
來監聽鼠標點擊標簽事件,然后通過getOption來動態構建option顯示,就達到了鑽入效果

點擊之后的鑽入效果

4. 自定義tooltip標簽
在tooltip中定義formatter,params參數為當前活動的元素數據
tooltip: { formatter:function(params) { var errors=0; for(var i =0;i< json_data.length;i++) { if (json_data[i][3]==params.name) { errors=json_data[i][4]; break; } } return "<div >"+"文件路徑:"+params.name+'<br>'+ "代碼行數:"+params.value[2]+'<br>'+ "缺陷數量:"+errors+ "</div>"; }, },
效果:

提示框浮層內容格式器,支持字符串模板和回調函數兩種形式。
1, 字符串模板
模板變量有 {a}, {b},{c},{d},{e},分別表示系列名,數據名,數據值等。 在 trigger 為 'axis' 的時候,會有多個系列的數據,此時可以通過 {a0}, {a1}, {a2} 這種后面加索引的方式表示系列的索引。 不同圖表類型下的 {a},{b},{c},{d} 含義不一樣。 其中變量{a}, {b}, {c}, {d}在不同圖表類型下代表數據含義為:
-
折線(區域)圖、柱狀(條形)圖、K線圖 :
{a}(系列名稱),{b}(類目值),{c}(數值),{d}(無) -
散點圖(氣泡)圖 :
{a}(系列名稱),{b}(數據名稱),{c}(數值數組),{d}(無) -
地圖 :
{a}(系列名稱),{b}(區域名稱),{c}(合並數值),{d}(無) -
餅圖、儀表盤、漏斗圖:
{a}(系列名稱),{b}(數據項名稱),{c}(數值),{d}(百分比)
更多其它圖表模板變量的含義可以見相應的圖表的 label.formatter 配置項。
示例:
formatter: '{b0}: {c0}<br />{b1}: {c1}'
2, 回調函數
回調函數格式:
(params: Object|Array, ticket: string, callback: (ticket: string, html: string)) => string
第一個參數 params 是 formatter 需要的數據集。格式如下:
{ componentType: 'series', // 系列類型 seriesType: string, // 系列在傳入的 option.series 中的 index seriesIndex: number, // 系列名稱 seriesName: string, // 數據名,類目名 name: string, // 數據在傳入的 data 數組中的 index dataIndex: number, // 傳入的原始數據項 data: Object, // 傳入的數據值。在多數系列下它和 data 相同。在一些系列下是 data 中的分量(如 map、radar 中) value: number|Array|Object, // 坐標軸 encode 映射信息, // key 為坐標軸(如 'x' 'y' 'radius' 'angle' 等) // value 必然為數組,不會為 null/undefied,表示 dimension index 。 // 其內容如: // { // x: [2] // dimension index 為 2 的數據映射到 x 軸 // y: [0] // dimension index 為 0 的數據映射到 y 軸 // } encode: Object, // 維度名列表 dimensionNames: Array<String>, // 數據的維度 index,如 0 或 1 或 2 ... // 僅在雷達圖中使用。 dimensionIndex: number, // 數據圖形的顏色 color: string, // 餅圖的百分比 percent: number, }
我這里使用的回調函數,定義雷達圖更方便一點
其他可參考官方文檔教程:
https://www.echartsjs.com/zh/option.html#title
