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

Google Maps 多 Marker 场景下 InfoWindow

废话不多说,核心useMap代码如下

import { ElMessage } from 'element-plus' import { useI18n } from 'vue-i18n' const DEFAULT_LAT = 13.752082783751177 const DEFAULT_LNG = 100.49313364056417 export function useMap() { const { t } = useI18n() let map = null // 主坐标点(始终存在) let mainMarker = null // 周边坐标点集合 let aroundMarkers = [] /** * 初始化地图 * @param {HTMLElement} root 地图容器 * @param {Object} point 主坐标点 * @param {Boolean} defaultFlag 是否使用默认坐标 */ function initMap(root, point = {}, defaultFlag = false) { let lat, lng if (defaultFlag) { lat = DEFAULT_LAT lng = DEFAULT_LNG } else { lat = Number(point.latitude) || DEFAULT_LAT lng = Number(point.longitude) || DEFAULT_LNG } map = new google.maps.Map(root, { zoom: 12, center: { lat, lng }, mapTypeControl: false, scaleControl: false, streetViewControl: false, fullscreenControl: false }) // 创建主坐标点 Marker mainMarker = new google.maps.Marker({ map, position: { lat, lng } }) } /** * 渲染周边坐标点(不影响主点) * Marker 与 InfoWindow 在此阶段一并创建 * @param {Array} list 周边点数据 */ function addAroundMarkers(list = []) { if (!map || !Array.isArray(list)) return // 清理旧的周边点 aroundMarkers.forEach(item => { item.marker.setMap(null) }) aroundMarkers = [] list.forEach(item => { const lat = Number(item.latitude) const lng = Number(item.longitude) const title = item.title || '' if (Number.isNaN(lat) || Number.isNaN(lng)) return const marker = new google.maps.Marker({ map, position: { lat, lng }, title }) const infoWindow = new google.maps.InfoWindow({ content: title }) // Marker 点击时显示 InfoWindow marker.addListener('click', () => { infoWindow.open(map, marker) }) aroundMarkers.push({ latitude: lat, longitude: lng, marker, infoWindow }) }) } /** * 点击周边列表项时: * 以主点为参考,展示主点与当前周边点 * 并打开对应的 InfoWindow * @param {Object} point 周边点 */ function focusAroundPoint({ latitude, longitude }) { if (!map || !mainMarker) return const lat = Number(latitude) const lng = Number(longitude) if (Number.isNaN(lat) || Number.isNaN(lng)) { ElMessage.warning(t('位置信息异常')) return } const mainPos = mainMarker.getPosition() const aroundPos = new google.maps.LatLng(lat, lng) const bounds = new google.maps.LatLngBounds() bounds.extend(mainPos) bounds.extend(aroundPos) map.fitBounds(bounds, { top: 60, right: 60, bottom: 60, left: 60 }) // 关闭所有 InfoWindow aroundMarkers.forEach(item => { item.infoWindow.close() }) // 打开目标点的 InfoWindow const target = aroundMarkers.find( item => item.latitude === lat && item.longitude === lng ) if (target) { target.infoWindow.open(map, target.marker) } } /** * 打开 Google Maps(新窗口) * @param {Object} point 坐标点 */ function openMap(point) { if (!point?.latitude || !point?.longitude) { ElMessage.warning(t('位置信息缺失')) return } const lat = Number(point.latitude) const lng = Number(point.longitude) if (Number.isNaN(lat) || Number.isNaN(lng)) { ElMessage.warning(t('位置信息异常')) return } const title = encodeURIComponent(point.title || '') const url = `https://www.google.com/maps/search/?api=1&query=${lat},${lng}(${title})` window.open(url, '_blank') } return { initMap, addAroundMarkers, focusAroundPoint, openMap } }

html

<div class="map-section"> <!-- 地图容器 --> <div class="map-container" ref="mapRef"></div> <!-- 主标题(可点击打开 Google Maps) --> <div class="address-name" @click="openMap(mainPoint)"> {{ mainPoint.title }} </div> <!-- 周边列表 --> <div class="around-list" v-if="aroundList.length"> <div class="around-item" v-for="(item, index) in aroundList" :key="index" @click="focusAroundPoint(item)" > <div class="label">{{ item.title }}</div> </div> </div> <!-- 距离提示 --> <div class="distance-tips"> {{ $t('显示距离') }} </div> </div>

调用示例

<script setup> import { ref, onMounted } from 'vue' import { useMap } from '@/composables/useMap' // 地图容器 const mapRef = ref(null) // 主点(示例数据) const mainPoint = { latitude: 13.75208, longitude: 100.49313, title: 'Main Location' } // 周边点列表(示例数据) const aroundList = [ { latitude: 13.756, longitude: 100.501, title: 'Nearby Point A' }, { latitude: 13.748, longitude: 100.485, title: 'Nearby Point B' } ] // 使用 useMap const { initMap, addAroundMarkers, focusAroundPoint, openMap } = useMap() onMounted(() => { // 初始化地图 initMap(mapRef.value, mainPoint) // 渲染周边 Marker(Marker + InfoWindow 一次性创建) addAroundMarkers(aroundList) }) </script>

结果展示如下图:

http://www.jsqmd.com/news/319061/

相关文章:

  • 手动搭MySQL MGR集群太费时间?一键自动化工具安排上
  • 数据库运维核心:MySQL主从复制与读写分离的部署与维护
  • 当我们系统出现msvcr100.dll文件丢失问题 免费下载方法分享
  • 搬了
  • 当系统出现找不到msvcr120.dll文件问题 免费下载方法分享
  • 社会网络仿真软件:NetLogo_(17).社会网络仿真的伦理与隐私问题
  • 社会网络仿真软件:NodeXL_(3).NodeXL安装与基本设置
  • Java计算机毕设之基于微信小程序的学生成绩管理系统基于小程序的高校班级管理系统设计与实现(完整前后端代码+说明文档+LW,调试定制等)
  • 社会网络仿真软件:NetLogo_(18).社会网络仿真结果的解释与报告
  • DDD领域驱动设计之实战指南:从理论到落地的完整实践
  • 【毕业设计】基于springboo的社团管理系统((源码+文档+远程调试,全bao定制等)
  • 《建议收藏》耗时一周,把 FFmpeg 音视频编解码彻底讲透了!从原理到实战,这一篇就够了!
  • 【毕业设计】基于小程序的企业考勤系统设计与实现(源码+文档+远程调试,全bao定制等)
  • 智能体之拆解 Clawdbot:从架构设计到提示词哲学的全链路硬核解析
  • 架构师必读:如何设计一个支撑千万级流量的中间件系统?从通信模型到无锁编程实战
  • 【计算机毕业设计案例】基于小程序的企业员工考勤打卡系统设计与实现基于小程序的企业考勤系统设计与实现(程序+文档+讲解+定制)
  • 企业架构问题篇之一文讲透企业架构、数字化转型与数智化的“三角关系”(1)
  • 论文降AIGC实用工具合集:亲测5款降AI率工具,有效降低AI率全教程
  • AI生成图片:新手必看的核心创作技巧与避坑指南
  • 香港户外须知
  • 降低AI率实用工具指南:亲测有效的免费降AI率工具,与论文降AI技巧【建议收藏】
  • 情人节贺卡:选款与写词的心意传递实用指南
  • 题解:P8258 [CTS2022] 独立集问题
  • 麦角甾醇PEG生物素;Ergosterol-PEG-Biotin的核心价值
  • [豪の算法奇妙冒险] 代码随想录算法训练营第三十六天 | 1049-最后一块石头的重量Ⅱ、494-目标和、474-一和零
  • 《以大制胜》精读笔记:与《影响力》《乌合之众》的非理性说服闭环
  • P1719 最大加权矩形(Kadane算法)
  • 【计算机毕业设计案例】基于Java+springboot+vue的社团活动成员管理系统((程序+文档+讲解+定制)
  • 【AI智能体】03-AI Agent架构与组件:解析AI Agent的组成部分及其工作流程
  • MyBatis的分页插件