首页 > 其他分享 >46.在 Vue3 中使用 OpenLayers 双击鼠标显示品牌代言人名片

46.在 Vue3 中使用 OpenLayers 双击鼠标显示品牌代言人名片

时间:2024-12-27 11:58:45浏览次数:7  
标签:ol const OpenLayers 46 new state 双击鼠标 Vue3 import

在现代 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 的 StyleIcon 类设置代言人位置的样式。

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

相关文章

  • vue3 setup函数内的防抖/节流节流不生效解决方式
    //debounce<template><!--生效--><el-inputv-model="value"@keyup="handelKeyUp"></el-input><!--不生效--><el-inputv-model="value"@keyup="debounce(handelKeyUp2,300)">......
  • vue3入门教程:ref能否完全替代reactive?
    1.使用场景与数据类型ref:主要用于基本数据类型(如String、Number、Boolean等)。也可以用于对象/数组,但需要通过.value访问。适合单个响应式数据的管理。reactive:主要用于对象类型(如Object、Array)。直接访问属性,不需要.value。适合多个响应式数据的管理。2.访问方式......
  • 大学生期末项目spingboot+vue3实现快递业务项目【附源码】
    目录一.登录界面 二.用户端 2.1用户端寄快递界面2.2寄快递功能2.3取快递功能 ​编辑 2.4查快递功能2.5快递投诉与拦截2.6查询登录者的信息 三.快递员端  3.1查询可视化界面3.2接单与抢单  3.3配送订单3.4快递员查询个人信息三.网点管理员......
  • P4694 [PA2013] Raper
    P4694[PA2013]Raper题目描述你需要生产\(k\)张光盘。每张光盘都要经过两道工序:先在A工厂进行挤压,再送到B工厂涂上反光层。你知道每天A、B工厂分别加工一张光盘的花费。你现在有\(n\)天时间,每天可以先送一张光盘到A工厂(或者不送),然后再送一张已经在A工厂加工过的......
  • vue3 vite使用postcss-px-to-viewport 实现页面自适应
    三、如何在Vue3中使用postcss-px-to-viewport?首先,我们需要安装相关的插件:npminstallpostcss-px-to-viewport-D在vite.config.js文件中进行配置importvuefrom'@vitejs/plugin-vue'//vite.config.tsimport{defineConfig}from'vite'importAutoImportfrom'......
  • COMP2046 POSIX API
    COMP2046CourseworkAutumn2024Weight:20%modulemarksDeadline:27thDecember2024,5pmBeijingtimeSubmission:CreateasinglescyXXX.zip(Studentaccount)filecontainingyoursourcecodefilesandfilesprovidedalongwiththiscoursework.Wewillne......
  • Vue3 展开收起组件
    组件定义:<!--展开收起组件--><scriptsetuplang="ts">import{getUuid}from'@/utils';interfaceProps{/**赋予input的id*/id?:string|number;/**字符串*/content?:string;}constprops=withDefaults(defineProps&l......
  • 详细讲一下Vue2.x,Vue3.x,React的Vdom和Diff算法
    1.Vue的vdom和Diff1.1.Vue的实现://Vue2.x的VNode结构{tag:'div',//标签名data:{//节点数据class:'container',attrs:{id:'app'},on:{click:handler}},childr......
  • vue3 - vite 对于是否生成 xxx.js.map文件的开关设置-总结
    有3个办法可以设置不生成map文件1.package.json文件里的打包语句"build:docker":"vue-tsc--noEmit&&vitebuild--modedev",中,添加--noEmit参数,则不会生成map包2.vite.config.ts文件里的build.sourcemap属性,设置为false,则不会生成map包3.tsconfig.json文件里的c......
  • 【Java基础面试题046】Java中的注解原理是什么?
    注解其实就是一个标记,是一种提供元数据的机制,用于给代码添加说明信息。可以标记在类上、方法上、属性上等,标记自身也可以设置一些值。注解本身不影响程序的逻辑执行,但可以通过工具或框架来利用这些信息进行特定的处理,如代码生成、编译时检查、运行时处理等。扩展知识自定义......