幾年前用高德地圖做過手機(jī)版的軌跡回放妓湘,準(zhǔn)備用Openlayers
來實(shí)現(xiàn)一個(gè)web
版的軌跡回放联逻,軌跡回放的原理相對比較簡單甜刻,首先將車輛的軌跡添加在地圖上,然后再添加一個(gè)軌跡點(diǎn)纱扭,設(shè)置一個(gè)速度胰舆,讓軌跡點(diǎn)在線上移動塞蹭。實(shí)現(xiàn)方式如下所示:
添加軌跡
由于沒有數(shù)據(jù)棘捣,在地圖上隨便找了一些點(diǎn)用于測試。
//添加軌跡線和起始點(diǎn)
addLineWithPoints(coordinates){
var geom = new ol.geom.LineString(coordinates);
//創(chuàng)建軌跡Feature
var feature = new ol.Feature({
geometry:geom
})
//創(chuàng)建矢量圖層
var vectorLayer = LayerUtil.vectorLayer()
//添加軌跡
vectorLayer.getSource().addFeature(feature)
//設(shè)置樣式
vectorLayer.setStyle(this.getStyle())
this.map.addLayer(vectorLayer)
//添加起點(diǎn)
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:'起點(diǎn)',
offsetY:-10
})
}))
vectorLayer.getSource().addFeature(startFeature)
//添加終點(diǎn)
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:'終點(diǎn)',
offsetY:-10
})
}))
vectorLayer.getSource().addFeature(endFeature)
//添加小車默勾,這里使用一個(gè)圓點(diǎn)代替
var carFeature = new ol.Feature({
geometry:new ol.geom.Point(coordinates[0])
})
vectorLayer.getSource().addFeature(carFeature)
}
添加的后效果如下所示:
軌跡.png
軌跡回放
添加好軌跡后碉渡,就要實(shí)現(xiàn)軌跡回放了,直接看代碼吧母剥,代碼中有注釋看起來也方便爆价,所有的代碼都在下邊:
class TrackPlayback{
constructor(map){
this.map = map
this.animating = false//是否結(jié)束
this.speed = 1//默認(rèn)速度
this.now//當(dāng)前時(shí)間
}
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({//點(diǎn)樣式使用一個(gè)圓
radius: 7,
fill: new ol.style.Fill({
color: '#ffcc33'
})
})
});
return style;
}
//添加軌跡線和起始點(diǎn)
addLineWithPoints(coordinates){
this.routeLength = coordinates.length
this.routeCoords = coordinates
var geom = new ol.geom.LineString(coordinates);
//創(chuàng)建軌跡Feature
var feature = new ol.Feature({
geometry:geom
})
//創(chuàng)建矢量圖層
var vectorLayer = LayerUtil.vectorLayer()
//添加軌跡
vectorLayer.getSource().addFeature(feature)
//設(shè)置樣式
vectorLayer.setStyle(this.getStyle())
this.map.addLayer(vectorLayer)
//添加起點(diǎn)
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:'起點(diǎn)',
offsetY:-10
})
}))
vectorLayer.getSource().addFeature(startFeature)
//添加終點(diǎn)
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:'終點(diǎn)',
offsetY:-10
})
}))
vectorLayer.getSource().addFeature(endFeature)
//添加小車,這里使用一個(gè)圓點(diǎn)代替
var carFeature = new ol.Feature({
geometry:new ol.geom.Point(coordinates[0])
})
this.geoMarker = carFeature
vectorLayer.getSource().addFeature(carFeature)
this.vectorLayer = vectorLayer
}
//設(shè)置速度
setSpeed(speed){
this.speed = speed
}
//開始播放
play(){
if (this.animating) {
this._stopAnimation(false);
} else {
//刪除開始添加的點(diǎn)
this.vectorLayer.getSource().removeFeature(this.geoMarker)
this.animating = true//設(shè)置為已經(jīng)開始動畫
this.now = new Date().getTime()//獲取當(dāng)前時(shí)間
var self = this
//監(jiān)聽圖層渲染后的事件
this.vectorLayer.on('postrender', function(event){
self._moveFeature(event)
});
}
}
//停止
stop(){
this._stopAnimation(true);
}
//移動要素
_moveFeature(event){
//獲取渲染圖層的畫布
var vectorContext = ol.render.getVectorContext(event);
//獲取當(dāng)前渲染幀狀態(tài)的對象
var frameState = event.frameState;
if (this.animating) {
//渲染時(shí)的時(shí)間減去開始播放軌跡的時(shí)間
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;
}
//取出坐標(biāo)點(diǎn)重新繪制
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);
}
}