百度地图API路书实现历史轨迹回放

该文章介绍了如何使用百度地图API实现路书功能,包括轨迹回放、开始/暂停/继续控制、滑动条调节播放速度和进度。此外,还展示了如何在路书运动过程中更新信息窗口内容以及通过BMap.DrivingRoute修正轨迹路径。
摘要由CSDN通过智能技术生成

以下内容设计的主要功能点:

目录

路书的基本使用

路书的开始、暂停、继续

滑动条控制路书速度

滑动条控制路书进度

路书运动过程信息窗口内容改变

路书边运动边画轨迹(使用BMap.DrivingRoute对路径进行修正)


接下来依次实现上述功能

路书的基本使用

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title>百度地图API路书实现历史轨迹回放</title>
		<script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=你的密钥"></script>
		<!--  你在百度地图开放平台申请的ak -->
		
		<!-- 路书功能 -->
        <script src="http://api.map.baidu.com/library/LuShu/1.2/src/LuShu_min.js"></script>
	</head>
	<body>
        <!-- 地图容器 -->
		<div id="allmap" style="position: absolute; width: 100%; top: 50px; bottom: 0px"></div>
		    
		<script type="text/javascript">
		
	    <!--新建地图及添加控件-->
        var map = new BMap.Map("allmap", { minZoom: 9, maxZoom: 19 });
        var point = new BMap.Point(116.128554, 24.294562);
        map.centerAndZoom(point, 9); //设置中心点和缩放比例
        var top_left_navigation = new BMap.NavigationControl();
        map.addControl(top_left_navigation);// 添加平移缩放控件
        map.addControl(new BMap.ScaleControl({ anchor: BMAP_ANCHOR_TOP_LEFT })); // 添加比例尺控件
        map.addControl(new BMap.OverviewMapControl()); //添加缩略地图控件
        map.enableScrollWheelZoom();//启用滚轮放大缩小
              
       //中心点坐标
		var carCenterPoint = new BMap.Point(113.408984, 23.174023);
	    map.centerAndZoom(carCenterPoint , 17);


	    //显示车辆轨迹线
		//车辆轨迹坐标
		var latLngArray = [
			"113.408984,23.174023",
			"113.406639,23.174023",
			"113.403944,23.173566",
			"113.400827,23.17394",
			"113.397468,23.174496",
			"113.391494,23.174513",
			"113.389032,23.174588",
			"113.388736,23.173217",
			"113.388511,23.171888",
			"113.388592,23.170501",
			"113.38861,23.170219",
			"113.38861,23.168342",
			"113.388574,23.165218"
		];
		
		
        //添加路书图标
		var icons = new BMap.Icon('C:\\Users\\out of the common\\Downloads\\car.png', new BMap.Size(32,32),{anchor: new BMap.Size(16, 16)});
		//路书默认信息窗口内容
		var trackContent = "某车辆轨迹回放";
		//添加路书
		var lushu = new BMapLib.LuShu(map,pois,{
			defaultContent: trackContent,
			icons: [icons],
			autoView: false,//是否开启自动视野调整,如果开启那么路书在运动过程中会根据视野自动调整
			speed: 100, //路书速度
			enableRotation: true,//是否设置marker随着道路的走向进行旋转
		});
		

    </script>
	</body>
	
</html>

路书的开始、暂停、继续

增加控件

<div id="controls">
			<!-- 开始按钮 -->
			<button onclick="start()">开始</button>
			<!-- 暂停按钮 -->
			<button onclick="pause()">暂停</button>
			<!-- 继续按钮 -->
			<button onclick="resume()">继续</button>
			 <!-- 暂停按钮 -->
			<button onclick="stop()">暂停</button>
			<!-- 播放进度条 -->
			<input type="range" id="progress" min="0" max="100" value="0" step="1">
</div>

增加js代码

// 定义开始、暂停、继续、停止函数
        function start() {
            lushu.start();
        }
        function pause() {
            lushu.pause();
        }
        function resume() {
            lushu.start();
        }
        function stop() {
            lushu.stop();
        }

