155.Vue3中使用OpenLayers+Turf获取两点之间的距离

✨ 效果图


✨ 写在前面

在地图开发中,我们经常会用到“两点之间的距离计算”功能。虽然 OpenLayers 本身也提供了一些距离量测的方法,但借助 Turf.js 可以更加灵活且兼容 GeoJSON 结构。

本篇文章介绍如何在 Vue3 项目中使用 OpenLayers 和 Turf 完成以下功能:

  • 绘制两个固定点及连线;

  • 计算两点之间的距离(单位:公里);

  • 清除图层重置内容。


🔧 技术栈

  • Vue 3(Composition API)

  • OpenLayers 10+

  • Turf.js

  • Element Plus(按钮展示)


📦 安装依赖

npm install ol @turf/turf
# 若未安装 Element Plus:
npm install element-plus

📄 完整源码

🧩 地图组件.vue

<!--
 * @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>
    <h4>
      <el-button type="primary" size="small" @click="showTwo">
        绘制两点并获取距离
        <span v-if="juli" class="text-green-400">{{ juli.toFixed(3) }} km</span>
      </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 { fromLonLat } from 'ol/proj'
import * as turf from '@turf/turf'
import GeoJSON from 'ol/format/GeoJSON'
import { Fill, Stroke, Style, Circle } from 'ol/style'

// 状态定义
const map = ref(null)
const turfSource = new VectorSource({ wrapX: false })
const juli = ref(0)

// 显示 GeoJSON 数据(可以是 Point、LineString)
function show(geojsonData) {
  const features = new GeoJSON().readFeatures(geojsonData, {
    dataProjection: 'EPSG:4326',
    featureProjection: 'EPSG:3857'
  })
  turfSource.addFeatures(features)
}

// 清除矢量图层数据和距离
function clearSource() {
  turfSource.clear()
  juli.value = 0
}

// 绘制两点及连线,计算距离
function showTwo() {
  const from = turf.point([-75.343, 39.984])
  const to = turf.point([-75.534, 39.123])
  const options = { units: 'kilometers' }

  clearSource()
  show(from)
  show(to)
  juli.value = turf.distance(from, to, options)

  const linestring1 = turf.lineString([[-75.343, 39.984], [-75.534, 39.123]], { name: 'line 1' })
  show(linestring1)
}

// 初始化地图
function initMap() {
  const gaode_Layer = 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 turfLayer = new VectorLayer({
    source: turfSource,
    style: new Style({
      fill: new Fill({
        color: 'rgba(255,0,0,0.2)'
      }),
      stroke: new Stroke({
        width: 2,
        color: 'blue'
      }),
      image: new Circle({
        radius: 5,
        fill: new Fill({
          color: '#ff0000'
        })
      })
    })
  })

  map.value = new Map({
    target: 'vue-openlayers',
    layers: [gaode_Layer, turfLayer],
    view: new View({
      projection: 'EPSG:3857',
      center: fromLonLat([-75.343, 39.984]),
      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.js 是基于 EPSG:4326 的地理坐标系计算距离,OpenLayers 渲染使用的是 EPSG:3857,需转换。

  • 单位支持:Turf 可选 kilometersmilesdegreesradians 等单位。


📚 延伸思考

  • 如何让用户自行点击两点进行测距?

  • 如何添加测量点提示文本(使用 Overlay)?

  • 如何封装为工具类或 Hook 函数,供多地图项目复用?

如果你对上述功能感兴趣,欢迎留言或者点赞收藏,我们后续会推出拓展版本!


💬 结语

地图开发中很多场景都会涉及距离、面积、角度等几何计算,借助 Turf 可以极大地提升开发效率。

如果你觉得这篇文章有用,欢迎点赞、评论、收藏三连,鼓励更多开发者坚持原创!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吉檀迦俐

你的鼓励奖是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值