Auto deploy: 2025-12-09 06:00:27

This commit is contained in:
Your Name 2025-12-09 06:00:31 +00:00
parent 4b7d8c3965
commit ae2be1a71b
2 changed files with 143 additions and 126 deletions

View File

@ -1,108 +1,170 @@
import maplibregl from "maplibre-gl"; import maplibregl from "maplibre-gl";
import { getCoords } from "./mapGeo";
import { extractPostText } from "./mapFilter";
// Supprime tous les markers actuels /**
* Supprime tous les marqueurs de la carte
*/
export function clearAllMarkers(markersRef, expandedElRef) { export function clearAllMarkers(markersRef, expandedElRef) {
markersRef.current.forEach((m) => m.marker.remove()); if (markersRef.current) {
for (const item of markersRef.current) {
try {
item.marker.remove();
} catch {
// ignore
}
}
}
markersRef.current = []; markersRef.current = [];
if (expandedElRef) { if (expandedElRef) {
expandedElRef.current = null; expandedElRef.current = null;
} }
} }
// Crée un marker pour un post /**
* Crée un DOM marker pour un post et l'ancre sur sa coordonnée.
* - mapRef : ref vers la map MapLibre
* - markersRef : ref vers la liste [{ id, marker, el, post }]
* - expandedElRef : ref vers l'élément DOM du post actuellement "grand"
*/
export function createMarkerForPost(post, mapRef, markersRef, expandedElRef) { export function createMarkerForPost(post, mapRef, markersRef, expandedElRef) {
const map = mapRef.current; const map = mapRef.current;
if (!map) return; if (!map) return;
const coords = getCoords(post); // Récupère les coords (lat/lon / Lat/Lon / latitude/longitude)
if (!coords) return; const lat =
typeof post.lat === "number"
? post.lat
: typeof post.Lat === "number"
? post.Lat
: typeof post.latitude === "number"
? post.latitude
: null;
// évite les doublons (même id déjà affiché) const lon =
if ( typeof post.lon === "number"
typeof post.id === "number" && ? post.lon
markersRef.current.some((m) => m.id === post.id) : typeof post.Lon === "number"
) { ? post.Lon
: typeof post.longitude === "number"
? post.longitude
: null;
if (lat == null || lon == null) {
console.warn("Post sans coordonnée valide:", post);
return; return;
} }
const [lngP, latP] = coords; // Petit texte (on garde court)
if ( const title = (post.title || post.Title || "").trim() || "Untitled";
typeof lngP !== "number" || const snippet =
typeof latP !== "number" || (post.snippet || post.Snippet || "").trim() ||
Number.isNaN(lngP) || (post.body || post.Body || "").trim() ||
Number.isNaN(latP) title;
) {
return;
}
const { title, body, short } = extractPostText(post); // ELEMENT DOM DU MARKER
const root = document.createElement("div");
root.className = "post-marker post-marker-compact";
const compactHTML = ` const inner = document.createElement("div");
<div class="marker-inner"> inner.className = "marker-inner";
<div class="marker-dot"></div>
<span class="marker-text">${short}</span>
</div>
`;
const expandedHTML = ` const dot = document.createElement("div");
<div class="marker-expanded-inner"> dot.className = "marker-dot";
<div class="marker-expanded-header">
<div class="marker-dot"></div>
<span class="marker-expanded-title">${title}</span>
</div>
<div class="marker-expanded-body">
${body}
</div>
</div>
`;
const el = document.createElement("div"); const text = document.createElement("div");
el.className = "post-marker post-marker-compact"; text.className = "marker-text";
el.innerHTML = compactHTML; text.textContent = title;
inner.appendChild(dot);
inner.appendChild(text);
root.appendChild(inner);
// Marker MapLibre -> POSITION = [lon, lat] SANS OFFSET
const marker = new maplibregl.Marker({ const marker = new maplibregl.Marker({
element: el, element: root,
anchor: "bottom", anchor: "bottom", // le bas du marker pointe sur la coordonnée
}) })
.setLngLat(coords) .setLngLat([lon, lat])
.addTo(map); .addTo(map);
const meta = { // Sauvegarde pour pouvoir les nettoyer
id: typeof post.id === "number" ? post.id : null, const entry = { id: post.id, marker, el: root, post };
marker, markersRef.current.push(entry);
el,
compactHTML,
expandedHTML,
};
markersRef.current.push(meta);
const toggle = () => { // Quand on clique -> on ouvre le gros post par-dessus, mais à la même coordonnée
if (expandedElRef.current && expandedElRef.current !== el) { root.addEventListener("click", (ev) => {
const prev = markersRef.current.find( ev.stopPropagation();
(m) => m.el === expandedElRef.current
); // Fermer le précédent gros post
if (prev) { if (expandedElRef.current && expandedElRef.current !== root) {
prev.el.className = "post-marker post-marker-compact"; collapseMarkerElement(expandedElRef.current);
prev.el.innerHTML = prev.compactHTML;
}
} }
if (expandedElRef.current === el) { // Toggle compact/expanded sur ce marker
el.className = "post-marker post-marker-compact"; if (root.classList.contains("post-marker-expanded")) {
el.innerHTML = compactHTML; collapseMarkerElement(root);
expandedElRef.current = null; expandedElRef.current = null;
} else { } else {
el.className = "post-marker post-marker-expanded"; expandMarkerElement(root, { title, snippet });
el.innerHTML = expandedHTML; expandedElRef.current = root;
expandedElRef.current = el;
} }
};
el.addEventListener("click", toggle);
el.addEventListener("touchend", (e) => {
e.preventDefault();
toggle();
}); });
} }
/**
* Passe un marker en mode "grand post"
*/
function expandMarkerElement(root, { title, snippet }) {
root.classList.remove("post-marker-compact");
root.classList.add("post-marker-expanded");
// Nettoie l'intérieur et reconstruit
root.innerHTML = "";
const container = document.createElement("div");
container.className = "marker-expanded-inner";
const header = document.createElement("div");
header.className = "marker-expanded-header";
const dot = document.createElement("div");
dot.className = "marker-dot";
const titleEl = document.createElement("div");
titleEl.className = "marker-expanded-title";
titleEl.textContent = title;
header.appendChild(dot);
header.appendChild(titleEl);
const bodyEl = document.createElement("div");
bodyEl.className = "marker-expanded-body";
bodyEl.textContent = snippet;
container.appendChild(header);
container.appendChild(bodyEl);
root.appendChild(container);
}
/**
* Repasse un marker en mode petit post
*/
function collapseMarkerElement(root) {
root.classList.remove("post-marker-expanded");
root.classList.add("post-marker-compact");
root.innerHTML = "";
const inner = document.createElement("div");
inner.className = "marker-inner";
const dot = document.createElement("div");
dot.className = "marker-dot";
const text = document.createElement("div");
text.className = "marker-text";
text.textContent = "…";
inner.appendChild(dot);
inner.appendChild(text);
root.appendChild(inner);
}

View File

@ -1,22 +1,12 @@
/* IMPORTANT: on ne touche pas au transform du marker :
MapLibre l'utilise pour placer le point. */
.post-marker { .post-marker {
position: relative;
transform: none !important; /* pas de translate chelou */
display: flex;
align-items: center;
justify-content: center;
pointer-events: auto; pointer-events: auto;
} }
/* Petit post */ /* Petit post compact */
.post-marker-compact { .post-marker-compact .marker-inner {
padding: 2px 4px;
}
.post-marker-expanded {
padding: 0;
}
.marker-inner {
display: flex; display: flex;
align-items: center; align-items: center;
padding: 4px 8px; padding: 4px 8px;
@ -27,25 +17,8 @@
max-width: 220px; max-width: 220px;
} }
.marker-dot {
width: 10px;
height: 10px;
border-radius: 999px;
background: #3ec6ff;
margin-right: 6px;
}
.marker-text {
color: #e8f5ff;
font-size: 11px;
font-weight: 500;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
/* Gros post */ /* Gros post */
.marker-expanded-inner { .post-marker-expanded .marker-expanded-inner {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
padding: 8px 10px; padding: 8px 10px;
@ -56,22 +29,4 @@
max-width: 260px; max-width: 260px;
} }
.marker-expanded-header { /* Etc… (le reste de ton style peut rester pareil) */
display: flex;
align-items: center;
margin-bottom: 6px;
}
.marker-expanded-title {
color: #f5fbff;
font-size: 12px;
font-weight: 600;
}
.marker-expanded-body {
color: #c7e3ff;
font-size: 11px;
line-height: 1.35;
max-height: 120px;
overflow: hidden;
}