Flask框架利用ajax数据驱动Echarts可视化

Python的可视化工具

python的数据可视化工具有很多,比如常见的matplotlib,但是讲到视觉效果的华丽,动态的交互,目前最漂亮的应该就是Echarts了。用Echarts可以做出很多漂亮的图形。Python里也有pyecharts,但是这种单一的图表页面做简单展示还可以,做一个完整的项目案例就比较麻烦了。
我对js几乎不懂,不过看了一下语法结构,还是很接近python和C++的,而js的数据传输,一般通过POST+ajax推送json数据完成(也许是我见到太少),这种语句比较常见,把语句做好了解析就可以用到单个需要数据驱动的Echarts上面。这是常见的思路。

Flask驱动Echarts的路线图

  1. 设计图表页面,引用echarts.js,设计图表框架
  2. 图表框架中嵌入接收数据的ajax
  3. Flask发送图表页面echarts.html
  4. Flask发送接送数据json
  5. 浏览器渲染图表页面echarts,运行含有ajax的js之后接收json数据
  6. json数据填充echarts,图表页面渲染完成

从这个路线图看,起始都是flask向浏览器发送数据,对于浏览器来说,只不过是两次"GET",并不是太难。
接下来,分布进行实施。

1.设计图表页面

在head中引入echarts.js
在body中留出一个容器Dom,这都是常见操作

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>ECharts</title>
    <!-- 引入 echarts.js -->
    <script type="text/javascript"  src="{{%20url_for('static',filename='js/echarts.min.js')%20}}"></script>
</head>
<body>
 	<!-- 为ECharts准备一个具备大小(宽高)的Dom -->
    <div id="main" style="width: 600px;height:600px;"></div>
    <!-- 定义echarts结构的JavaScript -->
</body>
</html>

接下来在body中设计JavaScript 定义echarts对象结构。
用item_name代表echarts的X轴名称,item_value代表名称对应的值

  <script type="text/javascript">
        // 基于准备好的dom,初始化echarts实例
        var myChart = echarts.init(document.getElementById('main'));

        //建立ajax所需的json数据
        var json_data=
        {   item_name:[], item_value:[] };

        //发送ajax数据请求
        $(document).ready(function()
        {
            getData();
        });
    </script>

2.图表框架中嵌入接收数据的ajax

