分享

pyecharts和echarts的混合使用

 __天眼__ 2021-02-17

  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会将其渲染到前端模板页面中:

复制代码
# 主体图-1def 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:///#/

2. 接下来在项目中再引入echarts来使用,和pyecharts混合使用互不影响

安装可参考echarts官网:

https://www./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./zh/option.html#title

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多