show carpool areas on the map only while the accordion is open
This commit is contained in:
@@ -121,7 +121,8 @@
|
||||
</div>
|
||||
|
||||
<!-- Covoiturage -->
|
||||
<div class="result-accordion" x-data="{ open: false }">
|
||||
<div class="result-accordion" x-data="{ open: false }"
|
||||
x-init="$watch('open', value => value ? showCarpoolAreaMarkers() : hideCarpoolAreaMarkers())">
|
||||
<button type="button" class="accordion-header" @click="open = !open" :class="{ 'active': open }">
|
||||
<span class="accordion-title">Covoiturage</span>
|
||||
<span class="accordion-badge" x-text="results.carpools?.number || 0"></span>
|
||||
@@ -733,47 +734,86 @@
|
||||
};
|
||||
}
|
||||
|
||||
function addCarpoolAreasLayer(map, areas) {
|
||||
if (!areas.length || map.getSource('carpool-areas')) return;
|
||||
// Marker glyph per BNLC type — same set as the back-office compact view.
|
||||
function carpoolAreaIcon(type) {
|
||||
const glyph = (body, width) => `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="13" height="13" fill="none" stroke="white" stroke-width="${width || 2}" stroke-linecap="round" stroke-linejoin="round">${body}</svg>`;
|
||||
|
||||
map.addSource('carpool-areas', {
|
||||
type: 'geojson',
|
||||
data: {
|
||||
type: 'FeatureCollection',
|
||||
features: areas.map(area => ({
|
||||
type: 'Feature',
|
||||
geometry: {type: 'Point', coordinates: area.coordinates},
|
||||
properties: {name: area.name, city: area.city || '', type: area.type || ''}
|
||||
}))
|
||||
}
|
||||
});
|
||||
switch (type) {
|
||||
case 'Aire de covoiturage':
|
||||
return glyph('<circle cx="7" cy="17" r="2"/><circle cx="17" cy="17" r="2"/><path d="M5 17h-2v-6l2 -5h9l4 5h1a2 2 0 0 1 2 2v4h-2m-4 0h-6"/>');
|
||||
case 'Parking':
|
||||
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="13" height="13"><text x="12" y="18.5" text-anchor="middle" font-family="ui-sans-serif, system-ui, sans-serif" font-size="20" font-weight="700" fill="white">P</text></svg>`;
|
||||
case 'Parking relais':
|
||||
return glyph('<circle cx="6" cy="17" r="2"/><circle cx="18" cy="17" r="2"/><path d="M4 17h-2v-11a1 1 0 0 1 1 -1h14a5 7 0 0 1 5 7v5h-2m-4 0h-8"/><path d="M2 10h15"/>');
|
||||
case "Sortie d'autoroute":
|
||||
return glyph('<path d="M4 21v-8a4 4 0 0 1 4 -4h9"/><path d="M14 6l3 3l-3 3"/>');
|
||||
case 'Supermarché':
|
||||
return glyph('<circle cx="9" cy="19" r="1.5"/><circle cx="17" cy="19" r="1.5"/><path d="M3 4h2l2.4 10.5a2 2 0 0 0 2 1.5h7.6a2 2 0 0 0 2 -1.6l1 -5.4h-13"/>');
|
||||
case 'Auto-stop':
|
||||
return glyph('<circle cx="13" cy="4" r="1"/><path d="M7 21l3 -4"/><path d="M16 21l-2 -4l-3 -3l1 -6"/><path d="M6 12l2 -3l4 -1l3 3l3 1"/>');
|
||||
case 'Délaissé routier':
|
||||
return glyph('<path d="M12 3v4"/><path d="M12 10v4"/><path d="M12 17v4"/><path d="M5 3v18"/><path d="M19 3v18"/>');
|
||||
default:
|
||||
return glyph('<path d="M15 10.5a3 3 0 1 1 -6 0a3 3 0 0 1 6 0z"/><path d="M19.5 10.5c0 7.142 -7.5 11.25 -7.5 11.25s-7.5 -4.108 -7.5 -11.25a7.5 7.5 0 1 1 15 0z"/>', 1.8);
|
||||
}
|
||||
}
|
||||
|
||||
map.addLayer({
|
||||
id: 'carpool-areas-points',
|
||||
type: 'circle',
|
||||
source: 'carpool-areas',
|
||||
paint: {
|
||||
'circle-radius': 6,
|
||||
'circle-color': getComputedStyle(document.documentElement)
|
||||
.getPropertyValue('--color-highlight').trim() || '#F08F29',
|
||||
'circle-stroke-width': 2,
|
||||
'circle-stroke-color': '#ffffff'
|
||||
}
|
||||
});
|
||||
// The areas only show while the Covoiturage accordion is open. The flag
|
||||
// outlives the map so the markers come back when the map is recreated on
|
||||
// a desktop/mobile switch.
|
||||
let carpoolAreasVisible = false;
|
||||
let carpoolAreaMarkers = [];
|
||||
|
||||
map.on('click', 'carpool-areas-points', (e) => {
|
||||
const props = e.features[0].properties;
|
||||
const lines = [`<strong>${props.name}</strong>`];
|
||||
if (props.city) lines.push(props.city);
|
||||
if (props.type) lines.push(props.type);
|
||||
new maplibregl.Popup()
|
||||
.setLngLat(e.features[0].geometry.coordinates)
|
||||
.setHTML(lines.join('<br>'))
|
||||
function clearCarpoolAreaMarkers() {
|
||||
carpoolAreaMarkers.forEach(marker => marker.remove());
|
||||
carpoolAreaMarkers = [];
|
||||
}
|
||||
|
||||
function renderCarpoolAreaMarkers() {
|
||||
const map = window.parcoursmobMap;
|
||||
clearCarpoolAreaMarkers();
|
||||
if (!map || !carpoolAreasVisible) return;
|
||||
|
||||
const areas = carpoolAreasFromData();
|
||||
if (!areas.length) return;
|
||||
|
||||
const data = window.__PARCOURSMOB_DATA__ || {};
|
||||
const bounds = new maplibregl.LngLatBounds();
|
||||
|
||||
areas.forEach((area) => {
|
||||
const el = document.createElement('div');
|
||||
el.className = 'map-marker map-marker-area';
|
||||
el.innerHTML = `<div class="map-marker-inner">${carpoolAreaIcon(area.type)}</div>`;
|
||||
|
||||
const lines = [`<strong>${area.name}</strong>`];
|
||||
if (area.city) lines.push(area.city);
|
||||
if (area.address) lines.push(area.address);
|
||||
if (area.type) lines.push(area.type);
|
||||
|
||||
const marker = new maplibregl.Marker({ element: el })
|
||||
.setLngLat(area.coordinates)
|
||||
.setPopup(new maplibregl.Popup({ offset: 20 }).setHTML(lines.join('<br>')))
|
||||
.addTo(map);
|
||||
|
||||
carpoolAreaMarkers.push(marker);
|
||||
bounds.extend(area.coordinates);
|
||||
});
|
||||
|
||||
map.on('mouseenter', 'carpool-areas-points', () => { map.getCanvas().style.cursor = 'pointer'; });
|
||||
map.on('mouseleave', 'carpool-areas-points', () => { map.getCanvas().style.cursor = ''; });
|
||||
// Keep the trip framed while bringing the areas into view, rather than
|
||||
// recentring on the areas alone.
|
||||
if (data.departure) bounds.extend(data.departure.geometry.coordinates);
|
||||
if (data.destination) bounds.extend(data.destination.geometry.coordinates);
|
||||
map.fitBounds(bounds, { padding: 60, maxZoom: 14 });
|
||||
}
|
||||
|
||||
function showCarpoolAreaMarkers() {
|
||||
carpoolAreasVisible = true;
|
||||
renderCarpoolAreaMarkers();
|
||||
}
|
||||
|
||||
function hideCarpoolAreaMarkers() {
|
||||
carpoolAreasVisible = false;
|
||||
clearCarpoolAreaMarkers();
|
||||
}
|
||||
|
||||
function initMap() {
|
||||
@@ -814,9 +854,11 @@
|
||||
const departureEl = document.createElement('div');
|
||||
departureEl.className = 'map-marker map-marker-departure';
|
||||
departureEl.innerHTML = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white" width="18" height="18">
|
||||
<path fill-rule="evenodd" d="M11.54 22.351l.07.04.028.016a.76.76 0 00.723 0l.028-.015.071-.041a16.975 16.975 0 001.144-.742 19.58 19.58 0 002.683-2.282c1.944-1.99 3.963-4.98 3.963-8.827a8.25 8.25 0 00-16.5 0c0 3.846 2.02 6.837 3.963 8.827a19.58 19.58 0 002.682 2.282 16.975 16.975 0 001.145.742zM12 13.5a3 3 0 100-6 3 3 0 000 6z" clip-rule="evenodd" />
|
||||
</svg>
|
||||
<div class="map-marker-inner">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white" width="18" height="18">
|
||||
<path fill-rule="evenodd" d="M11.54 22.351l.07.04.028.016a.76.76 0 00.723 0l.028-.015.071-.041a16.975 16.975 0 001.144-.742 19.58 19.58 0 002.683-2.282c1.944-1.99 3.963-4.98 3.963-8.827a8.25 8.25 0 00-16.5 0c0 3.846 2.02 6.837 3.963 8.827a19.58 19.58 0 002.682 2.282 16.975 16.975 0 001.145.742zM12 13.5a3 3 0 100-6 3 3 0 000 6z" clip-rule="evenodd" />
|
||||
</svg>
|
||||
</div>
|
||||
`;
|
||||
new maplibregl.Marker({ element: departureEl })
|
||||
.setLngLat(depCoords)
|
||||
@@ -827,19 +869,20 @@
|
||||
const arrivalEl = document.createElement('div');
|
||||
arrivalEl.className = 'map-marker map-marker-arrival';
|
||||
arrivalEl.innerHTML = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white" width="18" height="18">
|
||||
<path fill-rule="evenodd" d="M3 2.25a.75.75 0 01.75.75v.54l1.838-.46a9.75 9.75 0 016.725.738l.108.054a8.25 8.25 0 005.58.652l3.109-.732a.75.75 0 01.917.81 47.784 47.784 0 00.005 10.337.75.75 0 01-.574.812l-3.114.733a9.75 9.75 0 01-6.594-.77l-.108-.054a8.25 8.25 0 00-5.69-.625l-2.202.55V21a.75.75 0 01-1.5 0V3A.75.75 0 013 2.25z" clip-rule="evenodd" />
|
||||
</svg>
|
||||
<div class="map-marker-inner">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white" width="18" height="18">
|
||||
<path fill-rule="evenodd" d="M3 2.25a.75.75 0 01.75.75v.54l1.838-.46a9.75 9.75 0 016.725.738l.108.054a8.25 8.25 0 005.58.652l3.109-.732a.75.75 0 01.917.81 47.784 47.784 0 00.005 10.337.75.75 0 01-.574.812l-3.114.733a9.75 9.75 0 01-6.594-.77l-.108-.054a8.25 8.25 0 00-5.69-.625l-2.202.55V21a.75.75 0 01-1.5 0V3A.75.75 0 013 2.25z" clip-rule="evenodd" />
|
||||
</svg>
|
||||
</div>
|
||||
`;
|
||||
new maplibregl.Marker({ element: arrivalEl })
|
||||
.setLngLat(destCoords)
|
||||
.setPopup(new maplibregl.Popup().setHTML(`<strong>Arrivée</strong><br>${destination.properties.label}`))
|
||||
.addTo(map);
|
||||
|
||||
// Les aires de covoit : ajoutées à chaque création de carte, donc
|
||||
// aussi lors du basculement desktop/mobile qui recrée la carte.
|
||||
const carpoolAreas = carpoolAreasFromData();
|
||||
map.on('load', () => addCarpoolAreasLayer(map, carpoolAreas));
|
||||
// window.parcoursmobMap is assigned by the caller, which has already
|
||||
// returned by the time `load` fires.
|
||||
map.on('load', () => renderCarpoolAreaMarkers());
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user