接下来,设计接收数据的ajax放到getDta()函数中。
ajax之后,是加载数据到图表中。
再补一个出错处理。
可以看到,ajax接收的是封装的json,也就是文本化的dictionary。这对后台来说,简直太方便了。

  function getData()
         {
                    $.ajax({
		                    url:'/echart_json',  //渲染的是/ehart_json下的json数据
		                    data:{},     //接收数据存放的位置
		                    type:'GET',  //此处是从服务器获取数据,不涉及发送,因此是GET
		                    async:false,  //异步请求 同步请求将会锁住浏览器,用户其他操作必须等待请求完成才可以执行,默认false
		                    dataType:'json',
		                    success:function(data)
		                   {    json_data=data;
		                        // 指定图表的配置项和数据
			                    var option =({
		                       title: {text:'大灯材料类型'},
		                        tooltip: {},
		                        legend: { data:['材料'] },
		                        //X轴是由json发送的字典中item_name获取的
		                        xAxis: { data: json_data['item_name']},
		                        yAxis: {},
		                        //Y轴数据系列1的data是由json发送的字典中item_value获取的
		                        series: [{name: '数量',
		                                    type: 'bar',
		                                    data: json_data['item_value']}]
                        });
                        myChart.hideLoading(); //隐藏加载动画
                        myChart.setOption(option);  // 初次加载图表
                     },
                     
                    //如获取数据失败,则提示
                    error:function(msg)
                    { console.log(msg);
                      alert("数据加载失败!请检查数据链接是否正确");}
                    })

这部分函数设计完成之后,放到刚才的JavaScript中。这段函数是从网上抄的,但是看起来并不是很费力。

3.Flask发送图表页面

在视图代码中加入图表页面的路由代码:

from flask import Flask,Response,request
from flask import url_for
from flask import render_template
import json
app = Flask(__name__)
@app.route('/echarts')
def echarts():
    return render_template('echarts.html',title='echarts')

4.Flask发送图表Json数据

在视图代码中加入发送json数据的路由代码:

def Response_headers(content):
    resp = Response(content)
    resp.headers['Access-Control-Allow-Origin'] = '*'
    return resp
    
@app.route('/echart_json')
def get_data():
    item_name = ['LED', '卤素', '氙气']
    item_value = ['266', '126', '15']
    datas = {'item_name': item_name, 'item_value': item_value}
    # 如果有中文的话,就需要ensure_ascii=False
    content = json.dumps(datas, ensure_ascii=False)
    resp = Response_headers(content)
    return resp

5.浏览器渲染页面接收数据

在这里插入图片描述

6.Echarts格式调整

(1) 以下是柱状图的参数设置,参考博客:https://blog.csdn.net/qq_42816550/article/details/91604978
写的非常清楚,用心了。
版权声明:本文为CSDN博主「除了奋斗别无选择」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上

//定义图表option  
            var option = {  
                //标题,每个图表最多仅有一个标题控件,每个标题控件可设主副标题  
                title: {  
                    //主标题文本,'\n'指定换行  
                    text: '2013年广州降水量与蒸发量统计报表',  
                    //主标题文本超链接  
                    link: 'http://www.tqyb.com.cn/weatherLive/climateForecast/2014-01-26/157.html',  
                    //副标题文本,'\n'指定换行  
                    subtext: 'www.stepday.com',  
                    //副标题文本超链接  
                    sublink: 'http://www.stepday.com/myblog/?Echarts',  
                    //水平安放位置,默认为左侧,可选为:'center' | 'left' | 'right' | {number}(x坐标,单位px)  
                    x: 'left',  
                    //垂直安放位置,默认为全图顶端,可选为:'top' | 'bottom' | 'center' | {number}(y坐标,单位px)  
                    y: 'top'  
                },  
                //提示框,鼠标悬浮交互时的信息提示  
                tooltip: {  
                    //触发类型,默认('item')数据触发,可选为:'item' | 'axis'  
                    trigger: 'axis'  
                },  
                //图例,每个图表最多仅有一个图例  
                legend: {  
                    //显示策略,可选为:true(显示) | false(隐藏),默认值为true  
                    show: true,  
                    //水平安放位置,默认为全图居中,可选为:'center' | 'left' | 'right' | {number}(x坐标,单位px)  
                    x: 'center',  
                    //垂直安放位置,默认为全图顶端,可选为:'top' | 'bottom' | 'center' | {number}(y坐标,单位px)  
                    y: 'top',  
                    //legend的data: 用于设置图例,data内的字符串数组需要与sereis数组内每一个series的name值对应  
                    data: ['蒸发量','降水量']  
                },  
                //工具箱,每个图表最多仅有一个工具箱  
                toolbox: {  
                    //显示策略,可选为:true(显示) | false(隐藏),默认值为false  
                    show: true,  
                    //启用功能,目前支持feature,工具箱自定义功能回调处理  
                    feature: {  
                        //辅助线标志  
                        mark: {show: true},  
                        //dataZoom,框选区域缩放,自动与存在的dataZoom控件同步,分别是启用,缩放后退  
                        dataZoom: {  
                            show: true,  
                             title: {  
                                dataZoom: '区域缩放',  
                                dataZoomReset: '区域缩放后退'  
                            }  
                        },  
                        //数据视图,打开数据视图,可设置更多属性,readOnly 默认数据视图为只读(即值为true),可指定readOnly为false打开编辑功能  
                        dataView: {show: true, readOnly: true},  
                        //magicType,动态类型切换,支持直角系下的折线图、柱状图、堆积、平铺转换  
                        magicType: {show: true, type: ['line', 'bar']},  
                        //restore,还原,复位原始图表  
                        restore: {show: true},  
                        //saveAsImage,保存图片(IE8-不支持),图片类型默认为'png'  
                        saveAsImage: {show: true}  
                    }  
                },  
                //是否启用拖拽重计算特性,默认关闭(即值为false)  
                calculable: true,  
                //直角坐标系中横轴数组,数组中每一项代表一条横轴坐标轴,仅有一条时可省略数值  
                //横轴通常为类目型,但条形图时则横轴为数值型,散点图时则横纵均为数值型  
                xAxis: [  
                    {  
                        //显示策略,可选为:true(显示) | false(隐藏),默认值为true  
                        show: true,  
                        //坐标轴类型,横轴默认为类目型'category'  
                        type: 'category',  
                        //类目型坐标轴文本标签数组,指定label内容。 数组项通常为文本,'\n'指定换行  
                        data: ['1月','2月','3月','4月','5月','6月','7月','8月','9月','10月','11月','12月']  
                    }  
                ],  
                //直角坐标系中纵轴数组,数组中每一项代表一条纵轴坐标轴,仅有一条时可省略数值  
                //纵轴通常为数值型,但条形图时则纵轴为类目型  
                yAxis: [  
                    {  
                        //显示策略,可选为:true(显示) | false(隐藏),默认值为true  
                        show: true,  
                        //坐标轴类型,纵轴默认为数值型'value'  
                        type: 'value',  
                        //分隔区域,默认不显示  
                        splitArea: {show: true}  
                    }  
                ],  
                  
                //sereis的数据: 用于设置图表数据之用。series是一个对象嵌套的结构;对象内包含对象  
                series: [  
                    {  
                        //系列名称,如果启用legend,该值将被legend.data索引相关  
                        name: '蒸发量',  
                        //图表类型,必要参数!如为空或不支持类型,则该系列数据不被显示。  
                        type: 'bar',  
                        //系列中的数据内容数组,折线图以及柱状图时数组长度等于所使用类目轴文本标签数组axis.data的长度,并且他们间是一一对应的。数组项通常为数值  
                        data: [2.0, 4.9, 7.0, 23.2, 25.6, 76.7, 135.6, 162.2, 32.6, 20.0, 6.4, 3.3],  
                        //系列中的数据标注内容  
                        markPoint: {  
                            data: [  
                                {type: 'max', name: '最大值'},  
                                {type: 'min', name: '最小值'}  
                            ]  
                        },  
                        //系列中的数据标线内容  
                        markLine: {  
                            data: [  
                                {type: 'average', name: '平均值'}  
                            ]  
                        }  
                    },  
                    {  
                        //系列名称,如果启用legend,该值将被legend.data索引相关  
                        name: '降水量',  
                        //图表类型,必要参数!如为空或不支持类型,则该系列数据不被显示。  
                        type: 'bar',  
                        //系列中的数据内容数组,折线图以及柱状图时数组长度等于所使用类目轴文本标签数组axis.data的长度,并且他们间是一一对应的。数组项通常为数值  
                        data: [2.6, 5.9, 9.0, 26.4, 28.7, 70.7, 175.6, 182.2, 48.7, 18.8, 6.0, 2.3],  
                        //系列中的数据标注内容  
                        markPoint: {  
                            data: [  
                                {type: 'max', name: '最大值'},  
                                {type: 'min', name: '最小值'}  
                            ]  
                        },  
                        //系列中的数据标线内容  
                        markLine: {  
                            data: [  
                                {type: 'average', name: '平均值'}  
                            ]  
                        }  
                    }  
                ]  
            };  
                  
            //为echarts对象加载数据              
            myChart.setOption(option);  
        }  
    );  

