flask+echarts地图制作心得

先看最终效果图。

该地图显示的是公司在各个市区的项目数量,然后统计其数量,并以热点的方式显示在地图上,使使用者能直观的看到公司项目分布及数量情况。

现将程序制作过程中的问题及注意情况分解如下:

1.数据格式。

看了echarts网站的示例可知,要展示数据,需要有2个数据字段,分别是data与geoCoordMap,geoCoordMap是一个地名+坐标的数据,为了获取坐标,我做了一个程序,用于自动化获取城市坐标,并写入到数据库里面。

#获取城市经纬度
def Get_Urt(address):
    # 以get请求为例http://api.map.baidu.com/geocoder/v2/?address=百度大厦&output=json&ak=你的ak
    queryStr = '/geocoding/v3/?address=%s&output=json&ak=你的ak' % address#你的ak指的是自己去百度申请的ak
      
    #由于URL里面含有中文,所以需要用parse.quote进行处理,然后返回最终可调用的url
    url = parse.quote("http://api.map.baidu.com"+queryStr, safe="/:=&?#+!$,;'@()*[]")  
    res = requests.get(url=url)
    
    res_json = json.loads(res.text)
    jwd_res = res_json['result']['location']
    #print(jwd['lng'],'-',jwd['lat'])
    return jwd_res

if __name__ == '__main__':

    #print(jwd['lng'],'-',jwd['lat'])
    city_list = City_Jwd_Sql()
    #使用循环,查出城市的经纬度
    for x in range(len(city_list)):
        cityname = city_list[x][1]
        cityno = city_list[x][0]
        jwd = Get_Urt(cityname)
        lng = jwd['lng']
        lat = jwd['lat']
        #print(cityno,cityname,jwd['lng'],'-',jwd['lat'])
    #将查询到的城市经纬度插入到对应的记录行中
        status = Update_City_Jwd(lng,lat,cityno,cityname)
        print(cityname,status)
    

运行完程序后,我数据库表的字段内容如下。xmsl是数量,lng经度,lat纬度。这样就能把data与geoCoordMap要的数据都做到一张表里面了。

有了数据来源之后,需要对数据进行整理,按照echarts的要求,把数据整理成规定的格式。

后端脚本如下,数据返回的是一个字典格式。

#map地图首页
@server.route('/map',methods=['GET'])#
def map_web():
    #print('map')
    return render_template('map.html')
    
#地图数据    
@server.route("/mdt",methods=['GET']) 
def mdt():
    city_sql = sql_echarts.City_Project_Shu_Sql()
    print({'data':city_sql})
    return jsonify({'data':city_sql})

print出来的字典数据格式如下:

2.前端使用后端返回的数据

后端返回了一个data字典,前端要怎么调整格式,使其满足echarts的格式要求呢?这里我参考了文哥在知乎的一个视频,地址是:使用flask加echarts5.x进行地图大屏显示,值得观看 - 知乎 有兴趣的可以看下。

