几年前用高德地图做过手机版的轨迹回放,准备用Openlayers
来实现一个web
版的轨迹回放,轨迹回放的原理相对比较简单,首先将车辆的轨迹添加在地图上,然后再添加一个轨迹点,设置一个速度,让轨迹点在线上移动。实现方式如下所示:
添加轨迹
由于没有数据,在地图上随便找了一些点用于测试。
//添加轨迹线和起始点
addLineWithPoints(coordinates){
var geom = new ol.geom.LineString(coordinates);
//创建轨迹Feature
var feature = new ol.Feature({
geometry:geom
})
//创建矢量图层
var vectorLayer = LayerUtil.vectorLayer()
//添加轨迹
vectorLayer.getSource().addFeature(feature)
//设置样式
vectorLayer.setStyle(this.getStyle())
this.map.addLayer(vectorLayer)
//添加起点
var startFeature = new ol.Feature({
geometry:new ol.geom.Point(coordinates[0])
})
startFeature.setStyle(new ol.style.Style({
text:new ol.style.Text({
font:'15px sans-serif',
text:'起点',
offsetY:-10
})
}))
vectorLayer.getSource().addFeature(startFeature)
//添加终点
var endFeature = new ol.Feature({
geometry:new ol.geom.Point(coordinates[coordinates.length - 1])
})
endFeature.setStyle(new ol.style.Style({
text:new ol.style.Text({
font:'15px sans-serif',
text:'终点',
offsetY:-10
})
}))
vectorLayer.getSource().addFeature(endFeature)
//添加小车,这里使用一个圆点代替
var carFeature = new ol.Feature({
geometry:new ol.geom.Point(coordinates[0])
})
vectorLayer.getSource().addFeature(carFeature)
}
添加的后效果如下所示:
轨迹回放
添加好轨迹后,就要实现轨迹回放了,直接看代码吧,代码中有注释看起来也方便,所有的代码都在下边:
class TrackPlayback{
constructor(map){
this.map = map
this.animating = false//是否结束
this.speed = 1//默认速度
this.now//当前时间
}
getStyle(){
var style = new ol.style.Style({
fill: new ol.style.Fill({//填充样式
color: 'rgba(255, 255, 255, 0.2)'
}),
stroke: new ol.style.Stroke({//边框样式
color: '#ffcc33',
width: 2,
lineCap:'square'
}),
image: new ol.style.Circle({//点样式使用一个圆
radius: 7,
fill: new ol.style.Fill({
color: '#ffcc33'
})
})
});
return style;
}
//添加轨迹线和起始点
addLineWithPoints(coordinates){
this.routeLength = coordinates.length
this.routeCoords = coordinates
var geom = new ol.geom.LineString(coordinates);
//创建轨迹Feature
var feature = new ol.Feature({
geometry:geom
})
//创建矢量图层
var vectorLayer = LayerUtil.vectorLayer()
//添加轨迹
vectorLayer.getSource().addFeature(feature)
//设置样式
vectorLayer.setStyle(this.getStyle())
this.map.addLayer(vectorLayer)
//添加起点
var startFeature = new ol.Feature({
geometry:new ol.geom.Point(coordinates[0])
})
startFeature.setStyle(new ol.style.Style({
text:new ol.style.Text({
font:'15px sans-serif',
text:'起点',
offsetY:-10
})
}))
vectorLayer.getSource().addFeature(startFeature)
//添加终点
var endFeature = new ol.Feature({
geometry:new ol.geom.Point(coordinates[coordinates.length - 1])
})
endFeature.setStyle(new ol.style.Style({
text:new ol.style.Text({
font:'15px sans-serif',
text:'终点',
offsetY:-10
})
}))
vectorLayer.getSource().addFeature(endFeature)
//添加小车,这里使用一个圆点代替
var carFeature = new ol.Feature({
geometry:new ol.geom.Point(coordinates[0])
})
this.geoMarker = carFeature
vectorLayer.getSource().addFeature(carFeature)
this.vectorLayer = vectorLayer
}
//设置速度
setSpeed(speed){
this.speed = speed
}
//开始播放
play(){
if (this.animating) {
this._stopAnimation(false);
} else {
//删除开始添加的点
this.vectorLayer.getSource().removeFeature(this.geoMarker)
this.animating = true//设置为已经开始动画
this.now = new Date().getTime()//获取当前时间
var self = this
//监听图层渲染后的事件
this.vectorLayer.on('postrender', function(event){
self._moveFeature(event)
});
}
}
//停止
stop(){
this._stopAnimation(true);
}
//移动要素
_moveFeature(event){
//获取渲染图层的画布
var vectorContext = ol.render.getVectorContext(event);
//获取当前渲染帧状态的对象
var frameState = event.frameState;
if (this.animating) {
//渲染时的时间减去开始播放轨迹的时间
var elapsedTime = frameState.time - this.now;
var index = Math.round(this.speed * elapsedTime / 1000);
console.log(index)
if (index >= this.routeLength) {
this._stopAnimation(true);
return;
}
//取出坐标点重新绘制
var currentPoint = new ol.geom.Point(this.routeCoords[index]);
var feature = new ol.Feature(currentPoint);
vectorContext.drawFeature(feature,this.getStyle());
}
this.map.render();
}
_stopAnimation(ended){
this.animating = false;
var coord = ended ? this.routeCoords[this.routeLength - 1] : this.routeCoords[0];
var geometry = this.geoMarker.getGeometry();
geometry.setCoordinates(coord);
this.vectorLayer.getSource().addFeature(this.geoMarker)
this.vectorLayer.un('postrender', this._moveFeature);
}
}