使用高德地图回放车辆GPS轨迹,并添加速度和回放进度条,并支持调整,效果如下:
新增的功能:
在基础版本,有如下升级
- 速度条:可以拖动以调整车辆回放速度,且从当前位置继续回放
- 进度条:进度条表示车辆已回放的百分比,且拖动进度条车辆定位到相应的位置并继续回放
###思路分析
- 高德和marker回放相关的API
//主要靠他回放
moveAlong(path:Array,speed:Number,f:Function,circlable:Boolean)
//点移动到另一个位置,移动进度条车辆跟随移动
moveTo(lnglat:[LngLat],speed:Number, f:Function)
//停止播放
stopMove()
//继续播放 未用到
resumeMove()
未发现可以从指定点开始播放的API,所以只能迂回下了
- 假设我们得知从第100个点,开始回放;可以停止当前回放,并且从截取100到最后 的轨迹点,生成一个临时轨迹,让marker来moveAlong
- 所以在我们拖动速度条后,需要知道当前回放到哪个点
- 所以在我们拖动进度条后,需要知道当前回放到哪个点
- 进度条随车辆回放变化,需要知道当期回放到哪个点,再除以轨迹点总个数以设置回放百分比
所以关键是获取当前回放到哪个点,如下即可解决该问题
AMap.event.addListener(carMarker, 'moving', function (e) {
console.log("当前已回放: "+ e.passedPath.length)
});
关于进度条本文用的是 ion.rangeSlider,示例和用法大家可以参考官网,很简单
主要用到如下事件,我写了中文备注,大家也可以参考官网的示例
$("#demo_0").ionRangeSlider({
skin: "big",
min: 0,
max: 10,
from: 5,
onStart: function (data) {
// fired then range slider is ready
},
onChange: function (data) {
// fired on every range slider update-用鼠标拖动进度条时触发
},
onFinish: function (data) {
// fired on pointer release-用鼠标拖动进度条后,释放鼠标触发
},
onUpdate: function (data) {
// fired on changing slider with Update method-用JS方法更新进度条值后触发
}
});
那么实现思路就很清晰了
- 车辆移动,进度条跟随变化:当前车辆已回放点的个数➗轨迹点总个数 (代码137行)
- 修改速度,车辆从当前位置按新速度回放: 当前车辆停止回放,从当期位置到最后重新生成一段线路,车辆根据新轨迹回放
- 修改进度,车辆定位到相应位置:根据进度条的百分比✖️轨迹总个数,即可定位到当前百分比对应的轨迹点,将车辆移动到该位置即可(onUpdate事件)
- 修改进度后,车辆从当前位置回放:根据进度条的百分比✖️轨迹总个数,得到当前位置,生成从当前位置到最后的路径,并回放即可(onFinish事件)
源码如下
<html>
<head>
<!--bootstrap css-->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<!--rangeSlider css 进度条-->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ion-rangeslider/2.3.0/css/ion.rangeSlider.min.css"/>
<!--jquery js-->
<script src="http://libs.baidu.com/jquery/2.1.4/jquery.min.js"></script>
<!--bootstrap js-->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<!--Amap js 高德-->
<script src="https://webapi.amap.com/maps?v=1.3&key=fadee97bdcbf2dde564994f5deef0b58&plugin=AMap.Autocomplete,AMap.Walking,AMap.PlaceSearch,AMap.PolyEditor,AMap.CircleEditor,AMap.Transfer,AMap.Driving,AMap.CitySearch,AMap.Heatmap,AMap.Size" type="text/javascript"></script>
<script src="https://webapi.amap.com/ui/1.0/main.js?v=1.0.11"></script>
<!--rangeSlider js 进度条-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/ion-rangeslider/2.3.0/js/ion.rangeSlider.min.js"></script>
</head>
<body class="container">
<div class="row">
<div class="col-md-12">
<!--速度条-->
<div id="ionrange_speed"></div>
</div>
<div class="col-md-12">
<!--进度条-->
<div id="ionrange_process"></div>
</div>
<div class="col-md-12">
<button type="button" class="btn btn-info pull-right" onclick="carMarker.stopMove()">暂停</button>
<button type="button" class="btn btn-info pull-right" onclick="playCar()">播放</button>
</div>
</div>
<div class="row">
<div class="col-md-12">
<!--地图-->
<div id="mapContainer" style="height: 100%;width: 100%;">
</div>
</div>
</div>
</body>
<script type="text/javascript">
var carSpeed = 5000;//移动速度,后面调整速度已这个为基准
var carMarker; //回放车辆
var VEHICLE_PLAY_PROCESS = 0; //车辆当前回放到的百分比进度
var VEHICLE_PATH_REPLAY_START = 0;//当前回放的起点索引, 改变速度和改变进度条的时候,根据进度条百分比重新计算该数值,并从该位置开始再次回放
// 车辆轨迹、速度数据
var routeInfo = [{"lng":123.390381,"lat":41.929537,"speed":0},{"lng":123.390315,"lat":41.929736,"speed":13},{"lng":123.390331,"lat":41.930286,"speed":19},{"lng":123.390365,"lat":41.930819,"speed":25},{"lng":123.390381,"lat":41.931436,"speed":25},{"lng":123.390398,"lat":41.932069,"speed":24},{"lng":123.390416,"lat":41.932686,"speed":24},{"lng":123.390482,"lat":41.933203,"speed":20},{"lng":123.390582,"lat":41.933269,"speed":19},{"lng":123.390716,"lat":41.933287,"speed":19},{"lng":123.391433,"lat":41.933337,"speed":24},{"lng":123.392268,"lat":41.933305,"speed":26},{"lng":123.392402,"lat":41.933238,"speed":26},{"lng":123.392652,"lat":41.933071,"speed":24},{"lng":123.392819,"lat":41.932788,"speed":26},{"lng":123.393085,"lat":41.932205,"speed":30},{"lng":123.393536,"lat":41.931422,"speed":35},{"lng":123.393803,"lat":41.930956,"speed":39},{"lng":123.39407,"lat":41.930472,"speed":39},{"lng":123.394287,"lat":41.930006,"speed":41},{"lng":123.394504,"lat":41.929506,"speed":43},{"lng":123.394704,"lat":41.928972,"speed":44},{"lng":123.394921,"lat":41.928423,"speed":46},{"lng":123.395137,"lat":41.927857,"speed":46},{"lng":123.395354,"lat":41.92729,"speed":48},{"lng":123.395588,"lat":41.926707,"speed":46},{"lng":123.395822,"lat":41.926123,"speed":49},{"lng":123.396055,"lat":41.92554,"speed":47},{"lng":123.396338,"lat":41.924991,"speed":44},{"lng":123.396639,"lat":41.924508,"speed":41},{"lng":123.396939,"lat":41.924091,"speed":35},{"lng":123.397506,"lat":41.923391,"speed":28},{"lng":123.397974,"lat":41.922825,"speed":22},{"lng":123.398407,"lat":41.922375,"speed":13},{"lng":123.398841,"lat":41.921942,"speed":15},{"lng":123.399241,"lat":41.921525,"speed":24},{"lng":123.399791,"lat":41.920975,"speed":31},{"lng":123.400159,"lat":41.92061,"speed":35},{"lng":123.400876,"lat":41.919876,"speed":37},{"lng":123.401277,"lat":41.91946,"speed":41},{"lng":123.401693,"lat":41.919026,"speed":41},{"lng":123.40211,"lat":41.918576,"speed":43},{"lng":123.402527,"lat":41.918127,"spe