用百度地图开放平台提供的功能做一个轨迹回放,包括暂停、倍速播放、重点点位标注,而且轨迹是逐渐出现,而非一段一段画出来的。
网上有轨迹回放的文章,大多是用线覆盖物一段一段的画,达不到逐渐出现的效果。而百度地图自己提供的new
BMapGLLib.TrackAnimation方法,好像无法实现倍速,调整了duration也无法实时的渲染进去,还有就是无法在到达某个点的时候做判断是否添加特殊标注。我看了TrackAnimation的api,可能通过addPath和setDuration可以实现,但是我没有成功。
我最后采用的是把TrackAnimation和setTimeout结合起来,一段一段的渲染,最终达到了我想要的效果。
首先我用到了这些变量。
var bPoints=[]; //所有点 mapPoint
var timerTask; //timeOut任务
var velocity = 1; //播放倍速
var trackAni; //轨迹事件
var targetTime;//timeOut任务执行的时间点
var remainTime;//暂停使用
var newindex;//最新点的索引
var varList;//数据库提取过来的点位的原始数据
下面这个方法从数据库提取数据,并标注起点,开始做轨迹动画
function loadTrackByTime() {
//初始化各项数据
$("#pauseBtn").html('暂停');//暂停播放按钮文字控制
if(trackAni){
trackAni.cancel();//点击回放销毁之前的动画
}
map.clearOverlays();
bPoints=[];
clearTimeout(timerTask);
//获取起止时间
var daterange = $("#select1").val().split("~");
var ADDTIMES = daterange[0];
var ADDTIMEE = daterange[1].replace(' ','');
$.ajax({
xhrFields: {
withCredentials: true
},
url: httpurl,
type: 'POST',
data: {ADDTIMES:ADDTIMES,ADDTIMEE:ADDTIMEE,tm:new Date().getTime()},
success: function (data) {
if("success" == data.result){
var path = [];
if(data.workerSite && data.workerSite.length > 0){
varList = data.workerSite;
$.each(data.workerSite,function (index, item) {
bPoints.push(new BMapGL.Point(item.W_LNG,item.W_LAT));
});
//添加起点标志
var markerS = new BMapGL.Marker(bPoints[0]);
var labelS = new BMapGL.Label('起点',{offset:new BMapGL.Size(-15,2)});
labelS.setStyle({
background:'white',color:'black',border:'1px solid',fontSize:'15px',
});
markerS.setLabel(labelS);
map.addOverlay(markerS);
//开始画轨迹
if(bPoints.length>1){
newindex = 1;
timeOutStart();
}
}
}
}
})
}
下面这个方法用来控制动画
function timeOutStart(){
if(newindex < bPoints.length){
//如果滞留,加一个标记,进入下一段
if(varList[newindex].IS_RETENTION == '是'){
var markerR = new BMapGL.Marker(bPoints[newindex]);
var labelR = new BMapGL.Label('滞留',{offset:new BMapGL.Size(-15,2)});
labelR.setStyle({
background:'white',color:'black',border:'1px solid',fontSize:'15px',
});
markerR.setLabel(labelR);
map.addOverlay(markerR);
newindex++;
setTimeout(function () {
timeOutStart();
},300/velocity);
}else{
var thisIntervla = 10000/velocity;
var tempPoints = [];
tempPoints.push(bPoints[newindex-1]);
tempPoints.push(bPoints[newindex]);
var pl = new BMapGL.Polyline(tempPoints);
trackAni = new BMapGLLib.TrackAnimation(map, pl, {
overallView: newindex === bPoints.length-1,
tilt: 80,
duration: thisIntervla,
delay: 0
});
trackAni.start();
newindex++;
if(newindex === bPoints.length-1){
//添加终点标志
var markerE = new BMapGL.Marker(bPoints[bPoints.length-1]);
var labelE = new BMapGL.Label('终点',{offset:new BMapGL.Size(-15,2)});
labelE.setStyle({
background:'white',color:'black',border:'1px solid',fontSize:'15px',
});
markerE.setLabel(labelE);
map.addOverlay(markerE);
}
timerTask = setTimeout(function () {
if(newindex < bPoints.length){
timeOutStart(newindex);
}
},thisIntervla+50)
targetTime = new Date().getTime()+thisIntervla+50;
}
}
}
下面这个方法是暂停、继续播放的方法
function pauseAni () {
if($("#pauseBtn").html() == '播放'){
trackAni.continue();
$("#pauseBtn").html('暂停');
if(remainTime){
timerTask = setTimeout(function () {
if(newindex < bPoints.length){
timeOutStart(newindex);
}
},remainTime)
targetTime = new Date().getTime()+remainTime;
}
}else if($("#pauseBtn").html() == '暂停'){
trackAni.pause();
clearTimeout(timerTask);
remainTime = targetTime - new Date().getTime();
console.log('remainTime:'+remainTime);
console.log('now:'+new Date().getTime());
$("#pauseBtn").html('播放');
}
}
最后是控制播放倍速的方法
function setV(level) {
velocity = level;
}
我借鉴了网上的很多篇文章,最后结合项目自己做出来的方法。其中的难点在于如何衔接动画,也就是如何让一个setTimeOut接上另一个setTimeOut,关键是要可以暂停。所以targetTime的使用比较重要,不能出错。
这个方法最终有一个瑕疵,倍速播放不能立即生效,必须再下一段开始时生效。但是我们的项目最多一分钟就会有一个位置点传过来,每天都有几百个点位,所以几乎不会察觉。