完整代码

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title>百度地图API路书实现历史轨迹回放</title>
		<script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=你的密钥"></script>
		<!--  你在百度地图开放平台申请的ak -->
		
		<!-- 路书功能 -->
        <script src="http://api.map.baidu.com/library/LuShu/1.2/src/LuShu_min.js"></script>
	</head>
	<body>
		<!-- 在此处添加控制按钮和滑动条 -->
		<div id="controls">
			<!-- 开始按钮 -->
			<button onclick="start()">开始</button>
			<!-- 暂停按钮 -->
			<button onclick="pause()">暂停</button>
			<!-- 继续按钮 -->
			<button onclick="resume()">继续</button>
			 <!-- 暂停按钮 -->
			<button onclick="stop()">暂停</button>
		</div>
		<div id="allmap" style="position: absolute; width: 100%; top: 50px; bottom: 0px"></div>
		    
		<script type="text/javascript">
		
		
			
			
        var map = new BMap.Map("allmap", { minZoom: 9, maxZoom: 19 });
        var point = new BMap.Point(116.128554, 24.294562);
        var top_left_navigation = new BMap.NavigationControl();
        map.addControl(top_left_navigation);// 添加平移缩放控件
        map.addControl(new BMap.ScaleControl({ anchor: BMAP_ANCHOR_TOP_LEFT })); // 添加比例尺控件
        map.addControl(new BMap.OverviewMapControl()); //添加缩略地图控件
        map.enableScrollWheelZoom();//启用滚轮放大缩小
        map.centerAndZoom(point, 9);
        
		//中心点坐标
		var  carCenterPoint = new BMap.Point(113.408984, 23.174023);
		map.centerAndZoom(carCenterPoint , 17);
		

		
		var pois = [];
		//车辆轨迹坐标
		var latLngArray = [
			"113.408984,23.174023",
			"113.406639,23.174023",
			"113.403944,23.173566",
			"113.400827,23.17394",
			"113.397468,23.174496",
			"113.391494,23.174513",
			"113.389032,23.174588",
			"113.388736,23.173217",
			"113.388511,23.171888",
			"113.388592,23.170501",
			"113.38861,23.170219",
			"113.38861,23.168342",
			"113.388574,23.165218"
		];
		
		//对坐标进行处理,获取BMap.Point对象
		for(var i = 0; i < latLngArray.length ; i++) {
			var latLng = latLngArray[i];
			var pointArray = latLng.split(",");
			pois.push(new BMap.Point(pointArray[0], pointArray[1]));
		}
		
		//轨迹显示样式
		var sy = new BMap.Symbol(BMap_Symbol_SHAPE_BACKWARD_OPEN_ARROW, {
			scale: 0.6,//图标缩放大小
			strokeColor: '#fff',//设置矢量图标的线填充颜色
			strokeWeight: '2',//设置线宽
		});
		var icons = new BMap.IconSequence(sy, '10', '30');

		//创建polyline对象
		var polyline = new BMap.Polyline(pois, {
			enableEditing: false,//是否启用线编辑,默认为false
			enableClicking: true,//是否响应点击事件,默认为true
			icons: [icons],
			strokeWeight: '8',//折线的宽度,以像素为单位
			strokeOpacity: 0.8,//折线的透明度,取值范围0 - 1
			strokeColor: "#18a45b" //折线颜色
			
		});
		map.addOverlay(polyline);
		
		//添加路书图标
		var ls_icons = new BMap.Icon('C:\\Users\\out of the common\\Downloads\\car.png', new BMap.Size(32,32),{anchor: new BMap.Size(16, 16)});
		//路书默认信息窗口内容
		var trackContent = "某车辆轨迹回放";
		//添加路书
		var lushu = new BMapLib.LuShu(map,pois,{
			defaultContent: trackContent,
			icons: [ls_icons],
			autoView: false,//是否开启自动视野调整,如果开启那么路书在运动过程中会根据视野自动调整
			speed: 100,
			enableRotation: true,//是否设置marker随着道路的走向进行旋转
		});
		
	   

        // 定义开始、暂停、继续、停止函数
        function start() {
            lushu.start();
        }
        function pause() {
            lushu.pause();
        }
        function resume() {
            lushu.start();
        }
        function stop() {
            lushu.stop();
        }

    </script>
	</body>
	
</html>

滑动条控制路书速度

添加控件


这里滑动条用的是Bootstrap Slider

<!-- 引入 Bootstrap Slider 相关文件 -->
        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-slider/11.0.2/css/bootstrap-slider.min.css">
        <script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-slider/11.0.2/bootstrap-slider.min.js"></script>

