当前位置: 首页 > article >正文

48.在 Vue 3 中使用 OpenLayers 实现鼠标悬停显示城市名片

在现代前端开发中,Vue 3OpenLayers 是两个强大的工具。Vue 3 提供了简洁高效的前端框架,而 OpenLayers 则在地图应用领域表现优异。本篇文章将详细介绍如何结合 Vue 3 和 OpenLayers,实现一个简单的鼠标悬停地图上的点位,显示城市名片的功能。


实现效果
  1. 地图加载成功后,显示中国的部分城市点位,如北京、大连和天津。
  2. 当鼠标移动到某个城市点位时,会弹出一个包含该城市名称、图片和简介的悬浮窗口。
  3. 鼠标移出点位时,悬浮窗口会自动关闭。


实现步骤
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 实现鼠标悬停功能,增加了地图的交互性。如果你有更多的扩展需求,比如点击事件、动态加载点位或自定义图层样式,可以基于这个示例继续开发。

希望这篇文章对你有所帮助!如果有疑问或建议,欢迎评论交流。😊


http://www.kler.cn/a/457031.html

相关文章:

  • 阴阳师の新手如何速刷5个SP/SSR?!(急速育成)
  • HTML5 开关(Toggle Switch)详细讲解
  • 【竞技宝】LOL:IG新赛季分组被质疑
  • 揭秘文件上传漏洞之操作原理(Thoughts on File Upload Vulnerabilities)
  • RocketMQ(二)RocketMQ实战
  • 操作系统论文导读(八):Schedulability analysis of sporadic tasks with multiple criticality specifications——具有多个
  • 《类和对象:基础原理全解析(中篇)》
  • Android-插件化详解
  • 自动化测试-Pytest测试
  • 力扣-数据结构-2【算法学习day.73】
  • 数据结构(哈希表(中)纯概念版)
  • 【ACCSS】2024年亚信安全云认证专家题库
  • Cadence学习笔记 12 PCB初始化设置
  • 【生信圆桌x教程系列】如何安装 seurat V4版本R包
  • vue项目搭建规范
  • Cadence学习笔记 16 HDMI接口布局
  • 续写上一篇《C++学习指南》
  • 深度学习利用Kaggle和Colab免费GPU资源训练
  • Word论文交叉引用一键上标
  • java 构建树型结构
  • 数字设计实验:RISC-V指令单周期CPU
  • 简单的skywalking探针加载原理学习
  • apifox
  • Vulnhub靶场morpheus获得shell攻略
  • spring url匹配
  • WordPress Elementor Page Builder 插件存在任意文件读取漏洞(CVE-2024-9935)