angular中使用openlayer画运动轨迹从初始化开始
初始化地图
mapBasicLayerSource = new OSM({
warpX: true
});//加载街道地图
routeCoords = [
[102.3662707918166, 29.233057577468536],
[102.95566898358834, 29.979673112610453],
[103.10564651280956, 30.068605295035848],
[103.5015264278803, 30.183655962483723],
[103.83079867892431, 30.31694162614948],
[104.02724352786919, 30.579441557719907]
]
// 初始化地图
initMap() {
const view = new View({
center: [],
zoom: this.zoomLevel,
projection: 'EPSG:4326',
minZoom: this.MinZoom,
maxZoom: this.MaxZoom
})
// projection
const projection = 'EPSG:4326';
const layers = [];
this.mapOptions = {
target: 'mainMap',
projection,
layers,
view,
controls: [
// new MousePosition(
// {
// target: document.getElementById('mouse-position')
// }
// )
],
};
try {
this.map = new OLMAP(this.mapOptions);
} catch (ex) {
}
// //实例化全屏显示控件
// var fullScreenControl = new FullScreen();
// //将全屏显示控件加载到map中
// this.map.addControl(fullScreenControl);
}
加载图层
const mapBasicLayer = new TileLayer({
title: 'basicMap',
source: this.mapBasicLayerSource
});
// 把图层放入LAYERS集合中
this._layersMap.set('BASIC_LAYER', mapBasicLayer);
for (const [key, layer] of this._layersMap.entries()) {
this.map.addLayer(layer);
}
将两点之间分割成多个点,使得运动速度更平滑
const splitNumberQuick = 50// 分割点控制速度
const splitNumber = 300// 分割点控制速度
var tempPath = JSON.parse(JSON.stringify(this.routeCoords))
var pathResults = []
var tempPoint = [0, 0]
if (tempPath.length > 1) {
for (let i = 0; i < tempPath.length - 1; i++) { // 每两个点之间分割出splitNumber个点
pathResults.push(tempPath[i])
if (i == 0) {
for (let j = 0; j < splitNumber; j++) {
tempPoint[0] = (tempPath[i + 1][0] - tempPath[i][0]) * (j + 1) / splitNumber + tempPath[i][0]
tempPoint[1] = (tempPath[i + 1][1] - tempPath[i][1]) * (j + 1) / splitNumber + tempPath[i][1]
pathResults.push(JSON.parse(JSON.stringify(tempPoint)))
}
} else {
for (let j = 0; j < splitNumberQuick; j++) {
tempPoint[0] = (tempPath[i + 1][0] - tempPath[i][0]) * (j + 1) / splitNumberQuick + tempPath[i][0]
tempPoint[1] = (tempPath[i + 1][1] - tempPath[i][1]) * (j + 1) / splitNumberQuick + tempPath[i][1]
pathResults.push(JSON.parse(JSON.stringify(tempPoint)))
}
}
}
pathResults.push(tempPath[tempPath.length - 1])
this.routeCoords = pathResults
}
绘制路径和点
// lineString出现坐标点显示不全时 把坐标加上parseFloat,原因就是没有把float类型的坐标利用parseFloat强转,导致默认的泛数据类型精确度不够,经纬度小数点后末尾几位就会被忽略,于是造成数据失效,描出的线就会有问题。
var route = new LineString(this.routeCoords);
var routeLength = this.routeCoords.length;
this.routeFeature = new Feature({
type: 'route',
geometry: route,
});
this.geoMarker = /** @type Feature<import("../src/ol/geom/Point").default> */ (new Feature(
{
type: 'geoMarker',
geometry: new Point(this.routeCoords[0]),
}
));
var startMarker = new Feature({
type: 'icon',
geometry: new Point(this.routeCoords[0]),
});
var endMarker = new Feature({
type: 'icon',
geometry: new Point(this.routeCoords[routeLength - 1]),
});
var stopMakers = [];
const routeCoords = [
[],//经纬度
]
var stopText = []
for (var i = 0; i < routeCoords.length; i++) {
var s = new Feature({
type: 'stop',
geometry: new Point(routeCoords[i])
});
stopMakers.push(s);
}
for (var i = 0; i < routeCoords.length; i++) {
var s = new Feature({
type: 'text',
geometry: new Point(routeCoords[i]),
name: this.stopNameList[i]
});
stopText.push(s);
}
const that = this
this.stylesMap = {
'route': function (feature) {
var geometry = feature.getGeometry();
var length = geometry.getLength();//获取线段长度
var radio = length * 0.08;
var dradio = 10000;//投影坐标系,如3857等,在EPSG:4326下可以设置dradio=10000
var styles = [
new Style({
stroke: new Stroke({
color: "green",
width: 6,
})
})
];
for (var i = 0; i <= 1; i += radio) {
var arrowLocation = geometry.getCoordinateAt(i);
geometry.forEachSegment(function (start, end) {
if (start[0] == end[0] || start[1] == end[1]) return;
var dx1 = end[0] - arrowLocation[0];
var dy1 = end[1] - arrowLocation[1];
var dx2 = arrowLocation[0] - start[0];
var dy2 = arrowLocation[1] - start[1];
if (dx1 != dx2 && dy1 != dy2) {
if (Math.abs(dradio * dx1 * dy2 - dradio * dx2 * dy1) < 0.001) {
var dx = end[0] - start[0];
var dy = end[1] - start[1];
var rotation = Math.atan2(dy, dx);
styles.push(new Style({
geometry: new Point(arrowLocation),
image: new Icon({
src: '',
anchor: [0.75, 0.5],
rotateWithView: false,
rotation: -rotation + Math.PI,
scale: 0.3
})
}));
}
}
});
}
return styles;
},
'icon': new Style({
image: new Icon({
anchor: [0, -0.1],
scale: 0.2,
src: '',
}),
}),
'geoMarker': new Style({
image: new CircleStyle({
radius: 7,
fill: new Fill({ color: '#000' }),
stroke: new Stroke({
color: 'white',
width: 2,
}),
}),
}),
'stop': new Style({
image: new Icon({
anchor: [0.8, 1.9],
scale: 0.5,
src: '',
}),
}),
'text': function (feature) {
var styles = [
new Style({
text: new Text({
font: '12px sans-serif',
text: feature.getProperties().name,
offsetX: -6,
offsetY: -20,
textBaseline: "top",
textAlign: "center",
fill: new Fill({
color: "#000",
}),
stroke: new Stroke({ color: "rgba(255,255,255,0)" }),
})
})
];
return styles
}
};
this.vectorLayer = new VectorLayer({
source: new VectorSource({
features: [this.routeFeature, startMarker, this.geoMarker, ...stopMakers, ...stopText, endMarker],
}),
style: function (feature) {
if (that.animating && feature.get('type') === 'geoMarker') {
return null;
}
const myStyle = that.stylesMap[feature.get('type')];
if (myStyle instanceof Function) {
return myStyle(feature);
}
return myStyle;
},
});
this.map.addLayer(this.vectorLayer);
// 动画以及监听是否点击播放
var moveFeature = function (event) {
var vectorContext = getVectorContext(event);
var frameState = event.frameState;
if (that.animating) {
var elapsedTime = frameState.time - that.now;
var index = Math.round((that.speed * elapsedTime) / 100);
if (index >= routeLength) {
stopAnimation(true);
return;
}
let currentPoint = new Point(that.routeCoords[index])
var feature = new Feature(currentPoint);
vectorContext.drawFeature(feature, that.stylesMap.geoMarker);
}
that.map.render();
};
function startAnimation() {
if (that.animating) {
stopAnimation(false);
} else {
that.animating = !that.animating;
that.now = new Date().getTime();
that.speed = 5;
that.geoMarker.setStyle(null);
that.vectorLayer.on('postrender', moveFeature);
that.map.render();
}
}
function stopAnimation(ended) {
that.play = !ended
that.animating = false;
var coord = ended ? that.routeCoords[routeLength - 1] : that.routeCoords[0];
var geometry = that.geoMarker.getGeometry();
geometry.setCoordinates(coord);
//移除监听
that.vectorLayer.un('postrender', moveFeature);
}
document.getElementById('play').addEventListener('click', startAnimation, false)