diff --git a/src/components/Map/markerManager.js b/src/components/Map/markerManager.js index 560f96d..8c6b61f 100644 --- a/src/components/Map/markerManager.js +++ b/src/components/Map/markerManager.js @@ -20,15 +20,54 @@ export function clearAllMarkers(markersRef, expandedElRef) { } /** - * Helper: hide/show all markers except one element + * Util: rectangles overlap? */ -function setOthersVisibility(markersRef, exceptEl, visible) { +function rectsOverlap(a, b) { + return !( + a.right < b.left || + a.left > b.right || + a.bottom < b.top || + a.top > b.bottom + ); +} + +/** + * Hide only markers that overlap the expanded card. + * - expandedEl: the marker root that is expanded + */ +export function applyOcclusionForExpanded(markersRef, expandedEl) { + if (!expandedEl) return; + + const expandedCard = expandedEl.querySelector(".post-card"); + if (!expandedCard) return; + + const expandedRect = expandedCard.getBoundingClientRect(); + const list = markersRef.current || []; + + for (const item of list) { + const el = item?.el; + if (!el || el === expandedEl) continue; + + // Compute marker rect (bubble + pointer) + const r = el.getBoundingClientRect(); + + const hide = rectsOverlap(expandedRect, r); + + el.style.visibility = hide ? "hidden" : "visible"; + el.style.pointerEvents = hide ? "none" : "auto"; + } +} + +/** + * Reset all markers visible + */ +export function clearOcclusion(markersRef) { const list = markersRef.current || []; for (const item of list) { const el = item?.el; - if (!el || el === exceptEl) continue; - el.style.visibility = visible ? "visible" : "hidden"; - el.style.pointerEvents = visible ? "auto" : "none"; + if (!el) continue; + el.style.visibility = "visible"; + el.style.pointerEvents = "auto"; } } @@ -39,8 +78,8 @@ function setOthersVisibility(markersRef, exceptEl, visible) { * * Règles: * - 1 seul post ouvert à la fois - * - clic sur la map => ferme (géré dans useMapCore) - * - quand un post est ouvert => on cache les autres markers pour éviter les overlaps + * - clic sur la map => ferme (useMapCore) + * - quand un post est ouvert => on cache SEULEMENT les markers qui le recouvrent */ export function createMarkerForPost(post, mapRef, markersRef, expandedElRef) { const map = mapRef.current; @@ -96,8 +135,8 @@ export function createMarkerForPost(post, mapRef, markersRef, expandedElRef) {
`; - // remettre les autres markers visibles - setOthersVisibility(markersRef, root, true); + // bring back hidden markers + clearOcclusion(markersRef); } function renderExpanded() { @@ -149,14 +188,16 @@ export function createMarkerForPost(post, mapRef, markersRef, expandedElRef) { `; - // cacher les autres markers pendant que celui-ci est ouvert - setOthersVisibility(markersRef, root, false); + // Wait a frame so DOM has final size, then hide only overlapping markers + requestAnimationFrame(() => { + applyOcclusionForExpanded(markersRef, root); + }); } // état initial : compact renderCompact(); - // IMPORTANT: garder une ref stable pour useMapCore (clic sur map => ferme) + // utilisé par useMapCore pour fermer via clic map root.__renderCompact = renderCompact; const marker = new maplibregl.Marker({ @@ -179,7 +220,7 @@ export function createMarkerForPost(post, mapRef, markersRef, expandedElRef) { expandedElRef.current = null; } - // Toggle pour ce post + // Toggle const isExpanded = root.classList.contains("post-pin--expanded"); if (isExpanded) { renderCompact(); diff --git a/src/components/Map/useMapCore.js b/src/components/Map/useMapCore.js index d0b71b8..f41cc28 100644 --- a/src/components/Map/useMapCore.js +++ b/src/components/Map/useMapCore.js @@ -2,7 +2,7 @@ import { useEffect, useRef, useState } from "react"; import maplibregl from "maplibre-gl"; import { LAST_VIEW_KEY } from "./mapConfig"; import { getViewFromMap } from "./mapGeo"; -import { clearAllMarkers } from "./markerManager"; +import { clearAllMarkers, applyOcclusionForExpanded } from "./markerManager"; // renvoie le style MapLibre en fonction du thème function getBaseStyle(theme) { @@ -98,6 +98,14 @@ export function useMapCore(theme) { map.addControl(new maplibregl.NavigationControl(), "top-right"); mapRef.current = map; + // If a post is expanded, re-apply occlusion on zoom/move (only hides overlapping ones) + const reOcclude = () => { + const el = expandedElRef.current; + if (el) applyOcclusionForExpanded(markersRef, el); + }; + map.on("move", reOcclude); + map.on("zoom", reOcclude); + // Close expanded post when clicking on the map (outside markers) map.on("click", () => { const el = expandedElRef.current;