基于百度路书js实现车辆轨迹回放功能:接到一个新需求,实现车辆历史轨迹回放功能,之前没有做过,根据网上各种文章走了一些坑,基本上都是半成品,最后还是看百度地图原生api完成开发,现在把最终结果分享给大家。
项目技术选型:我们这里是springboot项目,前端框架是bootstrap,页面采用html,所以采用javascript地图解决方案,之前有百度地图做过可视化,所以选择百度地图+javascript+路书实现。
前提:必须有可连续描点成轨迹线路的经纬度数据,我们已有gps硬件三方api可以获取指定时间段内的车辆gps定位经纬度数据,json格式,这个是前提。还有注意经纬度格式和地图匹配,我这里使用百度地图,经纬度格式符合百度地图描点要求。开发前先要在百度地图申请开发者AK,具体方法百度一下即可。
说明:首先注意js引入的百度地图版本,不同的版本关于map操作语法不一样,早期没有路书,车辆轨迹回放是通过图层遮盖实现的,比较麻烦,后期版本加入了路书功能,实现更加简单,这里使用新版本BMapGL。
注意:BMapGL和BMap不一样,跟引入的百度地图版本有关。
<script type="text/javascript"
src="http://api.map.baidu.com/api?type=webgl&v=1.0&ak=你的ak"></script>
<script type="text/javascript" src="http://bj.bcebos.com/v1/mapopen/github/BMapGLLib/Lushu/src/Lushu.min.js"></script>
两种效果,一种普通地图,一种卫星地图,区别只有几行代码,普通地图注释掉就可以了。
点击左下角按钮,可以控制汽车动画开始、停止、暂停等操作。
代码如下(示例):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>路书</title>
<style type="text/css">
body,
html {
width: 100%;
height: 100%;
margin: 0;
font-family: "微软雅黑";
}
ul li {list-style: none;}
#map_canvas {
width: 100%;
height: 100%;
}
#result {
width: 100%
}
#btns {
z-index: 999;
position: fixed;
bottom: 3.5rem;
margin-left: 2.5rem;
padding-left: 0;
border-radius: .25rem;
display: flex;
box-shadow: 0 2px 6px 0 rgba(27, 142, 236, 0.5);
text-align:center;
}
#btns li{
border-right: 1px solid #d2d2d2;
padding:10px 10px;
height: 100%;
background-color: #fff;
cursor: pointer;
color:#3a79b5;
}
</style>
<script>
window.BMAP_AUTHENTIC_KEY = '7Cc5Kmn672miPzG4qQhvlOrERcXMMinq';
</script>
<!-- JavaScript Plugins -->
<script type='text/javascript' src='/js/utils/jquery-1.7.2.min.js' ></script>
<script type='text/javascript' src='/js/utils/jquery.mousewheel.min.js' ></script>
<script type='text/javascript' src='/js/utils/jquery.placeholder.js' ></script>
<script type='text/javascript' src='/js/utils/jquery.fileinput.js' ></script>
<script type='text/javascript' src='/js/utils/jquery.form.js' ></script>
<script type="text/javascript"
src="http://api.map.baidu.com/api?type=webgl&v=1.0&ak=你的ak"></script>
<script type="text/javascript" src="http://bj.bcebos.com/v1/mapopen/github/BMapGLLib/Lushu/src/Lushu.min.js"></script>
<style>
html,body,#container {
width: 100%;
height: 100%;
overflow: hidden;
margin: 0;
padding: 0
}
.info {
z-index: 999;
width: auto;
padding: 10px;
margin-left: 10px;
position: fixed;
top: 10px;
background-color: #fff;
border-radius: 5px;
font-size: 14px;
color: #666;
box-shadow: 0 2px 6px 0 rgba(27, 142, 236, 0.5);
}
ul li {
list-style: none;
}
.btn-wrap {
z-index: 999;
position: fixed;
bottom: 30px;
left: 10px;
padding: 10px;
border-radius: 5px;
background-color: #fff;
box-shadow: 0 2px 6px 0 rgba(27, 142, 236, 0.5);
}
.btn {
width: 100px;
height: 30px;
float: left;
background-color:rgba(265, 265, 265, 0.9);
color: rgba(27, 142, 236, 1);
font-size: 14px;
border:1px solid rgba(27, 142, 236, 1);
border-radius: 5px;
margin: 0 5px;
text-align: center;
line-height: 30px;
}
.btn:hover {
background-color: rgba(27, 142, 236, 0.8);
color: #fff;
cursor: pointer;
}
</style>
</head>
<body>
<div id="map_canvas"></div>
<div id="result"></div>
<ul id='btns'>
<li id="run">开始</li>
<li id="stop">停止</li>
<li id="pause">暂停</li>
<li id="hide">隐藏信息窗口</li>
<li id="show">展示信息窗口</li>
<li id="showRoadNet">显示路网</li>//不需要卫星地图的注释掉
<li id="hideRoadNet">隐藏路网</li>//不需要卫星地图的注释掉
</ul>
<script type="text/javascript">
//获取历史轨迹数据,后台获取经纬度api接口
window.onload = function(){
//查询基础数据
$.ajax({
type:'get',
async:false,
dataType:"json",
url : "后台获取经纬度api接口",
success : function(data) {
setTrackmap(data.aaData,data.carNum)
}
});
}
function setTrackmap(arrPois,carNum) {
if(arrPois!=null && arrPois!=false){
var map = new BMapGL.Map('map_canvas');
//控件
map.addControl(new BMapGL.ZoomControl());// 添加缩放控件
map.enableScrollWheelZoom();
map.setMapType(BMAP_EARTH_MAP); // 设置地图类型为地球模式,不需要卫星地图的注释掉
// map.centerAndZoom(new BMapGL.Point(116.404, 39.915), 13);
map.setTilt(73);//不需要卫星地图的注释掉
//开始位置 结束位置 开始时间,结束时间
var startPoint,endPoint;
var arrPoisT = [];//点位信息
//经纬度点位整理
for (let i = 0 && arrPois.length>0; i < arrPois.length; i++) {
var point = new BMapGL.Point(arrPois[i].toString().split(',')[0],arrPois[i].toString().split(',')[1]);
//业务逻辑
if(i===0){
//开始位置
startPoint = point
}
//结束位置
endPoint=point
arrPoisT.push(point);
}
map.centerAndZoom(arrPoisT[0], 12);
var lushu;
var marker;
var markerStart = new BMapGL.Marker(startPoint); // 创建标注
var markerEnd = new BMapGL.Marker(endPoint); // 创建标注
//添加开始结束点
//map.addOverlay(markerStart);
map.addOverlay(markerEnd);
markerEnd.setAnimation(BMAP_ANIMATION_BOUNCE); //跳动的动画
//以下是地图上的标注信息
//markerStart.setLabel(setLabelStyle("起点"));
//markerEnd.setLabel(setLabelStyle("终点"));
marker=new BMapGL.Marker(startPoint,{
//引入小车图标
icon : new BMapGL.Icon('/commonPic/car.png', new BMapGL.Size(52,26),{anchor : new BMapGL.Size(27, 13)})
});
//展示时小车样式
var label = new BMapGL.Label(carNum,{offset:new BMapGL.Size(-33,-45)});
label.setStyle({textAlign: 'center',border:"white .5px solid",color: "white",borderRadius:"2px",boxShadow:'0 0 1px 2px #1e68bb',padding:"2px 9px",background:"#1e68bb",});
marker.setLabel(label);
map.addOverlay(marker);
// 实例化一个驾车导航用来生成路线
var drv = new BMapGL.DrivingRoute('地区', {
onSearchComplete: function (res) {
if (drv.getStatus() == BMAP_STATUS_SUCCESS) {
var plan = res.getPlan(0);
/* var arrPois = [];
for (var j = 0; j < plan.getNumRoutes(); j++) {
var route = plan.getRoute(j);
arrPois = arrPois.concat(route.getPath());
} */
map.addOverlay(new BMapGL.Polyline(arrPoisT, {
strokeColor : "red",
strokeWeight : 5,//宽度
strokeOpacity : 1//透明度
}));
map.setViewport(arrPoisT);
lushu = new BMapGLLib.LuShu(map, arrPoisT, {
defaultContent: carNum, // "信息窗口文案"
autoView: true, // 是否开启自动视野调整,如果开启那么路书在运动过程中会根据视野自动调整
speed: 500,
// icon: new BMapGL.Icon('./images/car.png', new BMapGL.Size(32, 32), { anchor: new BMapGL.Size(10, 10) }),
icon: new BMapGL.Icon('/commonPic/car.png', new BMapGL.Size(52,26),{anchor : new BMapGL.Size(27, 13)}),
enableRotation: true, // 是否设置marker随着道路的走向进行旋转
});
}
}
});
//点击小车开始监听事件
marker.addEventListener("click",function(){
marker.enableMassClear(); //设置后可以隐藏改点的覆盖物
marker.hide();
lushu.start();
//map.clearOverlays(); //清除所有覆盖物
});
drv.search(startPoint, endPoint);
//绑定事件
$("run").onclick = function () {
marker.enableMassClear(); //设置后可以隐藏改点的覆盖物
marker.hide();
//开始
lushu.start();
}
$("stop").onclick = function () {
//停止
lushu.stop();
}
$("pause").onclick = function () {
//暂停
lushu.pause();
}
$("hide").onclick = function () {
//隐藏信息窗口
lushu.hideInfoWindow();
}
$("show").onclick = function () {
//展示信息窗口
lushu.showInfoWindow();
}
$("showRoadNet").onclick = function () {
map.setDisplayOptions({
street: true, //是否显示路网(只对卫星图和地球模式有效),不需要卫星地图的注释掉
})
}
$("hideRoadNet").onclick = function () {
map.setDisplayOptions({
street: false, //是否显示路网(只对卫星图和地球模式有效),不需要卫星地图的注释掉
})
}
function $(element) {
return document.getElementById(element);
}
}else{
var map = new BMapGL.Map('map_canvas');
map.enableScrollWheelZoom();
map.setMapType(BMAP_EARTH_MAP); // 设置地图类型为地球模式
// map.centerAndZoom(new BMapGL.Point(116.404, 39.915), 13);
//控件
map.addControl(new BMapGL.ZoomControl());// 添加缩放控件
var startPoint = new BMapGL.Point(116.643367,41.217292);
map.centerAndZoom(startPoint, 11);
var lushu;
var marker;
var markerStart = new BMapGL.Marker(startPoint); // 创建标注
//var markerEnd = new BMapGL.Marker(endPoint); // 创建标注
//添加开始结束点
//map.addOverlay(markerStart);
//map.addOverlay(markerEnd);
//markerEnd.setAnimation(BMAP_ANIMATION_BOUNCE); //跳动的动画
//以下是地图上的标注信息
//markerStart.setLabel(setLabelStyle("起点"));
//markerEnd.setLabel(setLabelStyle("终点"));
marker=new BMapGL.Marker(startPoint,{
//引入小车图标
icon : new BMapGL.Icon('/commonPic/car.png', new BMapGL.Size(52,26),{anchor : new BMapGL.Size(27, 13)})
});
//展示时小车样式
var label = new BMapGL.Label("车辆无信号",{offset:new BMapGL.Size(-33,-45)});
label.setStyle({textAlign: 'center',border:"white .5px solid",color: "white",borderRadius:"2px",boxShadow:'0 0 1px 2px #1e68bb',padding:"2px 9px",background:"#1e68bb",});
marker.setLabel(label);
map.addOverlay(marker);
//绑定事件
$("run").onclick = function () {
marker.enableMassClear(); //设置后可以隐藏改点的覆盖物
marker.hide();
//开始
lushu.start();
}
$("stop").onclick = function () {
//停止
lushu.stop();
}
$("pause").onclick = function () {
//暂停
lushu.pause();
}
$("hide").onclick = function () {
//隐藏信息窗口
lushu.hideInfoWindow();
}
$("show").onclick = function () {
//展示信息窗口
lushu.showInfoWindow();
}
function $(element) {
return document.getElementById(element);
}
}
}
</script>
</body>
</html>
百度路书其实也是封装了原有图层遮盖描点的方法,只是更加简单方便,开箱即用,比较适合我这种后台开发。