以下是使用OpenLayers根据三个经纬度点绘制贝塞尔曲线的完整实现方案。贝塞尔曲线通过控制点生成平滑曲线,特别适合绘制地图上的弧线、路径等。
实现思路
- 贝塞尔曲线原理:使用三个点(起点、控制点、终点)生成二阶贝塞尔曲线。
- 坐标转换:将WGS 84经纬度点转换为Web Mercator投影(EPSG:3857)以在地图上正确显示。
- 曲线计算:通过贝塞尔公式计算曲线上的多个点,形成近似曲线。
- 地图渲染:使用OpenLayers的
LineString
几何对象绘制曲线。
代码实现
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>OpenLayers贝塞尔曲线绘制</title>
<script src="https://cdn.jsdelivr.net/npm/ol@7.3.0/dist/ol.js"></script>
<link href="https://cdn.jsdelivr.net/npm/ol@7.3.0/ol.css" rel="stylesheet">
<style>
.map {
width: 100%;
height: 400px;
}
</style>
</head>
<body>
<div id="map" class="map"></div>
<script>
// 1. 定义三个经纬度点(起点、控制点、终点)
const startPoint = [116.3, 39.9]; // 北京(起点)
const controlPoint = [110.0, 30.5]; // 控制点(黄海海域)
const endPoint = [121.4, 31.2]; // 上海(终点)
// 2. 经纬度转Web Mercator投影
const transformPoints = (points) => {
return points.map(point =>
ol.proj.transform(point, 'EPSG:4326', 'EPSG:3857')
);
};
// 3. 计算二阶贝塞尔曲线上的点
function calculateBezierPoints(start, control, end, segments = 50) {
const points = [];
for (let t = 0; t <= 1; t += 1 / segments) {
// 二阶贝塞尔公式: B(t) = (1-t)²P0 + 2(1-t)tP1 + t²P2
const x = Math.pow(1 - t, 2) * start[0] +
2 * (1 - t) * t * control[0] +
Math.pow(t, 2) * end[0];
const y = Math.pow(1 - t, 2) * start[1] +
2 * (1 - t) * t * control[1] +
Math.pow(t, 2) * end[1];
points.push([x, y]);
}
return points;
}
// 4. 转换坐标并计算贝塞尔曲线
const [startMerc, controlMerc, endMerc] = transformPoints([
startPoint, controlPoint, endPoint
]);
const bezierPoints = calculateBezierPoints(
startMerc, controlMerc, endMerc, 100
);
// 5. 创建地图
const map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.OSM() // 使用OpenStreetMap作为底图
})
],
view: new ol.View({
center: ol.proj.transform([118, 35], 'EPSG:4326', 'EPSG:3857'),
zoom: 5
})
});
// 6. 创建贝塞尔曲线要素
const bezierCurve = new ol.geom.LineString(bezierPoints);
const feature = new ol.Feature({
geometry: bezierCurve,
name: '贝塞尔曲线'
});
// 7. 设置曲线样式
feature.setStyle(new ol.style.Style({
stroke: new ol.style.Stroke({
color: 'rgba(255, 0, 0, 0.8)', // 红色半透明
width: 3,
lineDash: [10, 5] // 虚线样式
})
}));
// 8. 添加曲线到地图
const vectorSource = new ol.source.Vector({
features: [feature]
});
const vectorLayer = new ol.layer.Vector({
source: vectorSource
});
map.addLayer(vectorLayer);
// 9. 添加起点、控制点和终点标记
const addMarker = (coord, label) => {
const marker = new ol.Feature({
geometry: new ol.geom.Point(coord),
name: label
});
marker.setStyle(new ol.style.Style({
image: new ol.style.Circle({
radius: 6,
fill: new ol.style.Fill({ color: 'blue' }),
stroke: new ol.style.Stroke({ color: 'white', width: 2 })
}),
text: new ol.style.Text({
text: label,
font: '14px Arial',
fill: new ol.style.Fill({ color: 'black' }),
stroke: new ol.style.Stroke({ color: 'white', width: 2 }),
offsetY: -10
})
}));
vectorSource.addFeature(marker);
};
addMarker(startMerc, '起点');
addMarker(controlMerc, '控制点');
addMarker(endMerc, '终点');
</script>
</body>
</html>
核心代码解析
-
贝塞尔曲线计算:
- 使用二阶贝塞尔公式:( B(t) = (1-t)^2P_0 + 2(1-t)tP_1 + t^2P_2 )
- 通过参数
t
从0到1的变化,计算曲线上的多个点,segments
参数控制精度
-
坐标转换:
- 使用
ol.proj.transform()
将WGS 84经纬度转换为Web Mercator坐标 - 确保所有点在同一投影系统下计算
- 使用
-
地图渲染:
- 使用
LineString
几何对象表示曲线 - 通过
Style
设置曲线样式(颜色、宽度、虚线等) - 添加标记点显示起点、控制点和终点
- 使用
效果展示
(注:实际运行时会显示OpenStreetMap底图和红色贝塞尔曲线)