在现代 Web 开发中,地图可视化已成为非常常见的需求之一,尤其是在地理位置相关的应用中。OpenLayers 是一款强大的开源 JavaScript 库,能够帮助开发者在网页中实现各种地图功能。结合 Vue 3 的强大功能,我们可以轻松地将 OpenLayers 集成到 Vue 项目中,展示地图上的地理信息。
本文将介绍如何在 Vue 3 中使用 OpenLayers 实现一个双击鼠标显示品牌代言人名片的功能,帮助大家快速上手并实现交互效果。
需求背景
我们要实现的功能如下:
- 在地图上显示多个品牌代言人的位置。
- 每个代言人信息包括:名字、电话、邮箱以及头像。
- 用户可以通过双击代言人所在的位置,展示代言人的详细信息(如名片)。
技术栈
- Vue 3:现代的前端框架,基于 Composition API 提供更简洁的代码结构。
- OpenLayers:开源的地图展示库,支持丰富的地图功能和交互。
- CSS:基本的样式设置,确保界面美观。
效果展示
1. 安装依赖
首先,我们需要安装 OpenLayers。你可以通过 npm 或 yarn 安装 OpenLayers:
npm install ol
2. 创建 Vue 组件
接下来,我们开始编写 Vue 组件来实现我们的需求。
代码实现
<!--* @Author: 彭麒* @Date: 2024/12/27* @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双击鼠标显示品牌代言人名片</div></div><div id="vue-openlayers"></div><div id="popup-box" class="ol-popup"><div id="popup-content"><div class="left"><img :src="state.imgurl"/></div><div class="right"><div class="name">{{ state.name }}</div><div class="dec">{{ state.phone }}</div><div class="dec">{{ state.email }}</div></div></div></div></div>
</template><script setup>
import 'ol/ol.css';
import {reactive, onMounted} from 'vue';
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 * as Interaction from 'ol/interaction';
import person1 from '@/assets/OpenLayers/person1.jpg';
import person2 from '@/assets/OpenLayers/person2.jpg';
const state = reactive({map: null,overlayer: null,vsource: new VectorSource({}),imgurl: null,name: '',email: '',phone: '',citys: [{name: '阿米尔·汗',position: [73, 19],phone: '138****8888',email: 'amh@lante.info',imgurl: person1,},{name: '艾西瓦娅·雷',position: [77, 28],phone: '138****6666',email: 'axwy@lante.info',imgurl: person2,},],
});const pointStyle = (img) => {return [new Style({image: new Icon({src: img,anchor: [0.5, 0.5],scale: 0.05,}),}),];
};const companyPoint = () => {const features = state.citys.map((data) => {const feature = new Feature({geometry: new Point(data.position),persondata: data,});feature.setStyle(pointStyle(data.imgurl));return feature;});state.vsource.addFeatures(features);
};const clickPoint = () => {const box = document.getElementById('popup-box');state.overlayer = new Overlay({element: box,autoPan: {animation: {duration: 250,},},});state.map.addOverlay(state.overlayer);state.map.on('dblclick', (e) => {const feature = state.map.forEachFeatureAtPixel(e.pixel, (feature) => feature);if (feature) {const person = feature.get('persondata');state.name = person.name;state.imgurl = person.imgurl;state.phone = person.phone;state.email = person.email;state.overlayer.setPosition(e.coordinate);} else {state.overlayer.setPosition(undefined);}});
};const initMap = () => {const osmLayer = new Tile({source: new OSM()});const cityLayer = new VectorLayer({source: state.vsource});state.map = new Map({target: 'vue-openlayers',layers: [osmLayer, cityLayer],view: new View({center: [77, 28],zoom: 5,projection: 'EPSG:4326',}),interactions: new Interaction.defaults({doubleClickZoom: false,}),});clickPoint();
};onMounted(() => {initMap();companyPoint();
});</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(210, 105, 30, 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(210, 105, 30, 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;
}#popup-content {width: 270px;height: 120px;border-radius: 10px;
}#popup-content .left {width: 100px;height: 120px;float: right;
}#popup-content .left img {width: 100px;height: 120px;
}#popup-content .right {width: 160px;height: 120px;float: left;text-align: left;padding-left: 10px;
}#popup-content .right .name {line-height: 50px;font-size: 20px;
}#popup-content .right .dec {line-height: 30px;font-size: 14px;
}
</style>
3. 代码说明
1. 状态管理
我们使用 reactive
来管理 Vue 3 组件的状态,包括地图对象、浮层(overlay)和代言人信息。
2. 设置代言人位置样式
通过 OpenLayers 的 Style
和 Icon
类设置代言人位置的样式。
3. 初始化地图和双击事件
在 initMap
中初始化 OpenLayers 地图,并在 dblclick
事件中监听双击操作,显示浮层。
4. 总结
通过这篇文章,我们学习了如何在 Vue 3 项目中集成 OpenLayers,并实现了一个简单的交互功能:双击地图上的城市点来显示品牌代言人名片。希望这篇文章对你有帮助,能够在你的项目中为地图和地理信息展示提供灵感!
如果你有任何问题,欢迎在评论区留言。