在现代 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,并实现了一个简单的交互功能:双击地图上的城市点来显示品牌代言人名片。希望这篇文章对你有帮助,能够在你的项目中为地图和地理信息展示提供灵感!
如果你有任何问题,欢迎在评论区留言。
标签:ol,const,OpenLayers,46,new,state,双击鼠标,Vue3,import From: https://blog.csdn.net/Miller777_/article/details/144764465