使用Python调用百度地图的API在地图上添加标记

写在前面

近期博主工作太忙,快一个月没更新博客。今天跑了大半天的腿,被一堆破事儿弄的无比憋屈,写篇博客调节一下心情。
博主的目的是在地图上做一些标记,然后保存为html网页文件,这样方便我的软件调用,前期我使用的folium包,这个包很强大,支持添加各种标记。但有几个缺点:

  • 地图的底图不支持百度地图,博主想用这个包的话,就不得不将数据点转到高德坐标系下,然后进行下一步工作,然而高德莫名其妙的封了我的账号,说我违规调取数据,简直莫须有;
  • 间歇性的出现一些未知的问题,比如添加的标记不显示等等,可以理解,毕竟外国人写的,也还不是很成熟;
  • 最要命的是地图加载太慢了,加载出来要接近一分钟。

想一想,既然数据点是百度坐标系下的,百度地图又提供了API,何不直接在百度地图上画呢。
好了,上编译环境。

  • Python3.7
  • Spyder

功能实现

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>

Python实现

好了,网页代码有了,可是博主并不会写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 = '''
    <!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)    //图片的偏移量。为了是图片底部中心对准坐标点。
            });
    '''
    message2 = points
    message3 = markers
    message4 = overlays
    message5 = '''
            //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>
    '''

    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文件。
这样下来,文件可以秒开,给大家看下。
在这里插入图片描述
这样就算完成了,当然除了添加标记点,也还可以添加其他内容。
最后鼓励一下自己:
保持进步,保持好心情~~

  • 28
    点赞
  • 123
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 12
    评论
调用百度地图绘制跑步轨迹,并进行回放,需要使用百度地图的JavaScript APIPython的Flask框架。下面是使用Flask框架和百度地图JavaScript API实现跑步轨迹绘制和回放功能的一个示例: 首先,需要在百度地图开放平台申请密钥,并创建一个名为index.html的HTML文件,代码如下: ```html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>跑步轨迹回放</title> <script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=你的密钥"></script> <style type="text/css"> body, html, #allmap { width: 100%; height: 100%; margin: 0; overflow: hidden; font-family: "微软雅黑"; } #infoDiv { position: fixed; top: 10px; left: 10px; background-color: #fff; opacity: 0.8; padding: 5px; border-radius: 5px; z-index: 2; } #ctrlDiv { position: fixed; top: 10px; right: 10px; background-color: #fff; opacity: 0.8; padding: 5px; border-radius: 5px; z-index: 2; } #playBtn { font-size: 20px; margin-left: 10px; cursor: pointer; } #slider { width: 300px; height: 5px; background-color: #ddd; margin-left: 10px; display: inline-block; vertical-align: middle; } #sliderBar { width: 0; height: 5px; background-color: #f00; } </style> </head> <body> <div id="allmap"></div> <div id="infoDiv"></div> <div id="ctrlDiv"> <span id="playBtn">播放</span> <div id="slider"> <div id="sliderBar"></div> </div> </div> <script type="text/javascript"> var map = new BMap.Map("allmap"); var points = []; var markers = []; var infoWindow = new BMap.InfoWindow(""); var playBtn = document.getElementById("playBtn"); var sliderBar = document.getElementById("sliderBar"); var maxIndex = 0; var currentIndex = 0; var isPlaying = false; var timer = null; function init() { map.centerAndZoom(new BMap.Point(116.404, 39.915), 15); // 读取轨迹数据,添加标记和折线 {% for point in points %} var point = new BMap.Point({{point[0]}}, {{point[1]}}); points.push(point); var marker = new BMap.Marker(point); marker.addEventListener("click", function (e) { infoWindow.setContent(e.target.getTitle()); infoWindow.open(e.target.getMap(), e.target.getPosition()); }); markers.push(marker); map.addOverlay(marker); {% endfor %} var polyline = new BMap.Polyline(points, {strokeColor: "#f00", strokeWeight: 3, strokeOpacity: 1}); map.addOverlay(polyline); maxIndex = points.length - 1; // 绑定事件 playBtn.addEventListener("click", function () { if (isPlaying) { clearInterval(timer); isPlaying = false; playBtn.innerText = "播放"; } else { isPlaying = true; playBtn.innerText = "暂停"; timer = setInterval(function () { if (currentIndex < maxIndex) { currentIndex += 1; sliderBar.style.width = currentIndex / maxIndex * 100 + "%"; map.panTo(points[currentIndex]); markers[currentIndex].setAnimation(BMAP_ANIMATION_BOUNCE); markers[currentIndex - 1].setAnimation(null); } else { clearInterval(timer); isPlaying = false; playBtn.innerText = "播放"; } }, 1000); } }); } window.onload = init; </script> </body> </html> ``` 在这个HTML文件中,我们首先引入了百度地图JavaScript API,然后创建一个包含地图容器、信息框和控制条的页面。接下来使用Flask框架创建一个名为app.py的Python文件,代码如下: ```python from flask import Flask, render_template import pandas as pd app = Flask(__name__) @app.route("/") def index(): # 读取轨迹数据 data = pd.read_csv("data.csv") points = [(row["经度"], row["纬度"]) for index, row in data.iterrows()] return render_template("index.html", points=points) if __name__ == "__main__": app.run(debug=True) ``` 在这个Python文件中,我们使用pandas库读取保存轨迹数据的CSV文件,并将经纬度数据转换为一个元组列表。然后,我们使用Flask框架的render_template方法将轨迹数据传递给HTML文件,并启动Flask应用程序。 执行完以上代码后,可以在浏览器中访问http://localhost:5000/,即可看到绘制好的跑步轨迹和回放控制条。用户可以点击播放按钮,回放跑步轨迹,并通过控制条控制回放进度。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

栀椩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值