mirror of
				https://forge.chapril.org/tykayn/osm-commerces
				synced 2025-10-09 17:02:46 +02:00 
			
		
		
		
	fix popup infos
This commit is contained in:
		
							parent
							
								
									ef42dba9dd
								
							
						
					
					
						commit
						abdd59e8c8
					
				
					 3 changed files with 192 additions and 118 deletions
				
			
		|  | @ -165,6 +165,10 @@ document.addEventListener('DOMContentLoaded', () => { | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |   /** | ||||||
|  |    * mettre à jour la barre de progression  | ||||||
|  |    * pour le formulaire de modification | ||||||
|  |    */ | ||||||
|   function updateCompletionProgress() { |   function updateCompletionProgress() { | ||||||
|     const inputs = document.querySelectorAll('input[type="text"]'); |     const inputs = document.querySelectorAll('input[type="text"]'); | ||||||
|     let filledInputs = 0; |     let filledInputs = 0; | ||||||
|  |  | ||||||
|  | @ -21,6 +21,9 @@ | ||||||
| function sortTable(Table, col, dir) { | function sortTable(Table, col, dir) { | ||||||
|     var sortClass, i; |     var sortClass, i; | ||||||
| 
 | 
 | ||||||
|  |     if (!Table) { | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|     // get previous sort column
 |     // get previous sort column
 | ||||||
|     sortTable.sortCol = -1; |     sortTable.sortCol = -1; | ||||||
|     sortClass = Table.className.match(/js-sort-\d+/); |     sortClass = Table.className.match(/js-sort-\d+/); | ||||||
|  |  | ||||||
|  | @ -118,6 +118,7 @@ | ||||||
|     let features = []; |     let features = []; | ||||||
|     let maplibre; |     let maplibre; | ||||||
|     let map; |     let map; | ||||||
|  |     let overpassData = {}; // Stockage des données Overpass | ||||||
| 
 | 
 | ||||||
|     function getCompletionColor(completion) { |     function getCompletionColor(completion) { | ||||||
|         if (completion === undefined || completion === null) { |         if (completion === undefined || completion === null) { | ||||||
|  | @ -129,30 +130,27 @@ | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     function calculateCompletion(element) { |     function calculateCompletion(element) { | ||||||
|         let completed = 0; |         let completionCount = 0; | ||||||
|         let total = 0; |         let totalFields = 0; | ||||||
|          |          | ||||||
|         // Critères à vérifier |         const fieldsToCheck = [ | ||||||
|         const criteria = [ |  | ||||||
|             'name', |             'name', | ||||||
|             'addr:street', |             'contact:street',  | ||||||
|             'addr:housenumber', |             'contact:housenumber', | ||||||
|             'addr:postcode', |  | ||||||
|             'addr:city', |  | ||||||
|             'opening_hours', |             'opening_hours', | ||||||
|             'website', |             'contact:website', | ||||||
|             'wheelchair', |             'contact:phone', | ||||||
|             'phone' |             'wheelchair' | ||||||
|         ]; |         ]; | ||||||
| 
 | 
 | ||||||
|         criteria.forEach(criterion => { |         fieldsToCheck.forEach(field => { | ||||||
|             if (element.tags && element.tags[criterion]) { |             totalFields++; | ||||||
|                 completed++; |             if (element.tags && element.tags[field]) { | ||||||
|  |                 completionCount++; | ||||||
|             } |             } | ||||||
|             total++; |  | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|         return total > 0 ? (completed / total) * 100 : 0; |         return (completionCount / totalFields) * 100; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     function createPopupContent(element) { |     function createPopupContent(element) { | ||||||
|  | @ -254,8 +252,8 @@ | ||||||
|     let josm_elements = []; |     let josm_elements = []; | ||||||
| 
 | 
 | ||||||
|     async function loadPlaces(map) { |     async function loadPlaces(map) { | ||||||
|         map_is_loaded = false; |  | ||||||
|         try { |         try { | ||||||
|  |             const request = `{{query_places |raw}}`; | ||||||
|             const response = await fetch('https://overpass-api.de/api/interpreter', { |             const response = await fetch('https://overpass-api.de/api/interpreter', { | ||||||
|                 method: 'POST', |                 method: 'POST', | ||||||
|                 body: request |                 body: request | ||||||
|  | @ -264,46 +262,113 @@ | ||||||
|                 throw new Error(`HTTP error! status: ${response.status}`); |                 throw new Error(`HTTP error! status: ${response.status}`); | ||||||
|             } |             } | ||||||
|             const data = await response.json(); |             const data = await response.json(); | ||||||
|             console.log('Lieux chargés:', data.elements); |             console.log('Données reçues:', data); | ||||||
|             mapElements = data.elements; |  | ||||||
|             map_is_loaded = true; |  | ||||||
| 
 | 
 | ||||||
|             // Créer le graphique de distribution |             // Stocker les données Overpass | ||||||
|             createCompletionChart(data.elements); |             data.elements.forEach(element => { | ||||||
|  |                 overpassData[element.id] = element; | ||||||
|  |             }); | ||||||
| 
 | 
 | ||||||
|             // Mettre à jour les cercles |             // Mettre à jour les cercles | ||||||
|             features = []; |             features = []; | ||||||
| 
 |  | ||||||
|             josm_elements = []; |             josm_elements = []; | ||||||
|             data.elements.forEach(element => { |             data.elements.forEach(element => { | ||||||
|                 const lat = element.lat || (element.center && element.center.lat); |                 const lat = element.lat || (element.center && element.center.lat); | ||||||
|                 const lon = element.lon || (element.center && element.center.lon); |                 const lon = element.lon || (element.center && element.center.lon); | ||||||
| 
 |  | ||||||
|                 if (lat && lon) { |                 if (lat && lon) { | ||||||
|                     const completion = calculateCompletion(element); |                     const completion = calculateCompletion(element); | ||||||
|                     const color = getCompletionColor(completion); |                     console.log('Completion pour', element.tags?.name, ':', completion, '%'); | ||||||
| 
 | 
 | ||||||
|                     // Créer un cercle de 20 mètres de rayon (plus petit) |                     const circle = { | ||||||
|                     const circle = turf.circle([lon, lat], 0.04, { steps: 64, units: 'kilometers' }); |                         id: `circle-${element.id}`, | ||||||
|                     circle.properties = { |                         type: 'Feature', | ||||||
|                         color: color, |                         properties: { | ||||||
|                         completion: completion, |                             id: element.id, | ||||||
|                             name: element.tags?.name || 'Sans nom', |                             name: element.tags?.name || 'Sans nom', | ||||||
|                         popupContent: createPopupContent(element), |                             completion: completion, | ||||||
|                         center: [lon, lat] // Stocker le centre comme un tableau [lon, lat] |                             center: [lon, lat] | ||||||
|  |                         }, | ||||||
|  |                         geometry: { | ||||||
|  |                             type: 'Point', | ||||||
|  |                             coordinates: [lon, lat] | ||||||
|  |                         } | ||||||
|                     }; |                     }; | ||||||
|                     features.push(circle); |                     features.push(circle); | ||||||
|                     josm_elements.push(element); |                     josm_elements.push(element); | ||||||
|                 } |                 } | ||||||
|             }); |             }); | ||||||
| 
 | 
 | ||||||
|             // Mettre à jour la source des cercles |             // Créer les cercles sur la carte | ||||||
|             map.getSource('completion-circles').setData({ |             features.forEach(feature => { | ||||||
|                 'type': 'FeatureCollection', |                 const layerId = `circle-${feature.properties.id}`; | ||||||
|                 'features': features |                 if (map.getSource(layerId)) { | ||||||
|  |                     map.removeSource(layerId); | ||||||
|  |                 } | ||||||
|  |                 if (map.getLayer(layerId)) { | ||||||
|  |                     map.removeLayer(layerId); | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 const circle = turf.circle( | ||||||
|  |                     feature.properties.center, | ||||||
|  |                     0.02, // Rayon initial en kilomètres | ||||||
|  |                     { steps: 64, units: 'kilometers' } | ||||||
|  |                 ); | ||||||
|  | 
 | ||||||
|  |                 map.addSource(layerId, { | ||||||
|  |                     'type': 'geojson', | ||||||
|  |                     'data': circle | ||||||
|                 }); |                 }); | ||||||
| 
 | 
 | ||||||
|             // Calculer les bounds pour tous les points |                 map.addLayer({ | ||||||
|  |                     'id': layerId, | ||||||
|  |                     'type': 'fill', | ||||||
|  |                     'source': layerId, | ||||||
|  |                     'paint': { | ||||||
|  |                         'fill-color': getCompletionColor(feature.properties.completion), | ||||||
|  |                         'fill-opacity': 0.7 | ||||||
|  |                     } | ||||||
|  |                 }); | ||||||
|  |             }); | ||||||
|  | 
 | ||||||
|  |             // Ajouter les popups sur les cercles | ||||||
|  |             map.on('click', function(e) { | ||||||
|  |                 const clickedFeatures = map.queryRenderedFeatures(e.point, { | ||||||
|  |                     layers: features.map(f => `circle-${f.properties.id}`) | ||||||
|  |                 }); | ||||||
|  | 
 | ||||||
|  |                 console.log('Clicked features:', clickedFeatures); | ||||||
|  | 
 | ||||||
|  |                 if (clickedFeatures.length > 0) { | ||||||
|  |                     const feature = clickedFeatures[0]; | ||||||
|  |                     const elementId = feature.layer.id.replace('circle-', ''); | ||||||
|  |                     const element = overpassData[elementId]; | ||||||
|  |                      | ||||||
|  |                     if (element) { | ||||||
|  |                         const completion = calculateCompletion(element); | ||||||
|  |                          | ||||||
|  |                         // Créer le contenu de la popup | ||||||
|  |                         const popupContent = ` | ||||||
|  |                             <div class="popup-content"> | ||||||
|  |                                 <h5>${element.tags?.name || 'Sans nom'}</h5> | ||||||
|  |                                 <p>Taux de complétion: ${Math.round(completion)}%</p> | ||||||
|  |                                 <ul> | ||||||
|  |                                     ${Object.entries(element.tags || {}) | ||||||
|  |                                         .filter(([key]) => !['name'].includes(key)) | ||||||
|  |                                         .map(([key, value]) => `<li><strong>${key}:</strong> ${value}</li>`) | ||||||
|  |                                         .join('')} | ||||||
|  |                                 </ul> | ||||||
|  |                             </div> | ||||||
|  |                         `; | ||||||
|  | 
 | ||||||
|  |                         new maplibregl.Popup() | ||||||
|  |                             .setLngLat(e.lngLat) | ||||||
|  |                             .setHTML(popupContent) | ||||||
|  |                             .addTo(map); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             }); | ||||||
|  | 
 | ||||||
|  |             // Ajuster la vue pour inclure tous les points | ||||||
|             const points = features.map(f => f.properties.center); |             const points = features.map(f => f.properties.center); | ||||||
|             if (points.length > 0) { |             if (points.length > 0) { | ||||||
|                 const bounds = new maplibregl.LngLatBounds(points[0], points[0]); |                 const bounds = new maplibregl.LngLatBounds(points[0], points[0]); | ||||||
|  | @ -320,13 +385,48 @@ | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|   |   | ||||||
|             document.getElementById('maploader').classList.add('d-none'); |             createCompletionChart(data.elements); | ||||||
|  | 
 | ||||||
|  |             // Cacher le spinner une fois le chargement terminé | ||||||
|  |             document.getElementById('maploader').style.display = 'none'; | ||||||
|  | 
 | ||||||
|         } catch (error) { |         } catch (error) { | ||||||
|             console.error('Erreur lors du chargement des lieux:', error); |             console.error('Erreur lors du chargement des lieux:', error); | ||||||
|             document.getElementById('maploader').classList.add('d-none'); |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     function updateCircles(map) { | ||||||
|  |         if (!map) return; | ||||||
|  | 
 | ||||||
|  |         const zoom = map.getZoom(); | ||||||
|  |         // Ajuster la taille de base en fonction du zoom | ||||||
|  |         // Plus le zoom est faible (loin), plus le rayon est grand | ||||||
|  |         const baseRadius = Math.min(100, 200 / Math.pow(1.2, zoom)); | ||||||
|  | 
 | ||||||
|  |         features.forEach(feature => { | ||||||
|  |             const source = map.getSource(feature.id); | ||||||
|  |             if (!source) return; | ||||||
|  | 
 | ||||||
|  |             const completion = feature.properties.completion; | ||||||
|  |             const radius = baseRadius * (1 + (completion / 100)); | ||||||
|  |              | ||||||
|  |             // Mettre à jour le rayon du cercle | ||||||
|  |             const circle = turf.circle( | ||||||
|  |                 feature.properties.center, | ||||||
|  |                 0.5* radius / 1000, // Convertir en kilomètres | ||||||
|  |                 { steps: 64, units: 'kilometers' } | ||||||
|  |             ); | ||||||
|  |              | ||||||
|  |             // Mettre à jour la source avec le nouveau cercle | ||||||
|  |             source.setData(circle); | ||||||
|  | 
 | ||||||
|  |             // Mettre à jour la couleur du cercle | ||||||
|  |             const layer = map.getLayer(feature.id); | ||||||
|  |             if (layer) { | ||||||
|  |                 map.setPaintProperty(feature.id, 'fill-color', getCompletionColor(completion)); | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     function openJOSMQuery(map, query) { |     function openJOSMQuery(map, query) { | ||||||
|         const bounds = map.getBounds(); |         const bounds = map.getBounds(); | ||||||
|  | @ -355,8 +455,6 @@ function openJOSMQuery(map, query) { | ||||||
|         const query = createJOSMQuery(josm_elements); |         const query = createJOSMQuery(josm_elements); | ||||||
|         console.log('map', map); |         console.log('map', map); | ||||||
|         openJOSMQuery(map, query); |         openJOSMQuery(map, query); | ||||||
| 
 |  | ||||||
|          |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     document.addEventListener('DOMContentLoaded', function() { |     document.addEventListener('DOMContentLoaded', function() { | ||||||
|  | @ -372,65 +470,34 @@ function openJOSMQuery(map, query) { | ||||||
| 
 | 
 | ||||||
|         document.getElementById('openInJOSM').addEventListener('click', openInJOSM); |         document.getElementById('openInJOSM').addEventListener('click', openInJOSM); | ||||||
| 
 | 
 | ||||||
|         map.on('load', () => { |         // Attendre que la carte soit chargée avant d'ajouter les écouteurs d'événements | ||||||
|             // Créer une source pour les cercles |         map.on('load', function() { | ||||||
|             map.addSource('completion-circles', { |             console.log('Map loaded'); | ||||||
|                 'type': 'geojson', |             map_is_loaded = true; | ||||||
|                 'data': { |  | ||||||
|                     'type': 'FeatureCollection', |  | ||||||
|                     'features': [] |  | ||||||
|                 } |  | ||||||
|             }); |  | ||||||
| 
 |  | ||||||
|             // Ajouter une couche pour les cercles |  | ||||||
|             map.addLayer({ |  | ||||||
|                 'id': 'completion-circles', |  | ||||||
|                 'type': 'fill', |  | ||||||
|                 'source': 'completion-circles', |  | ||||||
|                 'paint': { |  | ||||||
|                     'fill-color': ['get', 'color'], |  | ||||||
|                     'fill-opacity': 0.6, |  | ||||||
|                     'fill-outline-color': '#fff' |  | ||||||
|                 } |  | ||||||
|             }); |  | ||||||
| 
 |  | ||||||
|             // Ajouter une couche pour la bordure |  | ||||||
|             map.addLayer({ |  | ||||||
|                 'id': 'completion-circles-outline', |  | ||||||
|                 'type': 'line', |  | ||||||
|                 'source': 'completion-circles', |  | ||||||
|                 'paint': { |  | ||||||
|                     'line-color': 'rgba(100,100,100,0.5)', |  | ||||||
|                     'line-width': 2 |  | ||||||
|                 } |  | ||||||
|             }); |  | ||||||
| 
 |  | ||||||
|             // Ajouter les popups sur les cercles |  | ||||||
|             map.on('click', 'completion-circles', (e) => { |  | ||||||
|                 const properties = e.features[0].properties; |  | ||||||
| 
 |  | ||||||
|                 new maplibregl.Popup() |  | ||||||
|                     .setLngLat(e.lngLat) |  | ||||||
|                     .setHTML(properties.popupContent) |  | ||||||
|                     .addTo(map); |  | ||||||
|             }); |  | ||||||
| 
 |  | ||||||
|             // Changer le curseur au survol des cercles |             // Changer le curseur au survol des cercles | ||||||
|             map.on('mouseenter', 'completion-circles', () => { |             map.on('mouseenter', function(e) { | ||||||
|  |                 const hoveredFeatures = map.queryRenderedFeatures(e.point, { | ||||||
|  |                     layers: features.map(f => f.id) | ||||||
|  |                 }); | ||||||
|  |                 if (hoveredFeatures.length > 0) { | ||||||
|                     map.getCanvas().style.cursor = 'pointer'; |                     map.getCanvas().style.cursor = 'pointer'; | ||||||
|  |                 } | ||||||
|             }); |             }); | ||||||
| 
 | 
 | ||||||
|             map.on('mouseleave', 'completion-circles', () => { |             map.on('mouseleave', function(e) { | ||||||
|  |                 const hoveredFeatures = map.queryRenderedFeatures(e.point, { | ||||||
|  |                     layers: features.map(f => f.id) | ||||||
|  |                 }); | ||||||
|  |                 if (hoveredFeatures.length === 0) { | ||||||
|                     map.getCanvas().style.cursor = ''; |                     map.getCanvas().style.cursor = ''; | ||||||
|  |                 } | ||||||
|             }); |             }); | ||||||
| 
 | 
 | ||||||
|             // Charger les lieux |             // Charger les lieux | ||||||
|             loadPlaces(map); |             loadPlaces(map); | ||||||
|               |  | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|         sortTable(); |         sortTable(); | ||||||
|         colorHeadingTable(); |  | ||||||
|     }); |     }); | ||||||
| </script> | </script> | ||||||
| {% endblock %}  | {% endblock %}  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Tykayn
						Tykayn