zoukankan      html  css  js  c++  java
  • echarts使用多图的表达

    记录瞬间

    在实际的工作中总会遇到一些报表的展示问题,echarts作为百度的开源工具针对作图来说是不二选择。

    教程链接: https://echarts.apache.org/zh/tutorial.html#5%20%E5%88%86%E9%92%9F%E4%B8%8A%E6%89%8B%20ECharts

    参数设置:https://echarts.apache.org/zh/option.html#title

    本文主要介绍使用echarts时关于一批关联数据,展示到一张图上的方法

    主要应用:flask+bootstrap+echarts

    由于使用flask的三方插件(pyecharts)在灵活处理非图表数据时较为复杂,所以需要考虑,单独使用echarts进行考虑

    先将flask的pyecharts实现简单代码作以展示

    def render_result(data):
        from pyecharts.charts import Bar, Grid, Timeline
        from pyecharts import options as opts
        # 内置主题类型可查看 pyecharts.globals.ThemeType
        from pyecharts.globals import ThemeType
        from pyecharts.globals import CurrentConfig
        from jinja2 import Markup, Environment, FileSystemLoader
        from pyecharts.commons.utils import JsCode
        # 关于 CurrentConfig,可参考 [基本使用-全局变量]
        CurrentConfig.GLOBAL_ENV = Environment(loader=FileSystemLoader("./templates/echarts"))
        # js代码
        js_code_str = '''
                            function(params){
                            return params.data.text;
                            }
                            '''
    
        all_bar_keys = []
        # 获取所有的key数据  result是从执行结果的数据信息中获取的数据,不是最完整的数据结果
        for get_data in data:
            all_bar_keys += data[get_data]['result'].keys()
        # 去重
        get_bar_keys = list(set(all_bar_keys))  # 所有模块名称去重后的结果
        get_bar_keys.sort()                     # 排序保证每次显示的结果一致
        all_keys = list(data.keys())            # 获取执行的所有时间区间的值
        all_keys.sort(reverse=True)                         # 按照大小进行排序
        bar = (
            Bar(init_opts=opts.InitOpts(theme=ThemeType.LIGHT))
            .add_xaxis([i for i in range(1, len(all_keys))])
            .set_global_opts(title_opts=opts.TitleOpts(title="结果展示", subtitle="统计当前展示结果"),
                             tooltip_opts=opts.TooltipOpts(formatter=JsCode(js_code_str)),
                             toolbox_opts=opts.ToolboxOpts(is_show=True,
                                                           feature={"saveAsImage": {},
                                                                    "dataZoom": {"yAxisIndex": "none"},
                                                                    "restore": {},
                                                                    "magicType": {"show": True, "type": ["line", "bar",
                                                                                                         "stack"]}})
                             )
        )
    
        for bar_key in get_bar_keys:  # 遍历所有的模块数据
            get_list = []  # 保存执行结果中的,未出现模块个数数据,但不是最准确的数据结果
    
            temp_dict = {"value": 0, "text": ""}
            for data_key in all_keys:  # 遍历所有时间区间,筛选出符合相关模块的query词
                temp_dict["text"] = data_key + "<br>" + bar_key
                if bar_key in data[data_key]['result']:  # 结果是从执行query词的结果中获取的,不是最准确的结果,可参考
                    temp_dict["value"] = len(data[data_key]['result'][bar_key])
                    get_list.append(copy.deepcopy(temp_dict))
                else:
                    temp_dict["value"] = 0
                    get_list.append(copy.deepcopy(temp_dict))
    
            bar_ = (
                Bar()
                .add_xaxis([i for i in range(1, len(all_keys))])
                .add_yaxis(bar_key, get_list)
            )
            bar.overlap(bar_)
    
        get_all_order_dict = {}
        all_bar = []    # 保存所有模块下的柱状图
        row_list = []   # 记录行数据
        count = 1       # 遍历所有模块,每增加一个模块进行 +1 处理
        revise = 0      # 数据校正标记
        for bar_key in get_bar_keys:  # 遍历所有的模块数据
            get_all_order_dict[bar_key] = []
            for data_key in all_keys:
                if bar_key in data[data_key]['result']:
                    for word in data[data_key]['result'][bar_key]:
                        if word not in get_all_order_dict[bar_key]:
                            get_all_order_dict[bar_key].append(word)
            get_len = len(str(get_all_order_dict[bar_key]))  # 获取所有词的长度
            rows = int(get_len / 85) + 1                     # 除以95后,获取需要分几行,每行在乘以30就可以获取到词位置的高度了
            
            title_pos = 460 + 330 * (count - 1) + revise
            
            legend_pos = 510 + 330 * (count - 1) + revise
            row_list.append(rows)
            if row_list[count - 1] > 3:
                revise += (row_list[count - 1] - 3) * 30
            print(title_pos, legend_pos, revise)
            key_bar = (
                Bar(init_opts=opts.InitOpts(theme=ThemeType.DARK))
                .add_xaxis([i for i in range(1, len(all_keys))])
                .set_global_opts(title_opts=opts.TitleOpts(title="关键字统计展示-{}".format(bar_key),
                                                           subtitle="统计当前出现了关键字的相关词展示结果",
                                                           pos_top="{}px".format(title_pos)),
                                 tooltip_opts=opts.TooltipOpts(formatter=JsCode(js_code_str)),
                                 legend_opts=opts.LegendOpts(pos_top="{}px".format(legend_pos),
                                                             is_show=True, selected_mode='single'))
                # selected_mode 可以使用“single”、“multiple”使用单选或多选模式,默认为multiple
            )
            count += 1
            for word in get_all_order_dict[bar_key]:
                get_keys = []               # 保存所有模块的对应query词的个数数据,准确的结果
                temp_dict = {"value": 0, "text": ""}
                for data_key in all_keys:   # 遍历结果数据
                    temp_dict["text"] = word + '<br>' + data_key + '<br>' + bar_key
                    if bar_key in data[data_key]["keys_order"]:
                        if word in data[data_key]["keys_order"][bar_key]:
                            temp_dict['value'] = 1
                            get_keys.append(copy.deepcopy(temp_dict))
                        else:
                            temp_dict['value'] = 0
                            get_keys.append(copy.deepcopy(temp_dict))
                    else:
                        temp_dict['value'] = 1
                        get_keys.append(copy.deepcopy(temp_dict))
                key_bar_ = (
                    Bar()
                    .add_xaxis([i for i in range(1, len(all_keys))])
                    .add_yaxis(word, get_keys)
                )
                key_bar.overlap(key_bar_)
            all_bar.append(copy.deepcopy(key_bar))
    
        grid = Grid(init_opts=opts.InitOpts(theme=ThemeType.LIGHT, width='1100px', height='{}px'.format(700+len(row_list)*365)))
        grid.add(bar, grid_opts=opts.GridOpts(pos_left="5%", pos_right="1%", height="350px"))
        # grid.add(key_bar, grid_opts=opts.GridOpts(pos_top="520px", pos_left="5%", pos_right="1%", height="30%"))
        count = 1    # 循环展示模块的柱形图
        revise = 0   # 校正数据
        for key_bar in all_bar:
            # grid_pos = 600 + (240 + (sum(row_list[:count])) * 30) * (count - 1)
            if row_list[count - 1] > 3:
                revise += (row_list[count - 1] - 3) * 30
            grid_pos = 600 + 330 * (count - 1) + revise
            grid.add(key_bar, grid_opts=opts.GridOpts(pos_top="{}px".format(grid_pos), pos_left="5%",
                                                      pos_right="1%", height="150px"))
            count += 1
        # return Markup(bar.render_embed())
        return grid.render_embed()

    方法调用如下:

     1 @ots.route('aisi_summary', methods=["GET"])
     2 def aisi_summary():
     3     get_time = get_time_section(96, flag=True)[1]
     4     get_objs = TempData.objects(CREATE_TIME__gte=get_time).all()
     5     if get_objs and len(get_objs) > 85:
     6         data = sfo.aisi_summary()
     7         from jinja2 import Markup
     8         get_render = render_result(data=data)
     9         return Markup(get_render)       # 直接渲染结果
    10     else:
    11         # 准备数据过程中
    12         try:
    13             executor.submit(sfo.aisi_summary, flag=True)
    14         except:
    15             pass
    16         return render_template("aisi_summary.html", error="数据修整中,请稍后重试!")

    当然使用前提是需要安装pyecharts,并将pyecharts下面的模板放到templates目录下,才可以正常展示结果。

    此结果是按照既定的pyecharts的模板进行渲染展示的,所以很大程度上无法进行非图表数据的展示

     


     

    # 引入echarts

    我们希望在展示图表数据的过程中,还要展示其他的数据,比如:判断结果,表格,说明等等

    过程分为:1、数据准备;2、渲染页面;3、展示结果

    数据准备代码

     1 def total_result_for_data(data):
     2     result = {"height": 0, "x": [], "y": [], "title": ['结果概览'], "count": 0}
     3     all_bar_keys = []
     4     # 获取所有的key数据  result是从执行结果的数据信息中获取的数据,不是最完整的数据结果
     5     for get_data in data:
     6         all_bar_keys += data[get_data]['result'].keys()
     7     # 去重
     8     get_bar_keys = list(set(all_bar_keys))   # 所有模块名称去重后的结果
     9     get_bar_keys.sort()                      # 排序保证每次显示的结果一致
    10     result['title'] += get_bar_keys          # 主标题设置
    11     result['count'] = len(result['title'])   # 记录显示的柱形图的个数
    12     all_keys = list(data.keys())             # 获取执行的所有时间区间的值
    13     all_keys.sort(reverse=True)              # 按照大小进行排序
    14     result['all_keys'] = all_keys
    15     result['x'] = [i for i in range(1, len(all_keys)+1)]   # 生成x轴刻度
    16     # 总体数据展示结果
    17     get_all_order_dict = {}
    18     row_list = []  # 记录行数据
    19     count = 1      # 遍历所有模块,每增加一个模块进行 +1 处理
    20     result['结果概览_source'] = []
    21     result['结果概览'] = get_bar_keys
    22     result['grid_pos'] = [100]
    23     for bar_key in get_bar_keys:
    24         set_date_key = {"name": bar_key, "type": "bar", "data": [], "label": {"show": "true"}}
    25         for data_key in all_keys:           # 遍历所有时间区间,筛选出符合相关模块的query词
    26             temp_dict = {"value": 0, "text": data_key + '===' + bar_key}
    27             get_all_order_dict[bar_key] = []
    28             if bar_key in data[data_key]['result']:  # 结果是从执行query词的结果中获取的
    29                 data_value = len(data[data_key]['result'][bar_key])
    30                 temp_dict["value"] = len(data[data_key]['result'][bar_key])
    31             else:
    32                 temp_dict["value"] = 0
    33                 data_value = 0
    34             set_date_key["data"].append(copy.deepcopy(temp_dict))
    35             if bar_key in data[data_key]['result']:
    36                 for word in data[data_key]['result'][bar_key]:
    37                     if word not in get_all_order_dict[bar_key]:
    38                         get_all_order_dict[bar_key].append(word)
    39         result['结果概览_source'].append(copy.deepcopy(set_date_key))
    40     print(result['结果概览_source'])
    41     for bar_key in get_bar_keys:            # 遍历所有的模块数据
    42         result[bar_key + "_source"] = []
    43         get_all_order_dict[bar_key] = []
    44         for data_key in all_keys:           # 遍历所有时间区间,筛选出符合相关模块的query词
    45             if bar_key in data[data_key]['result']:
    46                 for word in data[data_key]['result'][bar_key]:
    47                     if word not in get_all_order_dict[bar_key]:
    48                         get_all_order_dict[bar_key].append(word)
    49         result[bar_key] = copy.deepcopy(get_all_order_dict[bar_key])
    50 
    51         get_len = len(str(get_all_order_dict[bar_key]))  # 获取所有词的长度
    52         rows = int(get_len / 85) + 1            # 除以85后,获取需要分几行,每行在乘以30就可以获取到词位置的高度了
    53 
    54         result['grid_pos'].append(70 + 30 * rows)
    55 
    56         count += 1
    57         for word in get_all_order_dict[bar_key]:
    58             set_date_key = {"name": word, "type": "bar", "data": [], "label": {"show": "true"}}
    59             for data_key in all_keys:  # 遍历结果数据
    60                 temp_dict = {"value": 0, "text": word + '===' + data_key + '===' + bar_key}
    61                 if bar_key in data[data_key]["keys_order"]:
    62                     if word in data[data_key]["keys_order"][bar_key]:
    63                         temp_dict["value"] = 1
    64                     else:
    65                         temp_dict["value"] = 0
    66                 else:
    67                     temp_dict["value"] = 1
    68                 set_date_key["data"].append(copy.deepcopy(temp_dict))
    69             result[bar_key + "_source"].append(copy.deepcopy(set_date_key))
    70         print(result[bar_key + "_source"])
    71 
    72     result['height'] = (len(row_list) + 1) * 365
    73 
    74     return result

    前端代码如下

      1 <!DOCTYPE html>
      2 <html lang="en">
      3 <head>
      4     <meta charset="UTF-8">
      5 
      6     <meta name="viewport" content="width=device-width, initial-scale=1">
      7     <meta name="description" content="">
      8     <meta name="generator" content="Hugo 0.84.0">
      9     <title>数据分析</title>
     10     <link href="{{ url_for('static', filename='bs/css/bootstrap.min.css') }}" rel="stylesheet">
     11     <link href="{{ url_for('static', filename='bs/css/carousel.css') }}" rel="stylesheet">
     12     <!-- 引入echarts -->
     13     <script src="/static/js/echarts.min.js"></script>
     14 </head>
     15 <body>
     16 {% include "common/header.html" %}
     17 
     18 <div class="container">
     19     <main>
     20         <div style="margin-top:25px">
     21             <nav aria-label="breadcrumb">
     22               <ol class="breadcrumb">
     23                 <li class="breadcrumb-item"><a href="#">监控</a></li>
     24                 <li class="breadcrumb-item active" aria-current="page">数据分析</li>
     25               </ol>
     26             </nav>
     27         </div>
     28     <div class="px-4 py-5 my-5 text-left">
     29         {% if error %}
     30         <span style="color: #e4393c">{{ error }}</span>
     31         {% endif %}
     32     <table class="table table-hover">
     33         <tr><th style="text-align: center;font-size: 0.8cm;background-color: #c8e0cf">结果一览</th></tr>
     34         <tr>
     35             <td>
     36                 <div id="main_picture"></div>
     37             </td>
     38         </tr>
     39         {% for foo in range(data.count) %}
     40         <tr>
     41             <td>
     42                 <div id="main_picture_{{ foo }}"></div>
     43             </td>
     44         </tr>
     45         {% endfor %}
     46     </table>
     47 
     48     </div>
     49     </main>
     50 </div>
     51 
     52 {% include "common/footer.html" %}
     53 
     54 <script src="/static/bs/js/bootstrap.bundle.min.js"></script>
     55 
     56 <script type="text/javascript">
     57     let temp_str = "{{ data }}".replace(/&#39;/g, '"');
     58     // 将接受的数据转换为json对象
     59     let obj = eval("("+temp_str+")");
     60     {% if data %}
     61         init(obj);
     62     {% endif %}
     63 
     64     function init(obj){
     65         console.log(obj);
     66         let num = obj.count;
     67         let xdata = obj.x;
     68         let title_data = obj.title;
     69         let grid_pos = obj.grid_pos
     70         for (let mpnum=0; mpnum<num; mpnum++){
     71             let main_picture = document.getElementById('main_picture_' + mpnum);
     72             //计算所需要的高度
     73             if (mpnum === 0) {
     74                 main_picture.style.height = "440px";
     75             } else {
     76                 main_picture.style.height = 150 + grid_pos[mpnum] + "px";
     77             }
     78             // 基于准备好的dom,初始化echarts实例
     79             let myChart = echarts.init(main_picture);
     80             let toolbox = [];      // 设置
     81             let legend = [];       // 图例显示
     82 
     83             //通过配置xAxi和yAxis的gridIndex  series的xAxisIndex和yAxisIndex 来配套格子
     84             let option = {
     85                 title: {
     86                       textAlign: "left",
     87                       text: title_data[mpnum],
     88                       subtext: title_data[mpnum],
     89                       top: "0px"
     90                 },
     91                 xAxis: {
     92                     type: "category",
     93                     data: xdata
     94                 },
     95                 yAxis: {
     96                   type: "value",
     97                   inverse: false,
     98                   splitLine: {
     99                     show: true
    100                   }
    101                 },
    102                 series: obj[title_data[mpnum]+"_source"],
    103                 grid: {
    104                     left: "3%",
    105                     right: "1%",
    106                      "95%",
    107                     top: grid_pos[mpnum] + "px"
    108                 }
    109             };
    110             // 工具栏设置
    111             if (mpnum === 0) {
    112                 toolbox.push({
    113                     show: true,
    114                     feature: {
    115                         mark: {show: true},
    116                         dataZoom: {show: true},
    117                         dataView: {show: true,readOnly: false},
    118                         magicType: {show: true,type: ['line', 'bar', 'stack']},
    119                         restore: {show: true},
    120                         saveAsImage: {show: true}
    121                     }
    122                 });
    123             } else {
    124                 toolbox.push({
    125                     show: false
    126                 });
    127             }
    128             option["toolbox"] = toolbox[0];
    129             option["tooltip"] = {
    130                 position: "top",
    131                 formatter: function (params) {
    132                     return params.data.text.replace(/===/g, "<br>");
    133                 }
    134             };
    135 
    136             // 图例设置
    137             if (mpnum === 0){
    138                 legend.push({
    139                     selectedMode: 'multiple',
    140                     top: "60px",
    141                     show: true
    142                 });
    143             } else {
    144                 legend.push({
    145                     selectedMode: 'single',
    146                     top: "60px",
    147                     show: true
    148                });
    149             }
    150             option["legend"] = legend[0];
    151             // 使用刚指定的配置项和数据显示图表。
    152             myChart.setOption(option);
    153         }
    154     }
    155 </script>
    156 </body>
    157 </html>

    展示结果如图

     当然图表都是动态加载的,整图下面还有其他的图表,由于截屏关系只截取当前两张

    注意:当前使用的都是最新的版本(bootstrap-v5.0、echarts-5.1.2)


    供参考---结束了

    ===

  • 相关阅读:
    OpenVAS安装过程
    网络攻防环境搭建
    kali linux 安装过程
    20159217《网络攻防实践》第三周学习总结
    网络攻防实践第二周学习总结
    移动平台课程总结
    Android实践项目汇报
    性能测试四十六:Linux 从网卡模拟延时和丢包的实现
    性能测试四十五:性能测试策略
    性能测试四十四:性能优化思路
  • 原文地址:https://www.cnblogs.com/wozijisun/p/15124209.html
Copyright © 2011-2022 走看看