html
复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>OpenLayers 历史轨迹(带箭头)效果演示</title>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/ol@9.1.0/ol.css"
/>
<script src="https://cdn.jsdelivr.net/npm/ol@9.1.0/dist/ol.js"></script>
<style>
html,
body {
margin: 0;
height: 100%;
width: 100%;
}
#map {
width: 100%;
height: 100%;
background: #f8f8f8;
}
.info {
position: absolute;
top: 10px;
left: 10px;
padding: 10px;
background: rgba(255, 255, 255, 0.8);
border: 1px solid #ccc;
border-radius: 5px;
font-family: sans-serif;
z-index: 1;
}
</style>
</head>
<body>
<div id="map"></div>
<div class="info">
<h4>历史轨迹箭头效果演示</h4>
<p>
此 Demo 展示了如何使用 Style Function 动态为每一段轨迹线添加方向箭头。
</p>
</div>
<script>
/**
* 核心函数:绘制历史轨迹(带箭头方向)
* @param {ol.Map} map - OpenLayers 的 Map 对象
* @param {Array<Array<{longitude: number, latitude: number}>>} multiHistoryWayPoints - 轨迹数组
*/
function createHistoryWays(map, multiHistoryWayPoints) {
const historyWayFeatures = [];
for (const historyWay of multiHistoryWayPoints) {
if (!Array.isArray(historyWay) || historyWay.length < 2) continue;
for (let i = 0; i < historyWay.length - 1; i++) {
const curPointCoor = historyWay[i];
const nextPointCoor = historyWay[i + 1];
// Use the global 'ol' object to access classes
const lineGeometry = new ol.geom.LineString([
ol.proj.fromLonLat([
curPointCoor.longitude,
curPointCoor.latitude,
]),
ol.proj.fromLonLat([
nextPointCoor.longitude,
nextPointCoor.latitude,
]),
]);
const lineFeature = new ol.Feature({
geometry: lineGeometry,
});
historyWayFeatures.push(lineFeature);
}
}
if (historyWayFeatures.length === 0) {
console.warn("没有有效的历史轨迹数据来创建图层。");
return;
}
const vectorSource = new ol.source.Vector({
features: historyWayFeatures,
});
const historyLayer = new ol.layer.Vector({
source: vectorSource,
});
const arrowSvg = `
<svg width="20" height="20" xmlns="http://www.w3.org/2000/svg">
<path d="M2 10 L18 10 M12 4 L18 10 L12 16"
fill="none" stroke="rgba(0, 123, 255, 0.9)" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round" />
</svg>`;
const arrowIconSrc = "data:image/svg+xml;base64," + btoa(arrowSvg);
const styleFunction = (feature) => {
const geometry = feature.getGeometry();
const coords = geometry.getCoordinates();
const start = coords[0];
const end = coords[1];
const dx = end[0] - start[0];
const dy = end[1] - start[1];
const rotation = Math.atan2(dy, dx);
return [
// Lines now start with 'ol.style'
new ol.style.Style({
stroke: new ol.style.Stroke({
color: "rgba(0, 123, 255, 0.8)",
width: 3,
}),
}),
new ol.style.Style({
geometry: new ol.geom.Point(end),
image: new ol.style.Icon({
src: arrowIconSrc,
anchor: [0.75, 0.5],
rotateWithView: true,
rotation: -rotation,
}),
}),
];
};
historyLayer.setStyle(styleFunction);
map.addLayer(historyLayer);
map.getView().fit(vectorSource.getExtent(), {
padding: [80, 80, 80, 80],
duration: 1000,
});
console.log("成功创建并添加了历史轨迹图层。");
}
// --- Demo 初始化 ---
// All classes are now accessed via the global 'ol' object
const map = new ol.Map({
target: "map",
layers: [
new ol.layer.Tile({
source: new ol.source.OSM(),
}),
],
view: new ol.View({
center: ol.proj.fromLonLat([116.397428, 39.90923]),
zoom: 10,
}),
});
const sampleTracks = [
[
{ longitude: 116.3, latitude: 39.9 },
{ longitude: 116.35, latitude: 39.92 },
{ longitude: 116.4, latitude: 39.9 },
{ longitude: 116.45, latitude: 39.93 },
{ longitude: 116.5, latitude: 39.91 },
],
[
{ longitude: 116.32, latitude: 39.98 },
{ longitude: 116.38, latitude: 39.99 },
{ longitude: 116.42, latitude: 39.96 },
],
];
createHistoryWays(map, sampleTracks);
</script>
</body>
</html>