openlayers利用已知的三个经纬度的坐标点 , 绘制一个贝塞尔曲线
以下是使用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²P2const 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底图和红色贝塞尔曲线)