前言
上一章节中,在地图上绘制了车辆的标注,实际开发中,可能有这样的需求,规划一条路径,让车辆在路径上进行前进。
一、绘制路径
import LineString from 'ol/geom/LineString.js';
// gps坐标数组[[108.919_402_037_703_2, 34.138_244_794_480_784],......]
import { routes } from './data';
// 添加路线图
function addRoute() {
const features = [];
// 添加路线
const routeFeature = new Feature({
type: 'lineStyle',
geometry: new LineString(routes),
});
// 车辆走过的路线
passRouteFeature.value = new Feature({
type: 'passLineStyle',
geometry: new LineString([]),
});
features.push(routeFeature, passRouteFeature.value);
const styles = {
lineStyle: new Style({
stroke: new Stroke({
color: 'gray',
width: 5,
}),
}),
passLineStyle: new Style({
stroke: new Stroke({
color: 'green',
width: 5,
}),
}),
};
// 路径图层
const vectorLayer = new VectorLayer({
source: new VectorSource({
features,
}),
style(feature) {
return styles[feature.get('type')];
},
});
// 将图层添加到地图上
map.instance.addLayer(vectorLayer);
}
二、车辆前进
// 通过设置车辆位置的方式,让车辆进行前进
function handleMoveCar() {
if (carFeature.value) {
if (routes.length <= index.value) {
return;
}
const coord = routes[index.value];
// 设置车辆的位置
carFeature.value.setGeometry(new Point(coord));
if (routes.length > index.value + 1) {
const nextCoord = routes[index.value + 1];
// 计算车辆的角度,保证车辆的前进方向和车身方向保持一直
const angele = calculateAngle(coord, nextCoord);
carFeature.value.setStyle(
new Style({
image: new Icon({
anchor: [0.5, 1],
scale: 0.2,
src: carIcon,
rotation: angele,
}),
}),
);
}
}
}
// 返回的是弧度,而非角度
function calculateAngle(coord1: any[], coord2: any[]) {
// 转换为OpenLayers的坐标格式
const x1 = coord1[0];
const y1 = coord1[1];
const x2 = coord2[0];
const y2 = coord2[1];
// 计算Δx和Δy
const deltaX = x2 - x1;
const deltaY = y2 - y1;
const radian = Math.abs(Math.atan2(deltaX, deltaY));
if (x2 > x1 && y2 < y1) {
return 0 - radian;
}
if (x2 < x1 && y2 < y1) {
return radian;
}
if (x2 < x1 && y2 > y1) {
return Math.PI - radian;
}
if (x2 > x1 && y2 > y1) {
return Math.PI + radian;
}
return radian;
}
角度:数学中计算的旋转角度(0-360°);
弧度:角度对应的半径为1圆弧的长度; 180°角对应的弧度是Math.PI;
三、设置车辆已走的路径
function handleSetPassRoute() {
if (routes.length <= index.value) {
return;
}
const newArray = routes.slice(0, index.value + 1);
if (passRouteFeature.value) {
passRouteFeature.value.setGeometry(new LineString(newArray));
}
}