(2)还有一个比较重要的是formatter的设置
这是整个图形的tooltip的formatter,可以设置鼠标经过的提示文字

tooltip: {
                            trigger: 'item',
                            折线(区域)图、柱状(条形)图、K线图 : {a}(系列名称),{b}(类目值),{c}(数值), {d}(无)
							散点图(气泡)图 : {a}(系列名称),{b}(数据名称),{c}(数值数组), {d}(无)
							地图 : {a}(系列名称),{b}(区域名称),{c}(合并数值), {d}(无)
							饼图、仪表盘、漏斗图: {a}(系列名称),{b}(数据项名称),{c}(数值), {d}(百分比)
                            formatter:  "{a} <br/>{c} ({d}%)" //显示 “系列名称 系列名称 20 (50%)”之类的效果
             }               

还有series里label的famatter设置:

  itemStyle: { normal:
                                                  { label: 
                                                    {formatter: "{c}\n{d}%",
                                                        show: true,
                                                        position: "inside",
                                                        textStyle: {fontWeight: "bolder", fontSize: "12",color: "#000000" } }
                                                  }
                                               }

可以在饼图里显示数量下一行百分比的效果。

7.Echarts最终效果

以下是调整后的最终效果,该有的都有了
关键的是json数据在后台输入,利用pymysql查询数据库转json这个难度就非常小了。
所以,通过这种方式,打通数据库与可视化Echarts界面的连接,可以说一件非常有意义的事情。
在这里插入图片描述
在这里插入图片描述


版权声明:本文为qq_43662503原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。