From 8ee0db5f3aba8ac56d91ec1817c7f4df6828fb7c Mon Sep 17 00:00:00 2001 From: hym Date: Mon, 6 Apr 2026 10:58:58 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=9C=B0=E5=9B=BE=20Popup=20?= =?UTF-8?q?=E5=AF=B9=E8=B1=A1=E5=A4=8D=E7=94=A8=E6=9C=BA=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/vector-layer-utils.js | 70 +++++++++++++++++++++++++++------ 1 file changed, 57 insertions(+), 13 deletions(-) diff --git a/src/utils/vector-layer-utils.js b/src/utils/vector-layer-utils.js index acebfe6..91783b6 100644 --- a/src/utils/vector-layer-utils.js +++ b/src/utils/vector-layer-utils.js @@ -3,9 +3,19 @@ import { regInfo } from '@/api/dataSearch' let sourceLayer = undefined; let clickedLineIds = []; -// 单例 Popup,用于确保地图上只有一个弹框实例 -let sharedPopup = null; +// 存储可复用的每个地图对象的唯一 Popup 实例(key 为 mapId),以避免频繁创建/销毁 Popup 导致的性能问题和潜在内存泄漏 +let sharedPopup = {}; +export function setMapLayoutProperty(mapId, visibility = "none") { + // 设置所有图层的显示/隐藏状态(根据图层类型或名称过滤底图图层,避免误操作) + const layers = Vue.config.maps[mapId].getStyle().layers; + layers.forEach(layer => { + // 跳过底图 + if (layer.id !== '影像地图' && layer.type !== 'raster') { + Vue.config.maps[mapId].setLayoutProperty(layer.id, 'visibility', visibility); + } + }); +} export function loadVectorLayer(layerId, features = ["line", "symbol"], colors = ["#FEFEFE", "#FF0000"], visibility = "visible", mapId = "homeMap", workspace = 'dsds', textField = "name") { // 添加数据源 const sourceId = `vector-${layerId}`; @@ -140,6 +150,10 @@ export async function loadVectorFeature(layerId, feature, color, visibility, map await showSampleLineInfo(`${sourceId}-${feature}`, mapId); if (layerId.includes("sample_station")) await showSampleStationInfo(`${sourceId}-${feature}`, mapId); + else if (sourceId.includes("-SY") || sourceId.includes("-FDZ")) { + await showDiveInfo(`${sourceId}-${feature}`, mapId); + console.log(mapId, `${sourceId}-${feature}`); + } else await showTrackInfo(`${sourceId}-${feature}`, mapId); @@ -415,6 +429,36 @@ export function showTrackInfo(layerId, mapId = "homeMap") { }); } +export function showDiveInfo(layerId, mapId = "homeMap") { + Vue.config.maps[mapId].on("click", layerId, async (e) => { + // 禁止点击事件穿透 - 判断同一个 event 是否已经触发,用于避免图层内标记点注册的点击事件重复触发(点位分布密集时容易出现) + if (e.defaultPrevented) + return; + // 标记该 event 已触发,禁止点击事件穿透 + if (typeof e.preventDefault === "function") + e.preventDefault(); + + const feature = e.features[0]; + let coordinate = e.lngLat; + const description = ` + + + + + + + + + + + + + `; + + showPopupDetails({ mapId, coordinate, description, maxWidth: "300px" }); + }) +} + export function showPopupDetails({ mapId, coordinate, description, maxWidth = "300px", closeButton = true, closeOnClick = true, options = {}, callbackOnClose }) { const map = Vue.config.maps[mapId]; if (!map) @@ -423,28 +467,29 @@ export function showPopupDetails({ mapId, coordinate, description, maxWidth = "3 const popupOptions = Object.assign({ offset: {}, className: "my-class", closeButton: closeButton, closeOnClick: closeOnClick }, options); // 如果已有共享 popup,复用并更新位置/内容;否则创建新的并绑定 close 事件以便释放引用 - if (sharedPopup) { + if (sharedPopup[mapId]) { try { - sharedPopup.setLngLat(coordinate) + sharedPopup[mapId].setLngLat(coordinate) .setHTML(description) .setOffset(10) - .setMaxWidth(maxWidth); + .setMaxWidth(maxWidth) + .addTo(map); } catch (err) { + console.error("设置 popup 失败:", err); try { // 万一现有 popup 状态异常,移除并重新创建 - sharedPopup.remove(); - sharedPopup = null; + sharedPopup[mapId].remove(); + sharedPopup[mapId] = null; } catch (e) { console.error("移除异常 popup 失败:", e); } - sharedPopup = new window.mapboxgl.Popup(popupOptions) + sharedPopup[mapId] = new window.mapboxgl.Popup(popupOptions) .setLngLat(coordinate) .setHTML(description) .setOffset(10) .setMaxWidth(maxWidth) .addTo(map); - sharedPopup.on('close', () => { - sharedPopup = null; + sharedPopup[mapId].on('close', () => { // 关闭弹窗时执行回调(如有) if (callbackOnClose && typeof callbackOnClose === "function") { callbackOnClose(); @@ -452,14 +497,13 @@ export function showPopupDetails({ mapId, coordinate, description, maxWidth = "3 }); } } else { - sharedPopup = new window.mapboxgl.Popup(popupOptions) + sharedPopup[mapId] = new window.mapboxgl.Popup(popupOptions) .setLngLat(coordinate) .setHTML(description) .setOffset(10) .setMaxWidth(maxWidth) .addTo(map); - sharedPopup.on('close', () => { - sharedPopup = null; + sharedPopup[mapId].on('close', () => { // 关闭弹窗时执行回调(如有) if (callbackOnClose && typeof callbackOnClose === "function") { callbackOnClose();