核心内容摘要
揭秘鞠婧祎造梦工厂MV:视觉盛宴,心动之旅
概述在现代前端GIS应用开发中地图标记点Marker的管理是核心功能之一。
本文将详细介绍如何基于Vue
Ant Design Vue
0和高德地图API实现一个高度可配置、支持多类型标记点、具备丰富交互功能的标记点管理系统。
技术栈Vue3使用Composition API进行逻辑封装JavaScript主要开发语言Ant Design Vue
0UI组件库高德地图API地图展示与交互基础事件总线组件间通信机制核心功能设计
标记点类型配置系统首先我们创建一个中央化的配置系统来管理不同类型的标记点// marker-config.js import { markerEnum } from /utils/enum; export const markerConfigs { [markerEnum.SXJ]: { key: markerEnum.SXJ, idKey: id, // 唯一标识字段 textKey: name, // 文本标签字段 isOnLine: (data) true, // 在线状态检测 iconFilter: (data, isHover) { let image null; image isHover ? sxjHoverMarker : sxjMarker; return getMarkerIcon(image); }, zIndex: 35, // 图层层级 }, [markerEnum.ZBJL]: { key: markerEnum.ZBJL, isOnLine: (data) true, iconFilter: (data, isHover false) { let image null; image isHover ? zbjlHoverMarker : zbjlMarker; return getMarkerIcon(image); }, idKey: id, textKey: license, zIndex: 35, }, // 其他标记点类型... }; // 获取配置的辅助函数 export const getMarkerConfig (type) markerConfigs[type];
自定义Hook封装使用Vue3的Composition API封装标记点管理逻辑// useMarker.js export default () { let textLabel null; const markerTypes ref([]); const markers ref([]); const selectMarkerId ref(null); // 创建单个标记点 const createMarker (point) { if (!useMap.AMap) return; const config getMarkerConfig(point.type); if (!config) return message.info(未找到对应标点配置); // 生成唯一标识符 const uuid ${config.key}:${point[config.idKey]}; const position new AMap.LngLat(point.longitude, point.latitude); // 创建高德地图Marker实例 const marker new AMap.Marker({ map: useMap.AMap, position, anchor: bottom-center, zIndex: config.zIndex, extData: { item: { ...point, uuid }, data: config }, }); // 初始图标设置 updateMarkerIcon(marker, config, selectMarkerId.value uuid); // 事件绑定 if (config.isOnLine(point)) { bindMarkerEvents(marker, config); } else { marker.setCursor(default); } return marker; }; return { setMarkers, clearMarkers }; };
交互事件绑定实现丰富的鼠标交互效果const bindMarkerEvents (marker, config) { const point marker.getExtData(); const uuid point.item?.uuid; // 鼠标移入事件 marker.on(mouseover, () { marker.setTop(true); // 置顶显示 if (selectMarkerId.value ! uuid) { updateMarkerIcon(marker, config, true); // 切换为悬停图标 } // 显示文本标签 if (config.textKey textLabel) { const text point.item[config.textKey]; const position marker.getPosition(); textLabel.show(); textLabel.setOffset(new AMap.Pixel(0, -
); textLabel.setPosition(position); textLabel.setText(div classamap-label-style${text}/div); } }); // 鼠标移出事件 marker.on(mouseout, () { marker.setTop(false); if (selectMarkerId.value ! uuid) { updateMarkerIcon(marker, config, false); // 恢复默认图标 } if (config.textKey textLabel) { textLabel.hide(); // 隐藏文本标签 } }); // 点击事件 marker.on(click, () { const prevUUID selectMarkerId.value; selectMarkerId.value uuid; // 更新前一个选中标记点的状态 if (prevUUID prevUUID ! uuid) { const { marker, config } getPrevMarkerConfig(prevUUID); if (marker config) { updateMarkerIcon(marker, config, false); } } // 更新当前标记点状态 updateMarkerIcon(marker, config, true); // 计算信息框偏移量 let offset new AMap.Pixel(0, -
; if (config.key markerEnum.CLOSE) { offset new AMap.Pixel(0, -
; } // 发送事件总线消息 eventBus.emit(marker-click, { type: point.item?.type, extData: { ...point, offset }, }); }); };
批量管理与状态控制提供批量操作接口和状态管理// 设置标记点数据 const setMarkers (points) { // 清除旧标点 clearMarkers(); // 创建文本标签实例 textLabel new AMap.Text({ map: useMap.AMap, anchor: bottom-center, visible: false, zIndex: 30, }); // 批量创建新标记点 markers.value points.map((point) createMarker(point)); markerTypes.value [...new Set(points.map((p) p.type))]; }; // 清除所有标记点 const clearMarkers () { // 通知各类型组件关闭 markerTypes.value.forEach((type) { eventBus.emit(marker-close, type); }); // 从地图移除所有标记点 markers.value.forEach((marker) { marker?.setMap(null); }); // 清理文本标签 textLabel?.setMap(null); textLabel null; markers.value []; markerTypes.value []; }; // 更新标记点图标 const updateMarkerIcon (marker, config, isHover false) { const extData marker.getExtData(); marker.setIcon(config.iconFilter(extData.item, isHover)); };
事件总线集成通过事件总线实现跨组件通信// 监听外部关闭事件 eventBus.on(marker-close, (uuid) { if (!uuid.includes(undefined)) { const { marker, config } getPrevMarkerConfig(uuid); if (marker config) updateMarkerIcon(marker, config, false); } }); // 获取前一个标记点配置 const getPrevMarkerConfig (uuid) { const prevMarker markers.value.find( (m) m.getExtData().item?.uuid uuid ); const point prevMarker?.getExtData(); return { marker: prevMarker, config: getMarkerConfig(point?.item?.type), }; };
在组件中使用template div classmap-container div idmap refmapRef/div /div /template script setup import { onMounted, ref } from vue; import useMarker from /hooks/useMarker; const mapRef ref(null); const { setMarkers, clearMarkers } useMarker(); // 模拟数据 const mockPoints [ { type: SXJ, id: 1, name: 摄像头1, longitude:
1
397428, latitude:
3
90923, }, { type: ZBJL, id: 2, license: 京A12345, longitude:
1
407428, latitude:
3
91923, }, ]; onMounted(() { // 初始化地图后设置标记点 setMarkers(mockPoints); }); // 组件卸载时清理 onUnmounted(() { clearMarkers(); }); /script style scoped .map-container { width: 100%; height: 600px; } .amap-label-style { background: white; padding: 4px 8px; border-radius: 4px; box-shadow: 0 2px 6px rgba(0, 0, 0,
0.
; font-size: 12px; white-space: nowrap; } /style
关键技术点
配置驱动设计通过中央化的配置对象实现了标记点类型的灵活扩展。
新增标记点类型只需在配置文件中添加相应配置即可。
响应式状态管理利用Vue3的ref和watch实现标记点状态的响应式管理确保UI与数据状态同步。
性能优化使用事件委托减少事件绑定数量按需创建和销毁标记点利用高德地图的Marker层级控制
组件通信通过自定义事件总线实现标记点与业务组件的解耦通信。
总结本文介绍了一个基于Vue3和高德地图的完整标记点管理系统。
该系统具有以下特点高度可配置通过配置文件管理所有标记点类型丰富的交互支持悬停、点击、选中等多种交互状态良好的性能优化了标记点的创建、更新和销毁机制可扩展性便于新增标记点类型和交互行为代码复用通过自定义Hook实现逻辑复用这种设计模式不仅适用于地图应用也可借鉴到其他需要管理大量可视化元素的场景中。
通过合理的架构设计可以使复杂的地图标记点管理变得简单而高效。
【我的自研工具推荐】轻松网购返利技术人的省钱助手✅ 自用省钱分享有奖支持主流电商平台 | 返利透明可提现 微信扫码立即体验说明本工具为我个人独立开发若您有技术合作或使用疑问欢迎在博客私信交流。