前置工作
var vecSource = new ol.source.Vector();
var vecLayer = new ol.layer.Vector({
source: vecSource
});
vecSource.clear();
map.addLayer(vecLayer);
1.画点
map.getOverlays().clear(); //清空之前画的点
let lonlatArr = [110,45];
const latlon = TransformUtil.gcj_decrypt_exact(lonlatArr[1], lonlatArr[0]);
const marker = new ol.Feature(new ol.geom.Point([latlon.lon, latlon.lat]));
const markerStyle = new ol.style.Style({
image: new ol.style.Icon({
src: 'images/location.png',
})
});
marker.setStyle(markerStyle);
const vectorSource = new ol.source.Vector({
features: [marker]
});
const vectorLayer = new ol.layer.Vector({
source: vectorSource
});
map.addOverlay(vectorLayer); // 将标注添加到地图中
map.getView().setCenter([latlon.lon, latlon.lat]);//设置选中井到地图中心
2.画线
const lineStyle = new ol.style.Style({
stroke: new ol.style.Stroke({
width: 3,
color: [255, 0, 0, 1]
})
});
const line_feature = new ol.Feature({
geometry: new ol.geom.LineString(coordDrawLineArr)
});
line_feature.setStyle(lineStyle);
const line_source = new ol.source.Vector({
features: [line_feature],
projection: 'EPSG:4326'
});
const line_layer = new ol.layer.Vector({
source: line_source
});
map.addLayer(line_layer);
3.绘制导航线完整代码(包含起点、终点、出行方式、方向箭头、线条描边)
drawTrace([[119.5,37.5],[120.5,38.5],[121.5,38.5],[122.5,37.5]]);
function drawTrace(coordDrawLineArr){
if (line_layer) {
map.removeLayer(line_layer); //清空之前画的线
}
map.getOverlays().clear(); //清空之前画的标志物
const line_feature = new ol.Feature({
geometry: new ol.geom.LineString(coordDrawLineArr)
});
const source = new ol.source.Vector({
features: [line_feature],
projection: 'EPSG:4326'
});
line_layer = new ol.layer.Vector({
source,
style: lineArrowStyles
});
map.addLayer(line_layer);
setPointMark(coordDrawLineArr[0],'start');
setPointMark(coordDrawLineArr.at(-1),'end');
setPointMark(coordDrawLineArr.at(-1),'car');
}
/**
* 内部箭头样式
* 用于每次渲染集合体的时候,OL 均会调用此函数以获得自定义样式
* @param feature
* @param res
* @returns {undefined[]}
*/
const lineArrowStyles = function (feature, res) {
let geometry = feature.getGeometry();
let styles = [
new ol.style.Style({
stroke: new ol.style.Stroke({
color: [30, 150, 250, 1],
width: 15
})
}),
new ol.style.Style({
stroke: new ol.style.Stroke({
color: [250, 100, 100, 1],
width: 10
})
})
];
// 如果几何体不是线条,这返回默认样式
if (!(geometry instanceof ol.geom.LineString)) return styles;
// 得到线条长度
const length = geometry.getLength();
// 内部箭头间隔距离(像素)
const step = 50;
// 将间隔像素距离转换成地图的真实距离
// res 是 OL 自动传入的地图比例系数
const geoStep = step * res;
// 得到一共需要绘制多少个 箭头
const arrowNum = Math.floor(length / geoStep);
const rotations = [];
const distances = [0];
// 分割线条,将折线根据坐标进行分割,并遍历
// 回调函数将传入开始坐标和结束坐标
// 利用开始距离和结束距离,得到每段线条的距离和方向信息
geometry.forEachSegment(function (start, end) {
let dx = end[0] - start[0];
let dy = end[1] - start[1];
let rotation = Math.atan2(dy, dx);
distances.unshift(Math.sqrt(dx ** 2 + dy ** 2) + distances[0])
rotations.push(rotation);
});
// 利用之前计算得到的线段矢量信息,生成对应的点样式塞入默认样式中
// 从而绘制内部箭头
for (let i = 1; i < arrowNum; ++i) {
const arrowCoord = geometry.getCoordinateAt(i / arrowNum);
const d = i * geoStep;
const grid = distances.findIndex(x => x <= d);
styles.push(
new ol.style.Style({
geometry: new ol.geom.Point(arrowCoord),
image: new ol.style.Icon({
src: 'images/arrow-right.png',
opacity: 1,
anchor: [.5, .5],
rotateWithView: true,
// 读取 rotations 中计算存放的方向信息
rotation: -rotations[distances.length - grid - 1],
scale: .05
}),
})
);
}
return styles;
}
function setPointMark(point,name){
const marker = new ol.Feature(new ol.geom.Point(point));
const iconStyle = new ol.style.Style({
image: new ol.style.Icon({
src: `images/${name}.png`
})
});
}
marker.setStyle(iconStyle);
const vectorSource = new ol.source.Vector({
features: [marker]
});
const vectorLayer = new ol.layer.Vector({
source: vectorSource
});
map.addOverlay(vectorLayer);
}
效果图: