🖼️ 效果演示
📚 实现背景
在地图可视化项目中,我们经常需要对轨迹或路径进行“平滑处理”,使其更自然、柔和。传统折线虽然精准,但视觉上较为生硬;而贝塞尔曲线可对线段进行插值优化,生成更符合用户感官的平滑路径。
本文基于:
-
Vue 3 + Composition API
-
OpenLayers 地图框架
-
Turf.js 空间算法库(用于处理几何图形)
实现了从 多线段绘制 到 贝塞尔曲线平滑处理 的完整流程。
🧩 技术栈与依赖
npm install ol @turf/turf
📦 主要功能
-
✏️ 一键绘制多段折线(LineString);
-
🧮 使用
turf.bezierSpline
将折线平滑为贝塞尔曲线; -
🗺️ 使用 OpenLayers 显示原始线与平滑后的线;
-
🧹 支持图层清除操作。
🧱 完整代码
<!--
* @Author: 彭麒
* @Date: 2025/7/16
* @Email: 1062470959@qq.com
* @Description: 此源码版权归吉檀迦俐所有,可供学习和借鉴或商用。
-->
<template>
<div class="container">
<div class="w-full flex justify-center flex-wrap">
<div class="font-bold text-[24px]">
Vue3 + OpenLayers + Turf 绘制线段并生成贝塞尔曲线
</div>
</div>
<h3></h3>
<h4>
<el-button type="primary" size="small" @click="showLine">绘制多线段</el-button>
<el-button type="warning" size="small" @click="showBezier">绘制贝塞尔曲线</el-button>
<el-button type="danger" size="small" @click="clearSource">清除图层</el-button>
</h4>
<div id="vue-openlayers"></div>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import 'ol/ol.css'
import Map from 'ol/Map'
import View from 'ol/View'
import TileLayer from 'ol/layer/Tile'
import VectorSource from 'ol/source/Vector'
import VectorLayer from 'ol/layer/Vector'
import XYZ from 'ol/source/XYZ'
import GeoJSON from 'ol/format/GeoJSON'
import { Fill, Stroke, Style, Circle } from 'ol/style'
import { fromLonLat } from 'ol/proj'
import * as turf from '@turf/turf'
// 地图和图层相关
const map = ref(null)
const turfSource = new VectorSource({ wrapX: false })
let line = null // 储存原始多线段 LineString
// 渲染 GeoJSON 数据到矢量图层
function show(geojsonData) {
const features = new GeoJSON().readFeatures(geojsonData, {
dataProjection: 'EPSG:4326',
featureProjection: 'EPSG:3857'
})
turfSource.addFeatures(features)
}
// 清除图层
function clearSource() {
turfSource.clear()
line = null
}
// 绘制原始多线段
function showLine() {
line = turf.lineString([
[-76.091308, 18.427501],
[-76.695556, 18.729501],
[-76.552734, 19.40443],
[-74.61914, 19.134789],
[-73.652343, 20.07657],
[-73.157958, 20.210656]
])
show(line)
}
// 绘制贝塞尔曲线
function showBezier() {
if (line) {
const curved = turf.bezierSpline(line)
show(curved)
}
}
// 初始化地图
function initMap() {
const baseLayer = new TileLayer({
source: new XYZ({
url: 'http://wprd0{1-4}.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=en&size=1&scl=1&style=7'
})
})
const vectorLayer = new VectorLayer({
source: turfSource,
style: new Style({
fill: new Fill({
color: 'rgba(255,0,0,0.2)'
}),
stroke: new Stroke({
color: '#f0f',
width: 2
}),
image: new Circle({
radius: 5,
fill: new Fill({
color: '#ff0000'
})
})
})
})
map.value = new Map({
target: 'vue-openlayers',
layers: [baseLayer, vectorLayer],
view: new View({
projection: 'EPSG:3857',
center: fromLonLat([-74.61914, 19.134789]),
zoom: 8
})
})
}
onMounted(() => {
initMap()
})
</script>
<style scoped>
.container {
width: 840px;
height: 570px;
margin: 50px auto;
border: 1px solid #42B983;
}
#vue-openlayers {
width: 800px;
height: 400px;
margin: 0 auto;
border: 1px solid #42B983;
position: relative;
}
</style>
📈 Turf 中的 bezierSpline 原理简述
turf.bezierSpline(line, options)
方法将折线插值成一条平滑曲线,本质是对线段进行贝塞尔插值,支持设置分辨率、曲线张力等参数。
其优点包括:
-
平滑自然;
-
适用于轨迹回放、导航路径可视化;
-
插值后的线段依旧符合 GeoJSON 标准,便于进一步处理。
🧰 衍生拓展方向
你可以在此基础上做更多扩展:
方向 | 建议 |
---|---|
轨迹动画 | 将贝塞尔线段动画渲染轨迹播放 |
用户绘制 | 让用户在地图上点击生成 LineString |
曲率控制 | 自定义 turf.bezierSpline(line, { sharpness: 0.5 }) 控制曲率 |
🔚 总结
本篇内容演示了如何用 Vue3 + OpenLayers + Turf 绘制线段并生成贝塞尔曲线,适用于路径平滑、地图轨迹、可视化展示等场景。通过简单按钮交互,你可以方便地控制原始线段与平滑曲线的展示。
如需源码或完整工程,可私信我或评论获取。欢迎点赞、收藏与转发!🌟
🔗 参考链接
-
Turf.js 官方文档:Advanced geospatial toolkit for Typescript | Turf.js
-
OpenLayers 中文文档:OpenLayers - Welcome
-
EPSG 坐标系说明:EPSG.io: Coordinate Systems Worldwide