$(function () {
		$.ajax({
			url:'/mdt',
			type:'get',
			success:function (cityres) {
			var data = new Array();
			var geoCoordMap = new Object();
				for (var i = 0;i < cityres.data.length; i++){
					data[i] = {
						name : cityres.data[i].cityname,
						value : cityres.data[i].xmsl
					};
					geoCoordMap[cityres.data[i].cityname] = [cityres.data[i].lng,cityres.data[i].lat];
				};


const convertData = function (data) {
  var res = [];
  for (var i = 0; i < data.length; i++) {
    var geoCoord = geoCoordMap[data[i].name];
    if (geoCoord) {
      res.push({
        name: data[i].name,
        value: geoCoord.concat(data[i].value),
		visualMap: true
      });
    }
  }
  return res;
};
...//后续的脚本
}

其实在看文哥视频之前,我虽然能把data与geoCoordMap按照格式生成出来,通过console.log也能显示出合规的数据,但是地图上却一直无法把我的数据显示出来,看了文哥的视频后我发现,他把前端的网页脚本调整了一下顺序。

 示例文件是先生成了data与geoCoordMap,然后在option中引用这2个变量。但是我在我的代码中同样的操作的时候,地图上就是显示不出数据,后来发现文哥的视频代码是把地图的一些样式设置脚本先显示出来,然后在get到数据后,再把后续的数据引用及整理脚本带出来(因此有2个myChart.setOption())。我把的前端代码全部贴出来,大家可以对照echarts的代码来看。

<!--
    THIS EXAMPLE WAS DOWNLOADED FROM https://echarts.apache.org/examples/zh/editor.html?c=effectScatter-bmap
-->
<!DOCTYPE html>
<html style="height: 100%">
    <head>
        <meta charset="utf-8">
		<!-- 去除百度logo -->
		<style type="text/css">
			.anchorBL{
				display:none
					}
		</style>
    </head>
    <body style="height: 100%; margin: 0">
        <div id="container" style="height: 100%"></div>

		<script type="text/javascript" src="../static/js/echarts.js"></script>
		<script type="text/javascript" src="../static/js/china.js"></script>
		<script type="text/javascript" src="../static/js/vintage.js"></script> 
		<script type="text/javascript" src="../static/js/jquery.min.js"></script>
		<script type="text/javascript" src="../static/js/bmap.js"></script>
		<script src="http://api.map.baidu.com/api?v=2.0&ak=你的ak"></script>
        <script type="text/javascript">
		
		
var dom = document.getElementById("container");
var myChart = echarts.init(dom);
var app = {};

var option,option_a,option_b;

//第一次进行myChart.setOption
myChart.setOption({
  title: {
    text: 'XX集团项目所在地热图',
    //subtext: 'data from PM25.in',
    //sublink: 'http://www.pm25.in',
    left: 'center'
  },
  tooltip: {
    trigger: 'item'
  },

  bmap: {
    //center: [108.3734508258, 22.8226066012],//南宁市为中心
	map: "china",
    center: [108.9464655506, 37.2472688166],//西安市为中心
    zoom: 5,
    roam: true,
	label: {
		emphasis: {
		show: false
		}
	},
          itemStyle: {
            normal: {
              areaColor: "#0d0059",
              borderColor: "#389dff",
              borderWidth: 1, //设置外层边框
              shadowBlur: 5,
              shadowOffsetY: 8,
              shadowOffsetX: 0,
              shadowColor: "#01012a"
            },
            emphasis: {
              areaColor: "#184cff",
              shadowOffsetX: 0,
              shadowOffsetY: 0,
              shadowBlur: 5,
              borderWidth: 0,
              shadowColor: "rgba(0, 0, 0, 0.5)"
            }
          }
  },

//设置散点圈颜色
  visualMap: {
                    show:true,
					type: 'piecewise',// 定义为分段型piecewise,如定义为连续型则 continuous ,
					splitNumber:6, 
					pieces: [                           //自定义『分段式视觉映射组件(visualMapPiecewise)』的每一段的范围,以及每一段的文字,以及每一段的特别的样式
								//{min: 0, label: 'aaaa'},                     // 不指定 max,表示 max 为无限大(Infinity)。
								{min: 1, max: 10, label: '项目数:1-10个', color: '#006400'}, // 表示 value 1至10 的情况(即区间)。
								{min: 11, max: 50, label: '项目数:11-50个', color: '#FF8C00'}, 
								{min: 51, max: 100, label: '项目数:51-10个', color: '#b1a0c7'}, 
								{min: 101, max: 200, label: '项目数:101-200个', color: '#538dd5'}, 
								//{value: '50', label: '11-50', color: '#fa7d82'}, // 表示 value 等于 50 的情况(即单个数值)。
								{min: 201 , label: '项目数:>=200个',color: '#ff0000'}                        // 不指定 min,表示 min 为无限大(-Infinity)。
							],
					min: 0,
                    max: 100,
					minOpen:true,                       //界面上会额外多出一个『< min』的选块
					maxOpen:true,
                    splitNumber: 5,
					itemSymbol:"circle",             //默认的图形。可选值为: 'circle', 'rect', 'roundRect', 'triangle', 'diamond', 'pin', 'arrow'
					hoverLink:true,//鼠标悬浮到 visualMap 组件上时,鼠标位置对应的数值 在 图表中对应的图形元素,会高亮
                    inRange: {
                        color: ['#f02764'].reverse(),//设置散点圈颜色
						symbolSize: [10, 50]
                    },
					outOfRange:{  //定义 在选中范围外 的视觉元素。
						color: ['#010101'].reverse(),
						symbolSize: [10, 50]
					},
					left:'1%', //组件离容器左侧的距离,'left', 'center', 'right','20%'
					backgroundColor:'#f9f8f7', //标题背景色
					borderWidth:0,//边框线宽
					textStyle: {
                        color: '#060606'
                    }



            }


});


$(function () {
		$.ajax({
			url:'/mdt',
			type:'get',
			success:function (cityres) {
			var data = new Array();
			var geoCoordMap = new Object();
				for (var i = 0;i < cityres.data.length; i++){
					data[i] = {
						name : cityres.data[i].cityname,
						value : cityres.data[i].xmsl
					};
					geoCoordMap[cityres.data[i].cityname] = [cityres.data[i].lng,cityres.data[i].lat];
				};


const convertData = function (data) {
  var res = [];
  for (var i = 0; i < data.length; i++) {
    var geoCoord = geoCoordMap[data[i].name];
    if (geoCoord) {
      res.push({
        name: data[i].name,
        value: geoCoord.concat(data[i].value),
		visualMap: true
      });
    }
  }
  return res;
};

//第二次进行myChart.setOption
myChart.setOption({
  series: [
    {
      name: '项目数(个)',
      type: 'scatter',
      coordinateSystem: 'bmap',
      data: convertData(data),
      symbolSize: function (val) {
        return val[2];
      },
      encode: {
        value: 2
      },
      label: {
        formatter: '{b}',
        position: 'right',
        show: false
      },
      emphasis: {
        label: {
          show: true
        }
      }
    },
	
	//显示前5数据名称
    {
      name: 'Top 5',
      type: 'effectScatter',
      coordinateSystem: 'bmap',
      data: convertData(
        data
          .sort(function (a, b) {
            return b.value - a.value;
          })
          .slice(0, 5)
      ),
      symbolSize: function (val) {
        return val[2] / 5;
      },
      encode: {
        value: 2
      },
      showEffectOn: 'render',
      rippleEffect: {
        brushType: 'stroke'
      },
      label: {
        formatter: '{b}',
        position: 'right',
        show: true
      },
      itemStyle: {
        shadowBlur: 10,
        shadowColor: '#333'
      },
      emphasis: {
        scale: true
      },
      zlevel: 1
    }
	
  ]
});/

//
                }
            });

        });
//

/*
if (option && typeof option === 'object') {
    myChart.setOption(option);
}
*/
        </script>
    </body>
</html>
    

另:为了方便大家使用js文件,我把js打包放网盘里了,大家可以下载使用。

链接:https://pan.baidu.com/s/1GGPlkLwUHtlWcyUtOVJTYA 
提取码:nru8

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值