mirror of
https://forge.chapril.org/tykayn/osm-commerces
synced 2025-06-20 01:44:42 +02:00
fix popup infos
This commit is contained in:
parent
ef42dba9dd
commit
abdd59e8c8
3 changed files with 192 additions and 118 deletions
|
@ -118,7 +118,8 @@
|
|||
let features = [];
|
||||
let maplibre;
|
||||
let map;
|
||||
|
||||
let overpassData = {}; // Stockage des données Overpass
|
||||
|
||||
function getCompletionColor(completion) {
|
||||
if (completion === undefined || completion === null) {
|
||||
return '#808080'; // Gris pour pas d'information
|
||||
|
@ -129,30 +130,27 @@
|
|||
}
|
||||
|
||||
function calculateCompletion(element) {
|
||||
let completed = 0;
|
||||
let total = 0;
|
||||
|
||||
// Critères à vérifier
|
||||
const criteria = [
|
||||
let completionCount = 0;
|
||||
let totalFields = 0;
|
||||
|
||||
const fieldsToCheck = [
|
||||
'name',
|
||||
'addr:street',
|
||||
'addr:housenumber',
|
||||
'addr:postcode',
|
||||
'addr:city',
|
||||
'contact:street',
|
||||
'contact:housenumber',
|
||||
'opening_hours',
|
||||
'website',
|
||||
'wheelchair',
|
||||
'phone'
|
||||
'contact:website',
|
||||
'contact:phone',
|
||||
'wheelchair'
|
||||
];
|
||||
|
||||
criteria.forEach(criterion => {
|
||||
if (element.tags && element.tags[criterion]) {
|
||||
completed++;
|
||||
fieldsToCheck.forEach(field => {
|
||||
totalFields++;
|
||||
if (element.tags && element.tags[field]) {
|
||||
completionCount++;
|
||||
}
|
||||
total++;
|
||||
});
|
||||
|
||||
return total > 0 ? (completed / total) * 100 : 0;
|
||||
return (completionCount / totalFields) * 100;
|
||||
}
|
||||
|
||||
function createPopupContent(element) {
|
||||
|
@ -254,8 +252,8 @@
|
|||
let josm_elements = [];
|
||||
|
||||
async function loadPlaces(map) {
|
||||
map_is_loaded = false;
|
||||
try {
|
||||
const request = `{{query_places |raw}}`;
|
||||
const response = await fetch('https://overpass-api.de/api/interpreter', {
|
||||
method: 'POST',
|
||||
body: request
|
||||
|
@ -264,46 +262,113 @@
|
|||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
const data = await response.json();
|
||||
console.log('Lieux chargés:', data.elements);
|
||||
mapElements = data.elements;
|
||||
map_is_loaded = true;
|
||||
console.log('Données reçues:', data);
|
||||
|
||||
// Créer le graphique de distribution
|
||||
createCompletionChart(data.elements);
|
||||
// Stocker les données Overpass
|
||||
data.elements.forEach(element => {
|
||||
overpassData[element.id] = element;
|
||||
});
|
||||
|
||||
// Mettre à jour les cercles
|
||||
features = [];
|
||||
|
||||
josm_elements = [];
|
||||
data.elements.forEach(element => {
|
||||
const lat = element.lat || (element.center && element.center.lat);
|
||||
const lon = element.lon || (element.center && element.center.lon);
|
||||
|
||||
if (lat && lon) {
|
||||
const completion = calculateCompletion(element);
|
||||
const color = getCompletionColor(completion);
|
||||
|
||||
// Créer un cercle de 20 mètres de rayon (plus petit)
|
||||
const circle = turf.circle([lon, lat], 0.04, { steps: 64, units: 'kilometers' });
|
||||
circle.properties = {
|
||||
color: color,
|
||||
completion: completion,
|
||||
name: element.tags?.name || 'Sans nom',
|
||||
popupContent: createPopupContent(element),
|
||||
center: [lon, lat] // Stocker le centre comme un tableau [lon, lat]
|
||||
console.log('Completion pour', element.tags?.name, ':', completion, '%');
|
||||
|
||||
const circle = {
|
||||
id: `circle-${element.id}`,
|
||||
type: 'Feature',
|
||||
properties: {
|
||||
id: element.id,
|
||||
name: element.tags?.name || 'Sans nom',
|
||||
completion: completion,
|
||||
center: [lon, lat]
|
||||
},
|
||||
geometry: {
|
||||
type: 'Point',
|
||||
coordinates: [lon, lat]
|
||||
}
|
||||
};
|
||||
features.push(circle);
|
||||
josm_elements.push(element);
|
||||
}
|
||||
});
|
||||
|
||||
// Mettre à jour la source des cercles
|
||||
map.getSource('completion-circles').setData({
|
||||
'type': 'FeatureCollection',
|
||||
'features': features
|
||||
// Créer les cercles sur la carte
|
||||
features.forEach(feature => {
|
||||
const layerId = `circle-${feature.properties.id}`;
|
||||
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
|
||||
});
|
||||
|
||||
map.addLayer({
|
||||
'id': layerId,
|
||||
'type': 'fill',
|
||||
'source': layerId,
|
||||
'paint': {
|
||||
'fill-color': getCompletionColor(feature.properties.completion),
|
||||
'fill-opacity': 0.7
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Calculer les bounds pour tous les points
|
||||
// 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);
|
||||
if (points.length > 0) {
|
||||
const bounds = new maplibregl.LngLatBounds(points[0], points[0]);
|
||||
|
@ -319,33 +384,68 @@
|
|||
console.warn('Bounds invalides, utilisation des coordonnées par défaut');
|
||||
}
|
||||
}
|
||||
|
||||
createCompletionChart(data.elements);
|
||||
|
||||
// Cacher le spinner une fois le chargement terminé
|
||||
document.getElementById('maploader').style.display = 'none';
|
||||
|
||||
document.getElementById('maploader').classList.add('d-none');
|
||||
} catch (error) {
|
||||
console.error('Erreur lors du chargement des lieux:', error);
|
||||
document.getElementById('maploader').classList.add('d-none');
|
||||
}
|
||||
}
|
||||
|
||||
function updateCircles(map) {
|
||||
if (!map) return;
|
||||
|
||||
function openJOSMQuery(map, query) {
|
||||
const bounds = map.getBounds();
|
||||
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));
|
||||
|
||||
const josmUrl = `http://localhost:8111/load_object?` +
|
||||
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) {
|
||||
const bounds = map.getBounds();
|
||||
|
||||
const josmUrl = `http://localhost:8111/load_object?` +
|
||||
|
||||
`objects=${query}`;
|
||||
`objects=${query}`;
|
||||
|
||||
// Créer un élément <a> temporaire
|
||||
const tempLink = document.createElement('a');
|
||||
tempLink.style.display = 'none';
|
||||
document.body.appendChild(tempLink);
|
||||
// Créer un élément <a> temporaire
|
||||
const tempLink = document.createElement('a');
|
||||
tempLink.style.display = 'none';
|
||||
document.body.appendChild(tempLink);
|
||||
|
||||
console.log('josmUrl', josmUrl);
|
||||
|
||||
tempLink.href = josmUrl;
|
||||
tempLink.click();
|
||||
document.body.removeChild(tempLink);
|
||||
}
|
||||
console.log('josmUrl', josmUrl);
|
||||
|
||||
tempLink.href = josmUrl;
|
||||
tempLink.click();
|
||||
document.body.removeChild(tempLink);
|
||||
}
|
||||
|
||||
function openInJOSM() {
|
||||
if (josm_elements.length === 0) {
|
||||
|
@ -355,8 +455,6 @@ function openJOSMQuery(map, query) {
|
|||
const query = createJOSMQuery(josm_elements);
|
||||
console.log('map', map);
|
||||
openJOSMQuery(map, query);
|
||||
|
||||
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
|
@ -372,65 +470,34 @@ function openJOSMQuery(map, query) {
|
|||
|
||||
document.getElementById('openInJOSM').addEventListener('click', openInJOSM);
|
||||
|
||||
map.on('load', () => {
|
||||
// Créer une source pour les cercles
|
||||
map.addSource('completion-circles', {
|
||||
'type': 'geojson',
|
||||
'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);
|
||||
});
|
||||
|
||||
// Attendre que la carte soit chargée avant d'ajouter les écouteurs d'événements
|
||||
map.on('load', function() {
|
||||
console.log('Map loaded');
|
||||
map_is_loaded = true;
|
||||
// Changer le curseur au survol des cercles
|
||||
map.on('mouseenter', 'completion-circles', () => {
|
||||
map.getCanvas().style.cursor = 'pointer';
|
||||
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.on('mouseleave', 'completion-circles', () => {
|
||||
map.getCanvas().style.cursor = '';
|
||||
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 = '';
|
||||
}
|
||||
});
|
||||
|
||||
// Charger les lieux
|
||||
loadPlaces(map);
|
||||
|
||||
});
|
||||
|
||||
sortTable();
|
||||
colorHeadingTable();
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
Loading…
Add table
Add a link
Reference in a new issue