毕设篇:调用百度api实现驾车路线和时间距离计算
效果展示
html页面:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
body,
html {
width: 100%;
height: 100%;
margin: 0;
font-family: "微软雅黑";
}
#allmap {
height: 600px;
width: 1000px;
margin: 50px auto;
}
.submitMap {
cursor: pointer;
display: block;
}
</style>
<link rel="stylesheet" href="lib/theme-chalk/index.css">
<!-- 百度api调用 设置地图ak, api key 申请的密钥 -->
<script type="text/javascript"
src="https://api.map.baidu.com/api?type=webgl&v=1.0&ak=FO9GG7UZlcypetqR3kuWX8DhwzKYpZwb"></script>
<!-- vue和element导入 -->
<script src="js/vue.js"></script>
<script src="lib/index.js"></script>
</head>
<body>
<div id="app">
<div id="allmap"></div>
<div style="float: left;margin-right: 100px;">
<form action="" method="post">
<input type="text" placeholder="请输入起始点坐标" v-model="input1" id="map1" value="">
<input type="text" placeholder="请输入目的地坐标" v-model="input2" id="map2" value="">
<input type="button" value="提交" onclick="get()">
</form>
</div>
<div style="float: left;text-align: center;font-size: 16px;">
预计驾车所需时间:<span id="time" style="margin: 0 20px;"></span>
预计驾车总路程:<span id="distance" style="margin: 0 20px;"></span>
</div>
<!-- -->
<!-- <span class="submitMap" @click="onSubmit()">提交</span> -->
</div>
<!-- <div id='result'>根据起点和终点经纬度驾车导航路线</div> -->
<script src="js/RouteApi.js"></script>
</body>
</html>
js页面:
//vue
const mapForm = new Vue({
//
el: '#app',
data() {
return {
//默认初始化,动态绑定
input1: '',
input2: '',
}
},
methods: {
}
});
// 百度地图API功能 初始化地图
var map = new BMapGL.Map("allmap");
//调用函数
setMap();
//公共控件 封装到getMap函数 var与const的区别,可自行百度查阅
function setMap() {
//设置地图样式 dark
function changeThemeDark() { map.setMapStyle({ style: "dark" }); }
//鼠标滚动缩放
map.enableScrollWheelZoom(true);
// 添加比例尺控件
var scaleCtrl = new BMapGL.ScaleControl();
map.addControl(scaleCtrl);
// 添加比例尺控件
var zoomCtrl = new BMapGL.ZoomControl();
map.addControl(zoomCtrl);
// 添加3D控件
var navi3DCtrl = new BMapGL.NavigationControl3D();
map.addControl(navi3DCtrl);
// 创建城市选择控件
var cityControl = new BMapGL.CityListControl({
// 控件的停靠位置(可选,默认左上角)
anchor: BMAP_ANCHOR_TOP_LEFT,
// 控件基于停靠位置的偏移量(可选)
offset: new BMapGL.Size(10, 5)
});
// 将控件添加到地图上
map.addControl(cityControl);
var cr = new BMapGL.CopyrightControl({
anchor: BMAP_ANCHOR_TOP_RIGHT,
offset: new BMapGL.Size(10, 25)
}); //设置版权控件位置
map.addControl(cr); //添加版权控件
var bs = map.getBounds(); //返回地图可视区域
cr.addCopyright({
id: 1,
content: "<img src='img/logo.png' width='50px' height='50px'/><a href='index.html' target='_blank' style='font-size:12px;color:gray;text-decoration: none;'>@张家界旅心网</a>",
bounds: bs
});
var menu = new BMapGL.ContextMenu();
var txtMenuItem = [
{
text: '放大一级',
callback: function () {
map.zoomIn();
}
}, {
text: '缩小一级',
callback: function () {
map.zoomOut();
}
}
];
for (var i = 0; i < txtMenuItem.length; i++) {
menu.addItem(new BMapGL.MenuItem(txtMenuItem[i].text, txtMenuItem[i].callback, 100));
}
map.addContextMenu(menu);
map.addEventListener('click', function (e) {
alert('点击位置经纬度:' + e.latlng.lng.toFixed(3) + ',' + e.latlng.lat.toFixed(3));
});
// 创建定位控件
var locationControl = new BMapGL.LocationControl({
// 控件的停靠位置(可选,默认左上角)
anchor: BMAP_ANCHOR_TOP_RIGHT,
// 控件基于停靠位置的偏移量(可选)
offset: new BMapGL.Size(20, 20)
});
// 将控件添加到地图上
map.addControl(locationControl);
// 添加定位事件
locationControl.addEventListener("locationSuccess", function (e) {
var address = '';
address += e.addressComponent.province;
address += e.addressComponent.city;
address += e.addressComponent.district;
address += e.addressComponent.street;
address += e.addressComponent.streetNumber;
alert("当前定位地址为:" + address);
});
locationControl.addEventListener("locationError", function (e) {
alert(e.message);
});
}
//初始化地图,用城市名设置地图中心点,显示比例级别
var point = new BMapGL.Point(110.469578, 29.144397);
map.centerAndZoom(point, 15);
function showSH() { map.centerAndZoom("张家界", 14); }
function theLocation() {
var city = document.getElementById("cityName").value;
if (city != "") {
map.centerAndZoom(city, 14); // 用城市名设置地图中心点,显示比例级别
}
}
//设置版权偏移
// map.setCopyrightOffset();
// 创建添加点标记
var marker = new BMapGL.Marker(new BMapGL.Point(110.46966, 29.144162));
map.addOverlay(marker);
// 创建图文信息窗口
var sContent = `<h4 style='margin:0 0 5px 0;'>吉首大学张家界校区</h4>
<img style='float:right;margin:0 4px 22px' id='imgDemo' src='img/zjjxq.jpg' width='139' height='104'/>
<p style='margin:0;line-height:1.5;font-size:13px;text-indent:2em'>
坐落于世界旅游知名旅游城市张家界,有着武陵源,天门山,黄龙洞,玻璃桥等世界知名景点,热情张家界欢迎你!
</p></div>`;
var infoWindow = new BMapGL.InfoWindow(sContent);
// marker添加点击事件
marker.addEventListener('click', function () {
this.openInfoWindow(infoWindow);
// 图片加载完毕重绘infoWindow
document.getElementById('imgDemo').onload = function () {
infoWindow.redraw(); // 防止在网速较慢时生成的信息框高度比图片总高度小,导致图片部分被隐藏
};
});
// 自定义中心点,自定义两地的驾车路线
map.centerAndZoom(new BMapGL.Point(110.470, 29.144), 14);
const p1 = new BMapGL.Point(110.471, 29.172);
const p2 = new BMapGL.Point(110.470, 29.144);
const driving = new BMapGL.DrivingRoute(map, { renderOptions: { map: map, autoViewport: true } });
driving.search(p1, p2);
//执行点击事件时,调用get()方法,重新加载map地图,关于setMap函数不能复用的原因,是由于调用外部函数会执行两次,位置放置前后也不能解决
function get() {
var map = new BMapGL.Map("allmap");
//已实现外部函数的复用
// function getMap() {
// }
//调用外部函数
function getMap() {
//设置地图样式 dark
function changeThemeDark() { map.setMapStyle({ style: "dark" }); }
//鼠标滚动缩放
map.enableScrollWheelZoom(true);
// 添加比例尺控件
var scaleCtrl = new BMapGL.ScaleControl();
map.addControl(scaleCtrl);
// 添加比例尺控件
var zoomCtrl = new BMapGL.ZoomControl();
map.addControl(zoomCtrl);
// 添加3D控件
var navi3DCtrl = new BMapGL.NavigationControl3D();
map.addControl(navi3DCtrl);
// 创建城市选择控件
var cityControl = new BMapGL.CityListControl({
// 控件的停靠位置(可选,默认左上角)
anchor: BMAP_ANCHOR_TOP_LEFT,
// 控件基于停靠位置的偏移量(可选)
offset: new BMapGL.Size(10, 5)
});
// 将控件添加到地图上
map.addControl(cityControl);
var cr = new BMapGL.CopyrightControl({
anchor: BMAP_ANCHOR_TOP_RIGHT,
offset: new BMapGL.Size(10, 25)
}); //设置版权控件位置
map.addControl(cr); //添加版权控件
var bs = map.getBounds(); //返回地图可视区域
cr.addCopyright({
id: 1,
content: "<img src='img/logo.png' width='50px' height='50px'/><a href='index.html' target='_blank' style='font-size:12px;color:gray;text-decoration: none;'>@张家界旅心网</a>",
bounds: bs
});
var menu = new BMapGL.ContextMenu();
var txtMenuItem = [
{
text: '放大一级',
callback: function () {
map.zoomIn();
}
}, {
text: '缩小一级',
callback: function () {
map.zoomOut();
}
}
];
for (var i = 0; i < txtMenuItem.length; i++) {
menu.addItem(new BMapGL.MenuItem(txtMenuItem[i].text, txtMenuItem[i].callback, 100));
}
map.addContextMenu(menu);
map.addEventListener('click', function (e) {
alert('点击位置经纬度:' + e.latlng.lng.toFixed(3) + ',' + e.latlng.lat.toFixed(3));
});
// 创建定位控件
var locationControl = new BMapGL.LocationControl({
// 控件的停靠位置(可选,默认左上角)
anchor: BMAP_ANCHOR_TOP_RIGHT,
// 控件基于停靠位置的偏移量(可选)
offset: new BMapGL.Size(20, 20)
});
// 将控件添加到地图上
map.addControl(locationControl);
// 添加定位事件
locationControl.addEventListener("locationSuccess", function (e) {
var address = '';
address += e.addressComponent.province;
address += e.addressComponent.city;
address += e.addressComponent.district;
address += e.addressComponent.street;
address += e.addressComponent.streetNumber;
alert("当前定位地址为:" + address);
});
locationControl.addEventListener("locationError", function (e) {
alert(e.message);
});
}
getMap();
//根据id获取属性值
var map1 = document.getElementById("map1").value;
var map2 = document.getElementById("map2").value;
//测试数据,得知获取的是 类似 110.458,29.158 格式的数据,中间有逗号,所以是字符串,可以使用split对字符串进行分割成数组
// console.log(map1, map2);
//设置路线显示中心点,这段代码不能省略,否则204行的alert会执行两次
map.centerAndZoom(new BMapGL.Point(map1.split(',')[0] + 0.5, map1.split(',')[1] + 0.5), 12);
//计算驾车路线时间和距离 由于现在无法实现用户输入两地自动获取其坐标,只能借助百度拾取坐标系统或者通过控件变相实现
var output = "";
var searchComplete = function (results) {
console.log('测试1');
if (transit.getStatus() != BMAP_STATUS_SUCCESS) {
return;
}
else {
//将数据传递到html页面
var jctime = results.getPlan(0).getDuration(true);
var stime = document.getElementById("time");
stime.innerHTML = jctime;
var jcdistance = results.getPlan(0).getDistance(true)
var sdistance = document.getElementById("distance");
sdistance.innerHTML = jcdistance;
//获取时间-获取距离
output = "此次驾车需要" + jctime + "\n" + "总路程为:" + jcdistance + "\n";
console.log('测试2');
}
}
//
var transit = new BMapGL.DrivingRoute(map, {
renderOptions: { map: map, autoViewport: true },
onSearchComplete: searchComplete,
onPolylinesSet() {
//可以通过alert弹出相应信息,使用settimeout进行延时
// setTimeout(function () { alert(output) }, "3000");
}
});
//动态获取用户输入的两地坐标
var start = new BMapGL.Point(map1.split(',')[0], map1.split(',')[1]);
var end = new BMapGL.Point(map2.split(',')[0], map2.split(',')[1]);
transit.search(start, end);
}
/**/
功能需求:
1.调用百度api实现旅游路线的规划,如何调用百度api请参考https://lbsyun.baidu.com/
2.添加自定义控件 https://lbsyun.baidu.com/index.php?title=open/jsdemo
注意区分BMapGL 和 BMap 的区别,前者无法实现点击图标显示百度地图自带的附属信息
详情参考文档 https://www.jianshu.com/p/1b99444f9a70
3.针对驾车路线和时间距离进行动态获取(如果你想从服务器传递数据,那就更加可以完善这个功能了,可惜我不会)
具体实现:
利用js获取表单信息,然后传递给html;
本来想用vue,但是突然发现vue的方法被js所调用也要通过js的onclick事件进行操作
本人vue学习的不是很好,不会使用vue的watch方法进行监测,同时百度地图api是基于js调用的,很难将百度api的代码放到vue的方法里面
对于外部ui,大家可以使用以下element ui (不过这个需要与vue.js对应版本并结合使用)
问题解决:
1.动态数据获取并随时刷新:利用onclick事件监听,每提交一次就重新刷新map地图,这样可以解决外部与get互不冲突,并且不会保留原有的起始点和终点的路线信息
2.对数据的分割和截取处理,利用js的split方法
3.将数据传递到html,使用innerhtml
4.对坐标信息进行小数点截取,利用toFixed()方法
功能完善:
1.暂无法实现让用户直接输入两地城市名来自动获取坐标,如有大佬看见,给我推荐一个有效的解决办法,或者提供新思路,如何将百度拾取坐标系统调用
或者通过自建json数据,指定24个城市之间的坐标信息,然后间接实现部分功能,关于json数据得获取可以直接用python批量获取,可以去网上找源码
2.如何解决代码复用的问题,setMap和getMap是同一个函数,但是在内部直接调用外部函数会间接执行两次,导致函数内部点击事件失效。如果有小伙伴能够解决,欢迎不吝赐教!
相关资源:
驾车路线模板:https://lbsyun.baidu.com/jsdemo.htm#sLngLatSearchPath