在现代前端开发中,Vue 3 和 OpenLayers 是两个强大的工具。Vue 3 提供了简洁高效的前端框架,而 OpenLayers 则在地图应用领域表现优异。本篇文章将详细介绍如何结合 Vue 3 和 OpenLayers,实现一个简单的鼠标悬停地图上的点位,显示城市名片的功能。
实现效果
- 地图加载成功后,显示中国的部分城市点位,如北京、大连和天津。
- 当鼠标移动到某个城市点位时,会弹出一个包含该城市名称、图片和简介的悬浮窗口。
- 鼠标移出点位时,悬浮窗口会自动关闭。
实现步骤
1. 项目初始化
在开始前,请确保你的项目已经配置好 Vue 3 环境,并安装了 OpenLayers:
npm install ol
2. Vue 3 和 OpenLayers 的代码实现
以下是完整代码,包括地图初始化、点位加载以及鼠标悬停事件处理:
<!--* @Author: 彭麒* @Date: 2024/12/28* @Email: 1062470959@qq.com* @Description: 此源码版权归吉檀迦俐所有,可供学习和借鉴或商用。-->
<template><button class="back-button" @click="goBack">返回</button><div class="container"><div class="w-full flex justify-center flex-wrap"><div class="font-bold text-[24px]">在Vue3中使用OpenLayers移动鼠标显示城市名片</div></div><div id="vue-openlayers"></div><div id="popup-box" class="ol-popup"><div id="popup-content"></div></div></div>
</template><script setup>
import {ref, 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 Overlay from 'ol/Overlay';
import VectorLayer from 'ol/layer/Vector';
import VectorSource from 'ol/source/Vector';
import Style from 'ol/style/Style';
import Icon from 'ol/style/Icon';
import Feature from 'ol/Feature';
import {Point} from 'ol/geom';
import dalianImg from '@/assets/OpenLayers/dalian.png';
import beijingImg from '@/assets/OpenLayers/beijing.png';
import tianjinImg from '@/assets/OpenLayers/tianjin.png';
import maker from '@/assets/OpenLayers/maker.png';
import router from "@/router";const goBack = () => {router.push('/OpenLayers');
};const map = ref(null);
const overlayer = ref(null);
const vsource = new VectorSource();
const citys = [{name: '大连',position: [121.63, 38.90],desc: '滨城、浪漫之都,辽宁省辖地级市、副省级市。',imgurl: dalianImg},{name: '北京',position: [116.40, 39.91],desc: '中华人民共和国的首都、中国政治、文化中心。',imgurl: beijingImg},{name: '天津',position: [117.21, 39.09],desc: '简称“津”,中华人民共和国省级行政区、直辖市。',imgurl: tianjinImg},
];const createCityPointFeatures = () => {const features = citys.map((city) => {const feature = new Feature({geometry: new Point(city.position),citydata: city});feature.setStyle(createPointStyle());return feature;});vsource.addFeatures(features);
};const createPointStyle = () => {return new Style({image: new Icon({src: maker,anchor: [0.5, 0.5],scale: 1})});
};const setupHoverInteraction = () => {const box = document.getElementById('popup-box');const content = document.getElementById('popup-content');overlayer.value = new Overlay({element: box,autoPan: {animation: {duration: 250}}});map.value.addOverlay(overlayer.value);map.value.on('pointermove', (e) => {if (e.dragging) return;const feature = map.value.forEachFeatureAtPixel(e.pixel, (feat) => feat);if (feature) {const cityInfo = feature.get('citydata');content.innerHTML = `<h3>${cityInfo.name}</h3><div><img src="${cityInfo.imgurl}"></div> <p>${cityInfo.desc}</p>`;overlayer.value.setPosition(e.coordinate);} else {overlayer.value.setPosition(undefined);}});
};const initializeMap = () => {const osmLayer = new Tile({source: new OSM()});const cityLayer = new VectorLayer({source: vsource});map.value = new Map({target: 'vue-openlayers',layers: [osmLayer, cityLayer],view: new View({center: [116.389, 39.903],zoom: 6,projection: 'EPSG:4326'})});setupHoverInteraction();
};onMounted(() => {initializeMap();createCityPointFeatures();
});</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;
}.ol-popup {position: absolute;background-color: rgba(255, 0, 0, 0.8);padding: 5px;border-radius: 5px;border: 1px solid #cccccc;bottom: 12px;left: -50px;color: #FFFFFF;min-width: 200px;
}.ol-popup:after,
.ol-popup:before {top: 100%;border: solid transparent;content: " ";height: 0;width: 0;position: absolute;pointer-events: none;
}.ol-popup:after {border-top-color: rgba(255, 0, 0, 0.8);border-width: 10px;left: 48px;margin-left: -10px;
}.ol-popup:before {border-top-color: #cccccc;border-width: 11px;left: 48px;margin-left: -11px;
}
</style>
总结
通过本文的学习,你学会了在 Vue 3 中如何结合 OpenLayers 实现鼠标悬停功能,增加了地图的交互性。如果你有更多的扩展需求,比如点击事件、动态加载点位或自定义图层样式,可以基于这个示例继续开发。
希望这篇文章对你有所帮助!如果有疑问或建议,欢迎评论交流。😊