近期博主工作太忙,快一个月没更新博客。今天跑了大半天的腿,被一堆破事儿弄的无比憋屈,写篇博客调节一下心情。
博主的目的是在地图上做一些标记,然后保存为html网页文件,这样方便我的软件调用,前期我使用的folium包,这个包很强大,支持添加各种标记。但有几个缺点:
想一想,既然数据点是百度坐标系下的,百度地图又提供了API,何不直接在百度地图上画呢。
好了,上编译环境。
先上百度地图js API地址。
看看API示例:
语言是JavaScript,展示的界面是添加标记点,我把完整的示例代码贴出来,并解释一下:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<title>添加点标记</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<style>
body,
html,
#container {
overflow: hidden;
width: 100%;
height: 100%;
margin: 0;
font-family: "微软雅黑";
}
</style>
<script src="//api.map.baidu.com/api?type=webgl&v=1.0&ak=您的密钥"></script>
</head>
<body>
<div id="container"></div>
</body>
</html>
<script>
var map = new BMapGL.Map('container');
map.centerAndZoom(new BMapGL.Point(116.404, 39.928), 15);
map.enableScrollWheelZoom(true);
// 创建点标记
var marker1 = new BMapGL.Marker(new BMapGL.Point(116.404, 39.925));
var marker2 = new BMapGL.Marker(new BMapGL.Point(116.404, 39.915));
var marker3 = new BMapGL.Marker(new BMapGL.Point(116.395, 39.935));
var marker4 = new BMapGL.Marker(new BMapGL.Point(116.415, 39.931));
// 在地图上添加点标记
map.addOverlay(marker1);
map.addOverlay(marker2);
map.addOverlay(marker3);
map.addOverlay(marker4);
</script>
虽然博主没搞过JavaScript,不过语言大体相通,能看明白写的是什么,前面是网页的基础设置,主体在script标签中,定义了四个点,然后将这四个点添加到地图上。
官方给的示例其实是有问题的,我填上了自己申请的AK,另存为html文件后却怎么也打不开,于是初略看了下代码,发现下面这行就是个坑:
<script src="//api.map.baidu.com/api?type=webgl&v=1.0&ak=您的密钥">
我稍微改了下,改成了:
<script src="https://api.map.baidu.com/api?type=webgl&v=1.0&ak=您的密钥">
就能显示了,不过显示还是不完整,猜测是可能缺少加载 BMapGL.Map方法的js包,所以不再纠结,于是在网上找了另外一段可以执行的代码,链接在这里。
这个代码也要加上https才行。有用的代码如下:
<!DOCTYPE html>
<html xmlns:asp="">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<style type="text/css">
body, html,#allmap {width: 100%;height: 100%;overflow: hidden;margin:0;font-family:"微软雅黑";}
</style>
<script type="text/javascript" src="//api.map.baidu.com/api?type=webgl&v=1.0&ak=d5Y5C26Xbhr3rBHo3GzzaA7xcXev6NL0"></script>
<title>添加信息窗口</title>
</head>
<body>
<div id="allmap"></div>
</body>
<script>
// An highlighted block
//百度地图API功能
function loadJScript() {
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "//api.map.baidu.com/api?v=2.0&ak=d5Y5C26Xbhr3rBHo3GzzaA7xcXev6NL0&callback=init";
document.body.appendChild(script);
}
window.init = function() {
var map = new BMap.Map("allmap"); // 创建Map实例
//var point = new BMap.Point(109.18592,34.36912); // 创建点坐标
map.centerAndZoom(new BMap.Point(109.19708,34.36820), 15); // 设置中心点,地图初始化
//map.centerAndZoom(points,20);
map.setCurrentCity("西安"); //设置当前城市
map.clearOverlays();
map.addControl(new BMap.MapTypeControl());
map.enableScrollWheelZoom(true); //启用滚轮放大缩小
//向地图中添加缩放控件
var ctrlNav = new window.BMap.NavigationControl({
anchor: BMAP_ANCHOR_TOP_LEFT,
type: BMAP_NAVIGATION_CONTROL_LARGE
});
map.addControl(ctrlNav);
//向地图中添加标记点
var myIcon =new BMap.Icon("http://api.map.baidu.com/img/markers.png", new BMap.Size(23, 25), { //小车图片
offset: new BMap.Size(0, -5), //相当于CSS精灵
imageOffset: new BMap.Size(0, 0) //图片的偏移量。为了是图片底部中心对准坐标点。
});
var points = [new BMap.Point(109.19474,34.36847),new BMap.Point(109.19435,34.37712),new BMap.Point(109.19261,34.37617),new BMap.Point(109.19701,34.37728),new BMap.Point(109.19702,34.37776),new BMap.Point(109.19784,34.37738),new BMap.Point(109.19784,34.376911),new BMap.Point(109.1987,34.37333),new BMap.Point(109.19705,34.36824),new BMap.Point(109.1836,34.37393)]; //10个坐标点
var marker1 =new BMap.Marker(points[1],{icon:myIcon}); // 创建10个标注
var marker2 =new BMap.Marker(points[2],{icon:myIcon});
var marker3 =new BMap.Marker(points[3],{icon:myIcon});
var marker4 =new BMap.Marker(points[4],{icon:myIcon});
var marker5 =new BMap.Marker(points[5],{icon:myIcon});
var marker6 =new BMap.Marker(points[6],{icon:myIcon});
var marker7 =new BMap.Marker(points[7],{icon:myIcon});
var marker8 =new BMap.Marker(points[8],{icon:myIcon});
var marker9 =new BMap.Marker(points[9],{icon:myIcon});
var marker0 =new BMap.Marker(points[0],{icon:myIcon});
map.addOverlay(marker1); // 将标注添加到地图中
map.addOverlay(marker2);
map.addOverlay(marker3);
map.addOverlay(marker4);
map.addOverlay(marker5);
map.addOverlay(marker6);
map.addOverlay(marker7);
map.addOverlay(marker8);
map.addOverlay(marker9);
map.addOverlay(marker0);
map.setViewport(points); //调整地图的最佳视野为显示标注数组point
loadJScript()
</script>
<script>
layui.use('theme/settings/earth', layui.factory('theme/settings/earth'));
</script>
<!--<script type="text/javascript" src="js\jquery-2.1.1.min.js"></script>-->
</html>
好了,网页代码有了,可是博主并不会写html,只会简单的写写Python,如何把上面的代码合理的利用起来,并且将里面的变量改变成自己的点呢?
博主的思路很简单,将上面这些代码分成几个部分的字符串,然后字符串拼接起来,最后形成一个完整的html网页代码。
如果大家有仔细看上面的代码,会发现网页框架可以分成五部分:
第一部分代码:
<!DOCTYPE html>
<html xmlns:asp="">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<style type="text/css">
body, html,#allmap {width: 100%;height: 100%;overflow: hidden;margin:0;font-family:"微软雅黑";}
</style>
<script type="text/javascript" src="https://api.map.baidu.com/api?type=webgl&v=1.0&ak=9Rz4tOb6PgQtqBt6K3YbSMBESLk8iYpE"></script>
<title>添加信息窗口</title>
</head>
<body>
<div id="allmap"></div>
</body>
<script>
// An highlighted block
//百度地图API功能
function loadJScript() {
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "https://api.map.baidu.com/api?v=2.0&ak=9Rz4tOb6PgQtqBt6K3YbSMBESLk8iYpE&callback=init";
document.body.appendChild(script);
}
window.init = function() {
var map = new BMap.Map("allmap"); // 创建Map实例
//var point = new BMap.Point(109.18592,34.36912); // 创建点坐标
map.centerAndZoom(new BMap.Point(120.2338341,31.58109976), 15); // 设置中心点,地图初始化
//map.centerAndZoom(points,20);
map.setCurrentCity("无锡"); //设置当前城市
map.clearOverlays();
map.addControl(new BMap.MapTypeControl());
map.enableScrollWheelZoom(true); //启用滚轮放大缩小
map.addEventListener('click', function(e) {
alert('点击的经纬度:' + e.latlng.lng + ', ' + e.latlng.lat);
var mercator = map.lnglatToMercator(e.latlng.lng, e.latlng.lat);
alert('点的墨卡托坐标:' + mercator[0] + ', ' + mercator[1]);
});
//向地图中添加缩放控件
var ctrlNav = new window.BMap.NavigationControl({
anchor: BMAP_ANCHOR_TOP_LEFT,
type: BMAP_NAVIGATION_CONTROL_LARGE
});
map.addControl(ctrlNav);
//向地图中添加标记点
var myIcon =new BMap.Icon("http://api.map.baidu.com/img/markers.png", new BMap.Size(23, 25), { //小车图片
offset: new BMap.Size(0, -5), //相当于CSS精灵
imageOffset: new BMap.Size(0, 0) //图片的偏移量。为了是图片底部中心对准坐标点。
});
这部分代码是基本不会变化的,改动无非就是那两个经纬度坐标和城市名。
再看第二部分:
var points = [new BMap.Point(109.19474,34.36847),new BMap.Point(109.19435,34.37712),new BMap.Point(109.19261,34.37617),new BMap.Point(109.19701,34.37728),new BMap.Point(109.19702,34.37776),new BMap.Point(109.19784,34.37738),new BMap.Point(109.19784,34.376911),new BMap.Point(109.1987,34.37333),new BMap.Point(109.19705,34.36824),new BMap.Point(109.1836,34.37393)]; //10个坐标点
这部分是定义的数据点,就是说如果要更换数据点,应该在这里改。
第三部分:
var marker1 =new BMap.Marker(points[1],{icon:myIcon}); // 创建10个标注
var marker2 =new BMap.Marker(points[2],{icon:myIcon});
var marker3 =new BMap.Marker(points[3],{icon:myIcon});
var marker4 =new BMap.Marker(points[4],{icon:myIcon});
var marker5 =new BMap.Marker(points[5],{icon:myIcon});
var marker6 =new BMap.Marker(points[6],{icon:myIcon});
var marker7 =new BMap.Marker(points[7],{icon:myIcon});
var marker8 =new BMap.Marker(points[8],{icon:myIcon});
var marker9 =new BMap.Marker(points[9],{icon:myIcon});
var marker0 =new BMap.Marker(points[0],{icon:myIcon});
第三部分是在为点添加标记,也是根据点来的,有多少点就写多少行。
第四部分:
map.addOverlay(marker1); // 将标注添加到地图中
map.addOverlay(marker2);
map.addOverlay(marker3);
map.addOverlay(marker4);
map.addOverlay(marker5);
map.addOverlay(marker6);
map.addOverlay(marker7);
map.addOverlay(marker8);
map.addOverlay(marker9);
map.addOverlay(marker0);
第四部分是把标记点添加到map图层上去,也是根据自己的数据来的。
第五部分:
loadJScript()
</script>
<script>
layui.use('theme/settings/earth', layui.factory('theme/settings/earth'));
</script>
<!--<script type="text/javascript" src="js\jquery-2.1.1.min.js"></script>-->
</html>
这部分也不需要动。
既然代码已经分解清楚了,用Python来把这些代码串起来就很简单了,看看怎么实现的吧:
#!/usr/bin/env python
#-*- coding:utf-8 -*-
# author:HP
# datetime:2020/12/11 16:47
import pandas as pd
data = pd.read_csv('数据.txt', sep='\t')
def get_html(YearData):
var_point = []
var_marker = []
addOverlay = []
for i in range(len(YearData)):
point = 'new BMap.Point(' + str(YearData.loc[i, 'lon_baidumap']) + ',' + str(YearData.loc[i, 'lat_baidumap']) + ')'
marker = 'var marker' + str(i) + '=new BMap.Marker(points[' + str(i) + '],{icon:myIcon});'
overlay = 'map.addOverlay(marker' + str(i) + ');'
var_point.append(point)
var_marker.append(marker)
addOverlay.append(overlay)
points = ','.join(var_point)
markers = '\n '.join(var_marker)
overlays = '\n '.join(addOverlay)
message1 = '''
添加信息窗口
'''
message = message1 + '\n' + ' var points = [' + message2 + '];' + '\n ' + message3 + '\n ' + message4 + '\n' + message5
return message
for i in range(2011, 2020):
yeardata = data[data.nian == i].reset_index(drop=True)
message = get_html(yeardata)
filename = 'qroad' + str(i) + '.html'
with open(filename, 'w', encoding="utf-8")as f:
f.write(message)
f.close()
还是简单解释一下代码吧:
前面是数据导入,数据就是我的百度地图坐标系下的经纬度坐标点。
然后是写方法,主要就是循环把点生成字符串,然后五部分加起来。
最后调用方法,生成html文件。
这样下来,文件可以秒开,给大家看下。
这样就算完成了,当然除了添加标记点,也还可以添加其他内容。
最后鼓励一下自己:
保持进步,保持好心情~~