<!-- 播放速度 -->
<span>播放速度</span>
<input type="range" id="speed">

添加代码

    //滑动条
	var slider = new Slider('#speed', {
			min: 1, //最小值
			max: 500, //最大值
			step: 50, //步长
			value: 100, //默认值
		});
		slider.on("change", function (obj) { //滑动条改变事件
			var value = obj.newValue;
			if (lushu != null) {
				lushu._opts.speed = parseInt(value);
			}			
		});

滑动条控制路书进度

添加控件

			<!-- 播放进度条 -->
			<span>播放进度</span>
			<input type="range" id="process">

添加代码

  1. 滑动条控制进度

    设置滑动条的最大值为路书数据的长度-1,当拖动时修改路书实例的属性,这个 对应的就是路书当前运动的数据索引。
    			$('#process').slider({
                    orientation: "horizontal", //排列方式
                    value: 0,
                    min: 0,
                    max: pois.length - 1, //pois为路书数据
                    slide: function (event, ui) {    //拖动
                        if (lushu.i < ui.value) {  //快进 如果滑动条的进度大于路书当前的进度,则把滑动条设置为路书当前的进度                               
                            $('#process').slider('value', lushu.i);
                        } else {  //后退
                            lushu.i = ui.value;
                        }
    					
    					if (ui.value == pois.length - 1) {
                                pause();
                        }
    				}
                       
                });
  2. 滑动条的值随着路书的运动增加
    其实就是重写路书的源码,BMapLib.LuShu.prototype._move指的就是路书运动时执行的函数,增加的代码就一行:$('#process').slider('value', this.i);
BMapLib.LuShu.prototype._move = function (initPos, targetPos, effect) {
                        
                        $('#process').slider('setValue', this.i);

                        var me = this,
                            //当前的帧数
                            currentCount = 0,
                            //步长,米/秒
                            timer = 10,
                            step = this._opts.speed / (1000 / timer),
                            //初始坐标
                            init_pos = this._projection.lngLatToPoint(initPos),
                            //获取结束点的(x,y)坐标
                            target_pos = this._projection.lngLatToPoint(targetPos),
                            //总的步长
                            count = Math.round(me._getDistance(init_pos, target_pos) / step);
                       
                        //如果小于1直接移动到下一点
                        if (count < 1) {
                            me._moveNext(++me.i);
                            return;
                        }

                        me._intervalFlag = setInterval(function () {
                            //两点之间当前帧数大于总帧数的时候,则说明已经完成移动
                            if (currentCount >= count) {
                                clearInterval(me._intervalFlag);
                                //移动的点已经超过总的长度
                                if (me.i > me._path.length) {
                                    return;
                                }
                                //运行下一个点
                                me._moveNext(++me.i);
                            } else {
                                currentCount++;
                                var x = effect(init_pos.x, target_pos.x, currentCount, count),
                                    y = effect(init_pos.y, target_pos.y, currentCount, count),
                                    pos = me._projection.pointToLngLat(new BMap.Pixel(x, y));
                                //设置marker
                                if (currentCount == 1) {
                                    var proPos = null;
                                    if (me.i - 1 >= 0) {
                                        proPos = me._path[me.i - 1];
                                    }
                                    if (me._opts.enableRotation == true) {
                                        me.setRotation(proPos, initPos, targetPos);
                                    }
                                    if (me._opts.autoView) {
                                        if (!me._map.getBounds().containsPoint(pos)) {
                                            me._map.setCenter(pos);
                                        }
                                    }
                                }
                                //正在移动
                                me._marker.setPosition(pos);
                                //设置自定义overlay的位置
                                me._setInfoWin(pos);
                            }


                        }, timer);
                    };

路书运动过程信息窗口内容改变

重写源码

其实关键代码也只有me._overlay.setHtml("现在运动到第"+me.i+"个数据了");

BMapLib.LuShu.prototype._setInfoWin = function (pos) {
                        //设置上方overlay的position
                        var me = this;
                        if (!me._overlay) {
                            return;
                        }
                        me._overlay.setPosition(pos, me._marker.getIcon().size);
                        var index = me._troughPointIndex(pos);
                        if (index != -1) {
                            clearInterval(me._intervalFlag);
                            me._overlay.setHtml(me._opts.landmarkPois[index].html);
                            me._overlay.setPosition(pos, me._marker.getIcon().size);
                            me._pauseForView(index);
                        } else {
                            me._overlay.setHtml("现在运动到第"+me.i+"个数据了");
                        }
                    };

