100.Vue3 + OpenLayers:使用 marker-feature 添加 Marker
在前端 GIS(地理信息系统)开发中,OpenLayers
是一个强大的开源地图库,可以帮助开发者快速构建 Web 地图应用。本文将详细介绍如何在 Vue3
项目中,使用 OpenLayers
并结合 marker-feature
插件来添加 Marker
。
1. 项目初始化
如果你的 Vue3
项目还没有创建,可以使用 Vite
进行快速搭建:
npm create vite@latest vue-openlayers-demo --template
vue cd vue-openlayers-demo npm install
然后安装 OpenLayers
和 marker-feature
插件:
npm install ol ol-marker-feature ol-popup
2. 创建 MarkerFeature.vue
组件
在 components
目录下新建 MarkerFeature.vue
,然后使用 setup
语法来封装 OpenLayers
地图,并添加 marker-feature
。
<!--
* @Author: 彭麒
* @Date: 2025/3/12
* @Email: 1062470959@qq.com
* @Description: 此源码版权归吉檀迦俐所有,可供学习和借鉴或商用。
-->
<template>
<div class="container">
<div class="w-full flex justify-center">
<div class="font-bold text-[24px]">在Vue3 + OpenLayers使用 marker-feature 来添加 marker</div>
</div>
<div id="vue-openlayers"></div>
</div>
</template>
<script setup>
import { onMounted } from "vue";
import "ol/ol.css";
import { Map, View } from "ol";
import Tile from "ol/layer/Tile";
import OSM from "ol/source/OSM";
import Marker from "ol-marker-feature";
import Popup from "ol-popup";
let map; // map 作为普通变量,不使用 ref
const initMap = () => {
if (map) return; // 避免重复初始化
const OSMlayer = new Tile({ source: new OSM() });
map = new Map({
target: "vue-openlayers",
layers: [OSMlayer],
view: new View({
center: [113.448, 23.986],
zoom: 7,
projection: "EPSG:4326",
}),
});
const marker = new Marker([113.448, 23.986]);
marker.set(
"info",
`<div style="background:#fff; padding:20px;">
<h3>我的 Marker 标题</h3>
<h4>vue-openlayers 的信息内容</h4>
</div>`
);
marker.setMap(map);
const popup = new Popup({ offset: [0, -32] });
map.addOverlay(popup);
marker.on("click", () => {
popup.show(marker.getLocation(), marker.get("info"));
});
};
onMounted(initMap);
</script>
<style scoped>
.container {
width: 840px;
height: 590px;
margin: 50px auto;
border: 1px solid #42B983;
}
#vue-openlayers {
width: 800px;
height: 470px;
margin: 0 auto;
border: 1px solid #42B983;
position: relative;
}
</style>
3. 组件解析
3.1 OpenLayers 地图初始化
我们创建了一个 OSM
(OpenStreetMap)底图,并在 div#vue-openlayers
内渲染 Map
实例:
map = new Map({
target: "vue-openlayers",
layers: [OSMlayer],
view: new View({
center: [113.448, 23.986],
zoom: 7,
projection: "EPSG:4326",
}),
});
注意:OpenLayers 默认使用
EPSG:3857
投影,因此如果你的坐标是EPSG:4326
,请确保所有数据一致。
3.2 添加 Marker
ol-marker-feature
允许我们直接创建 Marker
并绑定到 Map
:
const marker = new Marker([113.448, 23.986]);
marker.set("info", "<div>Vue3 OpenLayers Marker</div>");
marker.setMap(map);
这样,我们的 Marker
就会出现在指定经纬度的位置。
3.3 绑定 Popup 信息框
为了让 Marker
可以在点击时弹出 Popup
,我们使用 ol-popup
插件:
const popup = new Popup({ offset: [0, -32] });
map.addOverlay(popup);
marker.on("click", () => {
popup.show(marker.getLocation(), marker.get("info"));
});
这样,点击 Marker
时就能弹出对应的 HTML
内容。
4. 在 App.vue
引用组件
在 App.vue
中引入 MarkerFeature.vue
并使用:
<template>
<MarkerFeature />
</template>
<script setup>
import MarkerFeature from "./components/MarkerFeature.vue";
</script>
5. 运行项目
npm run dev
打开浏览器,访问 http://localhost:5173
(默认 Vite
端口),你应该可以看到地图,以及点击 Marker
后弹出的 Popup
信息框。
6. 常见问题
❓ Uncaught TypeError: Class constructor _Feature cannot be invoked without 'new'
如果 ol-marker-feature
发生此错误,可以使用 Feature + Point
方式替代:
import Feature from "ol/Feature";
import Point from "ol/geom/Point";
import VectorLayer from "ol/layer/Vector";
import VectorSource from "ol/source/Vector";
import { Icon, Style } from "ol/style";
import { fromLonLat } from "ol/proj"; // 使用 Feature + Point 方式创建 Marker
const markerFeature = new Feature({
geometry: new Point(fromLonLat([113.448, 23.986])),
});
markerFeature.setStyle( new Style({
image: new Icon({ anchor: [0.5, 1],
src: "https://openlayers.org/en/latest/examples/data/icon.png", // 自定义图标
}),
}) ); // 创建矢量图层
const vectorLayer = new VectorLayer({
source: new VectorSource({ features: [markerFeature], }),
});
map.addLayer(vectorLayer);
推荐:如果
marker-feature
兼容性不好,建议直接用Feature + Point
方式实现。
7. 总结
Vue3 + OpenLayers
提供了强大的 Web 地图能力marker-feature
可以快速添加Marker
,但兼容性可能有问题- 推荐使用
Feature + Point
方式 来实现Marker
- 可以结合
ol-popup
添加信息弹窗交互
8. 参考文档
- OpenLayers 官网
- ol-marker-feature GitHub
- Vue.js 官网
这样,你的 CSDN 文章就完成了!🚀 希望能帮到你,记得给文章加点排版,效果会更好哦! 🎉