大二下学期第一次结对作业(第一阶段:地图下钻)
今日主要完成了地图下钻的功能:
对于地图下钻前几天在网上找到过资源,可以实现下钻,但是当时知识将代码粘了过来,并没有理解代码的逻辑,所以导致无法插入数据。
今日将代码重头到尾理解了一番,实现了数据的插入,首先要代码需要引入高德地图api,要到官网上申请key。
地图下钻:https://www.makeapie.com/editor.html?c=xz3jGj90ns https://juejin.cn/post/6844903982377205768#heading-7
需要引入的内容:
<script type="text/javascript" src="https://webapi.amap.com/maps?v=1.4.15&key="></script> <script type="text/javascript" src="https://webapi.amap.com/maps?v=1.4.15&key=&plugin=AMap.DistrictSearch"></script> <script src="https://webapi.amap.com/ui/1.0/main.js"></script> <script src="https://cdn.bootcss.com/PapaParse/4.1.2/papaparse.min.js"></script>
<script> $('<div class="back">返回</div>').appendTo( $('#chart-panel') ); $('.back').css({ 'position': 'absolute', 'left': '17px', 'top': '25px', 'color': 'rgb(222,222,222)', 'font-size': '15px', 'cursor': 'pointer', 'z-index': '100' }) $('.back').click(function() { if (parentInfo.length === 1) { return; } parentInfo.pop() getGeoJson(parentInfo[parentInfo.length - 1].code) }) var parentJson = null var parentInfo = [{ cityName: '全国', level: 'china', code: 100000 }] var parent getGeoJson(100000) /** * 利用高德api获取行政区边界geoJson * adcode 行政区code 编号 **/ //此版本不再维护,准备在写另一个新版本 function getGeoJson(adcode) { AMapUI.loadUI(['geo/DistrictExplorer'], DistrictExplorer => { var districtExplorer = new DistrictExplorer() districtExplorer.loadAreaNode(adcode, function(error, areaNode) { if (error) { console.error(error); return; } parent = areaNode; let Json = areaNode.getSubFeatures() if (Json.length > 0) { parentJson = Json } else if (Json.length === 0) { Json = parentJson.filter(item => { if (item.properties.adcode == adcode) { return item } }) if (Json.length === 0) return } //去获取数据 getMapData(Json) }); }) } //获取数据,这里我们用随机数模拟数据 function getMapData(Json) { /* let mapData = [{ name: '广东省', value: 1000, cityCode: 440000, value2:200 }, { name: '湖南省', value: 2000, cityCode: 430000 }]*/ /* 全国:100000 北京:110000 天津:120000 河北:130000 山西:140000 内蒙古:150000 辽宁:210000 吉林:220000 黑龙江:230000 上海:310000 江苏:320000 浙江:330000 安徽:340000 福建:350000 江西:360000 山东:370000 河南:410000 湖北:420000 湖南:430000 广东:440000 广西:450000 海南:460000 重庆:500000 四川:510000 贵州:520000 云南:530000 西藏:540000 陕西:610000 甘肃:620000 青海:630000 宁夏:640000 新疆:650000 台湾:710000 香港:810000 澳门:820000 */ var mapData $.ajax({ url:"/c2", data: {name: parent.getName() }, success: function (data) { mapData=data.data; let pointData = Json.map(item => { return ({ name: item.properties.name, value: ['118.83531246', '32.0267395887', Math.random() * 1000], cityCode: item.properties.adcode }) }) let mapJson = {} //geoJson必须这种格式 mapJson.features = Json //去渲染echarts initEcharts(mapData, pointData, mapJson) }, error: function (xhr, type, errorThrown) { } }) /* mapData = Json.map(item => { return ({ name: item.properties.name, value: Math.random() * 100, level: item.properties.level, cityCode: item.properties.adcode }) })*/ } var myChart = echarts.init(document.querySelector(".map .chart")); function initEcharts(mapData, pointData, mapJson) { //注册 echarts.registerMap('Map', mapJson); //这里加true是为了让地图重新绘制,不然如果你有筛选的时候地图会飞出去 myChart.setOption({ borderColor: "rgba(0, 0, 0, 0.5)", // tooltip: { // trigger: "item", // formatter: p => { // let val = p.value; // if (window.isNaN(val)) { // val = 0; // } // let txtCon = // "<div style='text-align:center'>" + p.name + ":<br />台量:" + val.toFixed(2) + '</div>'; // return txtCon; // } // }, tooltip: { formatter: function(params, ticket, callback) { return params.data.name + "<br />" + "累计确诊" + ":" + params.data.value + "<br />" + "累计治愈" + ":" + params.data.heal + "<br />" + "累计死亡" + ":" + params.data.dead + "<br />" + "疑似病例:" + 0 } }, toolbox: { feature: { dataView: { show: false, readOnly: true }, magicType: { show: false, type: ["line", "bar"] }, restore: { show: false }, saveAsImage: { show: true, name: parentInfo[parentInfo.length - 1].cityName + "地图", pixelRatio: 2 } }, iconStyle: { normal: { borderColor: "#41A7DE" } }, itemSize: 15, top: 20, right: 22 }, visualMap: { left: 26, bottom: 30, showLabel: !0, text: ["高", "低"], textStyle: { fontSize: 12, color: "#fff" }, pieces: [{ max: 100, label: '<100', color: '#ffd768' }, { min: 100, max: 1000, label: '100-1000', color: '#ff8c71' }, { min: 1000, max: 10000, label: '1000-10000', color: '#ff5428' }, { min: 10000, label: '>10000', color: '#7f1100' }, ], color: '#fff', textStyle: { color: '#fff', }, show: !0 }, series: [{ name: "地图", type: "map", map: "Map", roam: true, //是否可缩放 zoom: 1.1, //缩放比例 top: 120, data: mapData, itemStyle: { normal: { show: true, areaColor: '#2E98CA', borderColor: "rgba(0, 0, 0, 0.5)", borderWidth: '1', }, }, label: { normal: { show: true, //显示省份标签 textStyle: { color: "rgb(249, 249, 249)", //省份标签字体颜色 fontSize: 12 }, formatter: p => { let val = p.value; if (window.isNaN(val)) { val = 0; } // switch (p.name) { case '内蒙古自治区': p.name = "内蒙古" break; case '西藏自治区': p.name = "西藏" break; case '新疆维吾尔自治区': p.name = "新疆" break; case '宁夏回族自治区': p.name = "宁夏" break; case '广西壮族自治区': p.name = "广西" break; case '香港特别行政区': p.name = "香港" break; case '澳门特别行政区': p.name = "澳门" break; default: // code } if (p.name === "内蒙古自治区") { p.name = "内蒙古"; } let txtCon = p.name; return txtCon; } }, emphasis: { //对应的鼠标悬浮效果 show: true, textStyle: { color: "#000" } } } }, { name: '散点', type: 'effectScatter', coordinateSystem: 'geo', rippleEffect: { brushType: 'fill' }, itemStyle: { normal: { borderColor: "rgba(0, 0, 0, 0.5)" } }, data: pointData, symbolSize: 8, showEffectOn: 'render', //加载完毕显示特效 }, ] }, true) //点击前解绑,防止点击事件触发多次 myChart.off('click'); myChart.on('click', echartsMapClick); window.addEventListener("resize", function() { myChart.resize(); }); } //echarts点击事件 function echartsMapClick(params) { //如果当前是最后一级,那就直接return if (parentInfo[parentInfo.length - 1].code == params.data.cityCode) { return } let data = params.data parentInfo.push({ cityName: data.name, level: data.level, code: data.cityCode }) getGeoJson(data.cityCode) } </script> <script>
1.首先代码开头定义了一个返回按钮以及点击事件,比较容易理解。
2.然后是getGeoJson(100000)这是获取地图边界geoJson,就是说要通过这个画地图,这里面的参数就是当前地图的code。
所以一开始定义了一个“全国” 里面的code是100000,所以会返回各省的code,这样一开始进入网页就会绘制全国地图。注意这
里的code是一一对应的,可到高德地图官网查看。代码中的注释里我已经给出了各个省的code。
3.接着就是获取数据,只需要修改mapdata即可,用ajax请求返回数据。这就遇到了一个问题,如何获取数据,根据什么我能确
定我需要各省的还是一个省中各个市的数据。
我们先不看绘制地图部分的代码,最后有一个地图点击事件,这里其实是获取了你当前点击的省的的名字和code,这样将code
传入getGeoJson就可以获取这个省份的地图,然后返回各市区的code。
这样又有一个问题,在getMapData(Json)函数中我们只有了各个市区的信息,并没办法确定这是那个省,我们通过省份查取数
据库要比通过市方便许多。所以在getGeoJson中我设置了一个parent,这样就可以获取市之上省的名字。
4.传数据,只要修改mapdata,但是不能随便修改,要注意一定要有name与value以及cityCode属性,且name要与高德地图上的
名字相符,而且citycode也要一一对应正确。
5.接着就是最后的渲染地图的部分利用echarts渲染,没有太大问题。
不过因为是爬取的腾讯疫情的信息,里面的各省的地区数据不全,而且名字也会因为个别字不一样导致对应不上。对于省份,我们
还可以一一修改,但是对于每个省的市区,我们无法一一修改,而且因为修改情况太多所以没办法修改,导致有的地区没有数据。
下面给出数据库查询以及服务层的函数:
@app.route('/c2') def get_c2_data(): name=request.values.get("name") res=[] if(name=="全国"): res=[] for tup in utils.get_c2_data(): res.append({"name": addname(tup[0]), "value": int(tup[1]),"cityCode":getcode(tup[0]),"heal": int(tup[2]),"dead": int(tup[3])}) else: res=[] for tup in utils.get_city_data(delname(name)): res.append({"name":addcityname(tup[0]),"value":int(tup[1]),"heal": int(tup[2]),"dead": int(tup[3])}) print(res) return jsonify({"data":res})
def addname(name): list=["北京","天津","上海","重庆"] list2=["内蒙古","西藏"] list3=["香港","澳门"] list4=["河北","山西","辽宁","吉林","黑龙江","江苏","浙江","安徽","福建","江西", "山东","河南","湖北","湖南","广东","海南","四川","贵州","云南", "陕西","甘肃","青海","台湾"] if(name in list): return name+"市" if(name in list2): return name+"自治区" if(name=="新疆"): return "新疆维吾尔自治区" if(name=="宁夏"): return "宁夏回族自治区" if(name=="广西"): return "广西壮族自治区" if(name in list3): return name+"特别行政区" if(name in list4): return name+"省" def delname(name): list=["北京市","天津市","上海市","重庆市"] list2=["内蒙古自治区","西藏自治区","新疆维吾尔自治区","宁夏回族自治区","广西壮族自治区"] list3=["香港特别行政区","澳门特别行政区"] list4=["河北省","山西省","辽宁省","吉林省","黑龙江省","江苏省","浙江省","安徽省","福建省","江西省", "山东省","河南省","湖北省","湖南省","广东省","海南省","四川省","贵州省","云南省", "陕西省","甘肃省","青海省","台湾省"] if(name in list): return name[0:len(name)-1] if(name in list2): return name[0:len(name)-3] if(name in list3): return name[0:len(name)-5] if(name in list4): return name[0:len(name)-1] def getcode(name): if(name=="全国"): return 100000 if(name=="北京"): return 110000 if(name=="天津"): return 120000 if(name=="河北"): return 130000 if(name=="山西"): return 140000 if(name=="内蒙古"): return 150000 if(name=="辽宁"): return 210000 if(name=="吉林"): return 220000 if(name=="黑龙江"): return 230000 if(name=="上海"): return 310000 if(name=="江苏"): return 320000 if(name=="浙江"): return 330000 if(name=="安徽"): return 340000 if(name=="福建"): return 350000 if(name=="江西"): return 360000 if(name=="山东"): return 370000 if(name=="河南"): return 410000 if(name=="湖北"): return 420000 if(name=="湖南"): return 430000 if(name=="广东"): return 440000 if(name=="广西"): return 450000 if(name=="海南"): return 460000 if(name=="重庆"): return 500000 if(name=="四川"): return 510000 if(name=="贵州"): return 520000 if(name=="云南"): return 530000 if(name=="西藏"): return 540000 if(name=="陕西"): return 610000 if(name=="甘肃"): return 620000 if(name=="青海"): return 630000 if(name=="宁夏"): return 640000 if(name=="新疆"): return 650000 if(name=="台湾"): return 710000 if(name=="香港"): return 810000 if(name=="澳门"): return 820000 def addcityname(name): if(name[len(name)-1]=='区'): return name if(name[len(name)-1]=='县'): return name return name+"市"
def get_city_data(name): sql='select city ,confirm ,heal ,dead from details '\ 'where update_time=(select update_time from details order by update_time desc limit 1) '\ 'and province='+'"'+name+'"'+' and city not in ("境外输入","地区待确认") ' res=query(sql) print(res) return res def get_c2_data(): """ :return: 返回各省数据 """ # 因为会更新多次数据,取时间戳最新的那组数据 sql = "select province,sum(confirm),sum(heal),sum(dead) from details " \ "where update_time=(select update_time from details " \ "order by update_time desc limit 1) " \ "group by province" res = query(sql) print(res) return res
数据库结构: