From 799dd817aeef4490ca2f2567d0aa02c6c86064dd Mon Sep 17 00:00:00 2001 From: EpicKiwi Date: Sat, 13 Jun 2026 15:37:07 +0200 Subject: [PATCH] Amelioration de la navigation sur la carte --- css/style.css | 51 ++++++++++++++++++++--- js/components/bidi-panel.js | 2 +- js/index.js | 82 ++++++++++++++++++++++++++++--------- js/map.js | 66 ++++++++++++++++++++--------- js/symbols.js | 16 +++++++- 5 files changed, 171 insertions(+), 46 deletions(-) diff --git a/css/style.css b/css/style.css index ba2565a..c7a4b23 100644 --- a/css/style.css +++ b/css/style.css @@ -88,8 +88,53 @@ body > hr { } } -.highlight-point-icon > * { +#map .highlight-point-icon > * { + width: fit-content; + height: fit-content; transform: translateX(-50%) translateY(-50%); + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + position: relative; +} + +#map .highlight-point-icon > a { + text-decoration: none; + color: inherit; +} + +#map .highlight-point-icon h3 { + width: max-content; + max-width: min(25vw, 100px); + text-align: center; + margin: 0; + color: white; + font-size: 1em; + line-height: 1; + --outline-size: 1px; + text-shadow: 0px var(--outline-size) 0px var(--symbol-border-color), + var(--outline-size) 0px 0px var(--symbol-border-color), + var(--outline-size) var(--outline-size) 0px var(--symbol-border-color), + calc(var(--outline-size) * -1) calc(var(--outline-size) * -1) 0px var(--symbol-border-color), + 0px calc(var(--outline-size) * -1) 0px var(--symbol-border-color), + calc(var(--outline-size) * -1) 0px 0px var(--symbol-border-color) + ; + opacity: clamp(0, calc( var(--zoom-level) - 18 ), 1) ; +} + +#map .highlight-point-icon img ~ h3 { + position: absolute; + bottom: 0; + left: 50%; + transform: translateX(-50%) translateY(100%); + margin-top: 1ex; +} + + +#map .highlight-point-icon:not(.active) { + opacity: 0; + pointer-events: none; } .map-amenity-icon .map-amenity-icon-container { @@ -135,10 +180,6 @@ body > hr { opacity: 0; } -#map .highlight-point-icon:not(.active) { - opacity: 0; -} - /* SAERCH FORM */ #search-section { diff --git a/js/components/bidi-panel.js b/js/components/bidi-panel.js index 73e09e3..d326f65 100644 --- a/js/components/bidi-panel.js +++ b/js/components/bidi-panel.js @@ -209,7 +209,7 @@ export class BidiPanelElement extends HTMLElement { requestDispatchChangeEvent(){ let currentPanel = this.activeChildren if(currentPanel != this.#lastActive){ - this.dispatchEvent(new ActivePanelChangeEvent("activePanelChange", this.#currentIndex)) + this.dispatchEvent(new ActivePanelChangeEvent("activePanelChange", this.#currentIndex || this.activeChildrenIndex)) this.#lastActive = currentPanel } } diff --git a/js/index.js b/js/index.js index 6dc7021..8f12cbe 100644 --- a/js/index.js +++ b/js/index.js @@ -26,13 +26,44 @@ search_form.elements["query"].addEventListener("change", () => search_form.reque search_form.elements["query"].addEventListener("input", () => search_form.requestSubmit()) window.addEventListener("hashchange", () => { - let place_id = decodeURIComponent(location.hash.substring(1)) - if(place_id){ - MAP.highlight(place_id) - } else { - MAP.unhighlight_all() - } + let place_id = decodeURIComponent(location.hash.substring(1)) + if (place_id) { + let feature = places.getFeatureById(place_id); + if (feature) { + MAP.highlight(place_id) + if(document.getElementById("search-result")) { + openSearchResultItem(feature) + } else { + let foundIndex = null; + let panelChildren = document.getElementById("result-panel").children + for(let i = 0; i { e.preventDefault() @@ -44,23 +75,23 @@ search_form.addEventListener("submit", e => { let search_results = places.search(data.get("query")) + MAP.unhighlight_all(); + for(let result_item of search_results){ let el = document.createElement("li") let a = document.createElement("a") el.append(a) a.href = "#"+encodeURIComponent(result_item.ref) - a.addEventListener("click", e => { - e.preventDefault() - openSearchResultItem(result_item.feature) - }) - let header = document.createElement("camp-feature-short-header") - header.feature = result_item.feature - a.append(header) + let header = document.createElement("camp-feature-short-header") + header.feature = result_item.feature + a.append(header) resultElements.push(el) + MAP.show(result_item.feature) } if(!document.getElementById("search-result")){ let el = document.createElement("ol") + el.id = "search-result" document.getElementById("result-panel").replaceChildren(el) } @@ -71,7 +102,6 @@ search_form.addEventListener("submit", e => { document.getElementById("search-result").replaceChildren(document.createTextNode("Pas de resultat")) } - document.getElementById("search-result").children[0]?.scrollIntoView() } else { document.getElementById("search-result")?.remove() } @@ -112,25 +142,39 @@ function openSearchResultItem(feature){ } } +function openFeature(feature){ + let panel = document.getElementById("result-panel") + let root = document.createElement("camp-feature") + root.feature = feature + panel.replaceChildren(root) + requestAnimationFrame(() => { + panel.setActiveChildrenIndex(0, {behavior: "instant"}) + }) + updateActiveFeature(feature) +} + function updateActiveFeature(feature_or_featureid){ let newUrl = new URL(window.location) if(feature_or_featureid){ newUrl.hash = encodeURIComponent(feature_or_featureid.id || feature_or_featureid) } else { - delete newUrl.hash; + newUrl.hash = ""; + } + if(newUrl.toString() != location.toString()){ + window.history.replaceState(null, "", newUrl.toString()) + window.dispatchEvent(new Event("hashchange")) } - window.history.replaceState(null, "", newUrl.toString()) - window.dispatchEvent(new Event("hashchange")) } document.getElementById("result-panel").addEventListener("activePanelChange", e => { - if(e.activePanelIndex){ + console.log("Panel changed", e.activePanelIndex) + if(e.activePanelIndex || e.activePanelIndex === 0){ let activeElement = e.target.children[e.activePanelIndex] if(activeElement instanceof FeatureElement){ let feature = activeElement.feature updateActiveFeature(feature) } else { - MAP.unhighlight_all() + updateActiveFeature(null) } } }) diff --git a/js/map.js b/js/map.js index 53a60a4..9e26f54 100644 --- a/js/map.js +++ b/js/map.js @@ -107,22 +107,38 @@ export async function init_places(places_db){ // La couche des zones disponibles const area_highlight = L.geoJSON(null, { pointToLayer: function(feature, latlng) { + let contentEl = document.createElement("a") + + if(feature.id){ + contentEl.href = `#${encodeURIComponent(feature.id)}` + } else if(feature.parentFeature?.id){ + contentEl.href = `#${encodeURIComponent(feature.parentFeature.id)}` + } + let symbol = feature.mapSymbol; if(symbol.markerUrl) { - - let iconEl = document.createElement("img"); - iconEl.src = symbol.markerUrl; - - if(iconEl){ - return L.marker(latlng, { - icon: L.divIcon({ - className: "highlight-point-icon", - html: iconEl, - iconSize: [0, 0] - }) - }) - } + let iconEl = document.createElement("img") + iconEl.src = symbol.markerUrl + contentEl.append(iconEl) } + + if(symbol.borderColor && symbol.borderColor != "white"){ + contentEl.style.setProperty("--symbol-border-color", symbol.borderColor); + } + + if(feature.properties.name){ + let nameEl = document.createElement("h3") + nameEl.textContent = feature.properties.name + contentEl.append(nameEl) + } + + return L.marker(latlng, { + icon: L.divIcon({ + className: "highlight-point-icon", + html: contentEl, + iconSize: [0, 0] + }) + }) }, style: function(feature){ let symbol = feature.mapSymbol; @@ -171,6 +187,24 @@ export function highlight(place_or_placeid){ place = place_or_placeid } + show(place_or_placeid) + + let centroid = turf.centroid(place) + map.panTo(L.latLng( + centroid.geometry.coordinates[1], + centroid.geometry.coordinates[0] + )) +} + +export function show(place_or_placeid){ + let place; + + if(typeof place_or_placeid == "string"){ + place = places.getFeatureById(place_or_placeid) + } else { + place = place_or_placeid + } + if(place[HIGHLIGHT_LAYER]){ place[HIGHLIGHT_LAYER].getElement() .classList.add("active") @@ -181,10 +215,4 @@ export function highlight(place_or_placeid){ point_layer.getElement() .classList.add("active") } - - let centroid = turf.centroid(place) - map.panTo(L.latLng( - centroid.geometry.coordinates[1], - centroid.geometry.coordinates[0] - )) } \ No newline at end of file diff --git a/js/symbols.js b/js/symbols.js index 310a506..3358eb6 100644 --- a/js/symbols.js +++ b/js/symbols.js @@ -102,8 +102,14 @@ function getBaseSymbolForFeature(feature){ if(feature.properties["batiment"] || feature.properties["piece-batiment"]){ return BUILDING_SYMBOL } - - return DEFAULT_SYMBOL + + if(feature.parentFeature && feature.parentFeature.geometry.type != "Point"){ + return DEFAULT_AREA_SYMBOL + } else if (feature.geometry.type != "Point") { + return DEFAULT_AREA_SYMBOL + } else { + return DEFAULT_SYMBOL + } } // PREDEFINED Symbols @@ -115,6 +121,12 @@ export const DEFAULT_SYMBOL = new MapSymbol() DEFAULT_SYMBOL.borderColor = "white" } +export const DEFAULT_AREA_SYMBOL = new MapSymbol() +{ + DEFAULT_AREA_SYMBOL.backgroundColor = "white" + DEFAULT_AREA_SYMBOL.borderColor = "white" +} + export const SLEEPING_SYMBOL = new MapSymbol() { SLEEPING_SYMBOL.markerUrl = new URL("../icons/dortoir.svg", import.meta.url)