Amelioration de la navigation sur la carte

This commit is contained in:
EpicKiwi 2026-06-13 15:37:07 +02:00
parent aa8ea624c7
commit 799dd817ae
Signed by: epickiwi
GPG key ID: C4B28FD2729941CE
5 changed files with 171 additions and 46 deletions

View file

@ -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 {

View file

@ -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
}
}

View file

@ -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<panelChildren.length; i++) {
let feature_el = panelChildren[i];
if(feature_el instanceof FeatureElement && feature_el.feature.id == feature.id){
foundIndex = i;
break;
}
}
if(foundIndex != null){
document.getElementById("result-panel").setActiveChildrenIndex(foundIndex, {behavior: "instant"})
} else {
openFeature(feature)
}
}
for(let feature_el of document.getElementById("result-panel").children) {
if(feature_el instanceof FeatureElement){
MAP.show(feature_el.feature)
}
}
}
} else {
MAP.unhighlight_all()
}
})
if(location.hash){
window.dispatchEvent(new Event("hashchange"))
}
search_form.addEventListener("submit", e => {
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)
}
}
})

View file

@ -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]
))
}

View file

@ -103,7 +103,13 @@ function getBaseSymbolForFeature(feature){
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)