路书边运动边画轨迹(使用BMap.DrivingRoute对路径进行修正)

修改BMapLib.LuShu.prototype._move

直接加代码,我这里使用了bmap.drivingroute(百度地图路线规划),因为有时候我们的点坐标不准容易飘点,画出来的线路不在道路上。

initPos和targetPos就是路书每次运动的开始点和结束点

onsearchcomplete是获取driving.search结果之后的回调函数,具体的可以去官网详细看看

jspopular | 百度地图API SDK

onmarkersset是获取图标,我这里的操作是删除了始发站和终点站的图标

var pointsArr = [initPos,targetPos];
var driving = new bmap.drivingroute(map, {
                            onsearchcomplete: function (results) {

                                if (driving.getstatus() == bmap_status_success) {
                                    let path = results.getplan(0).getroute(0).getpath();
                                    let polyline = new bmap.polyline(path, { strokecolor: "#18a45b", strokeweight: 8 });
                                    map.addoverlay(polyline);
                                    _this.group.push(polyline);
                                }
                            },
                            onmarkersset: function (routes) {
                                map.removeoverlay(routes[0].marker); //删除起点
                                map.removeoverlay(routes[1].marker);//删除终点
                            }
                        });
driving.search(pointsArr[0], pointsArr[1]);

要是不想用线路规划直接添加折线也可以的,完整的代码如下

			BMapLib.LuShu.prototype._move = function (initPos, targetPos, effect) {

                        $('#process').slider('setValue', this.i);
						
						var pointsArr = [initPos,targetPos];
                        var me = this,
                            //当前的帧数
                            currentCount = 0,
                            //步长,米/秒
                            timer = 10,
                            step = this._opts.speed / (1000 / timer),
                            //初始坐标
                            init_pos = this._projection.lngLatToPoint(initPos),
                            //获取结束点的(x,y)坐标
                            target_pos = this._projection.lngLatToPoint(targetPos),
                            //总的步长
                            count = Math.round(me._getDistance(init_pos, target_pos) / step);

                        //    //添加折线
						var driving = new bmap.drivingroute(map, {
                            onsearchcomplete: function (results) {

                                if (driving.getstatus() == bmap_status_success) {
                                    let path = results.getplan(0).getroute(0).getpath();
                                    let polyline = new bmap.polyline(path, { strokecolor: "#18a45b", strokeweight: 8 });
                                    map.addoverlay(polyline);
                                    _this.group.push(polyline);
                                }
                            },
                            onmarkersset: function (routes) {
                                map.removeoverlay(routes[0].marker); //删除起点
                                map.removeoverlay(routes[1].marker);//删除终点
                            }
                        });
                        driving.search(pointsarr[0], pointsarr[1]);

                        //如果小于1直接移动到下一点
                        if (count < 1) {
                            me._moveNext(++me.i);
                            return;
                        }

                        me._intervalFlag = setInterval(function () {
                            //两点之间当前帧数大于总帧数的时候,则说明已经完成移动
                            if (currentCount >= count) {
                                clearInterval(me._intervalFlag);
                                //移动的点已经超过总的长度
                                if (me.i > me._path.length) {
                                    return;
                                }
                                //运行下一个点
                                me._moveNext(++me.i);
                            } else {
                                currentCount++;
                                var x = effect(init_pos.x, target_pos.x, currentCount, count),
                                    y = effect(init_pos.y, target_pos.y, currentCount, count),
                                    pos = me._projection.pointToLngLat(new BMap.Pixel(x, y));
                                //设置marker
                                if (currentCount == 1) {
                                    var proPos = null;
                                    if (me.i - 1 >= 0) {
                                        proPos = me._path[me.i - 1];
                                    }
                                    if (me._opts.enableRotation == true) {
                                        me.setRotation(proPos, initPos, targetPos);
                                    }
                                    if (me._opts.autoView) {
                                        if (!me._map.getBounds().containsPoint(pos)) {
                                            me._map.setCenter(pos);
                                        }
                                    }
                                }
                                //正在移动
                                me._marker.setPosition(pos);
                                //设置自定义overlay的位置
                                me._setInfoWin(pos);
                            }


                        }, timer);
                    };

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值