responsive style

This commit is contained in:
Tykayn 2024-12-28 17:59:15 +01:00 committed by tykayn
parent bbf1bf3cdd
commit 61b7dc601f
5 changed files with 350 additions and 336 deletions

View File

@ -24,7 +24,7 @@
content="width=device-width, initial-scale=1.0, user-scalable=yes, minimum-scale=0.25, maximum-scale=5.0"> content="width=device-width, initial-scale=1.0, user-scalable=yes, minimum-scale=0.25, maximum-scale=5.0">
<link rel="shortcut icon" href="img/french.png"> <link rel="shortcut icon" href="img/french.png">
</head> </head>
<body> <body class="side-panel-open">
<header> <header>
@ -102,14 +102,10 @@
<p>Cartes des stations de recharge pour véhicules électriques basée sur les données collaborative <a <p>Cartes des stations de recharge pour véhicules électriques basée sur les données collaborative <a
href="https://openstreetmap.org">OpenStreetMap</a></p> href="https://openstreetmap.org">OpenStreetMap</a></p>
<div class="icones"> <form onclick="searchLocation()">
<img class="icon-img" src="img/Type2_Connector_Outline.svg" alt="type2"> <input type="text" id="searchLocation" placeholder="Rechercher un lieu" class="search-input">
<button id="searchButton" class="rounded-button">🔍 Rechercher</button>
<img class="icon-img" src="img/type2_combo.svg" alt="prise"> </form>
<img class="icon-img" src="img/Type2_socket.svg" alt="prise">
<img class="icon-img" src="img/socket_typee.svg" alt="prise">
<img class="icon-img" src="img/chademo.svg" alt="prise">
</div>
<button id="removeMarkers" class="rounded-button"> <button id="removeMarkers" class="rounded-button">
🗑️ Effacer les marqueurs 🗑️ Effacer les marqueurs
</button> </button>
@ -122,6 +118,9 @@
<button id="sendToJOSM" class="rounded-button"> <button id="sendToJOSM" class="rounded-button">
🗺️ Éditer dans JOSM 🗺️ Éditer dans JOSM
</button> </button>
<button id="shareUrl" class="rounded-button">
📤 Partager l'URL
</button>
<!-- <button id="toggle">--> <!-- <button id="toggle">-->
<!-- toggle : montrer les stations avec à minima 150kW de puissance dispo--> <!-- toggle : montrer les stations avec à minima 150kW de puissance dispo-->
@ -183,11 +182,19 @@
<br> <br>
Fait par <a href="https://mastodon.cipherbliss.com/@tykayn">Tykayn</a> - <a href="https://www.cipherbliss.com">www.cipherbliss.com</a>. Fait par <a href="https://mastodon.cipherbliss.com/@tykayn">Tykayn</a> - <a href="https://www.cipherbliss.com">www.cipherbliss.com</a>.
<a href="https://forge.chapril.org/tykayn/">Sources disponibles sur la forge du Chapril.</a> <a href="https://forge.chapril.org/tykayn/">Sources disponibles sur la forge du Chapril.</a>
<div class="icones">
<img class="icon-img" src="img/Type2_Connector_Outline.svg" alt="type2">
<img class="icon-img" src="img/type2_combo.svg" alt="prise">
<img class="icon-img" src="img/Type2_socket.svg" alt="prise">
<img class="icon-img" src="img/socket_typee.svg" alt="prise">
<img class="icon-img" src="img/chademo.svg" alt="prise">
</div>
<br> <br>
icones icones
câble électrique <a href="https://www.flaticon.com/fr/icones-gratuites/energie" title="energie icônes">Energie câble électrique <a href="https://www.flaticon.com/fr/icones-gratuites/energie" title="energie icônes">Energie
icônes créées par rukanicon - Flaticon</a> icônes créées par rukanicon - Flaticon</a>
</div> </div>
<script src='js/leaflet.js'></script> <script src='js/leaflet.js'></script>
<script src='js/jquery-3.2.1.min.js'></script> <script src='js/jquery-3.2.1.min.js'></script>

View File

@ -2,28 +2,51 @@
* Fonctions liées à l'édition des données OSM et à l'interaction avec JOSM * Fonctions liées à l'édition des données OSM et à l'interaction avec JOSM
*/ */
export function sendToJOSM(map) {
/**
* Envoyer les bornes de recharge de la zone visible à JOSM
* @param {*} map
*/
function sendToJOSM(map) {
const bounds = map.getBounds(); const bounds = map.getBounds();
const bbox = `${bounds.getWest()},${bounds.getSouth()},${bounds.getEast()},${bounds.getNorth()}`; const bbox = `${bounds.getWest()},${bounds.getSouth()},${bounds.getEast()},${bounds.getNorth()}`;
const josmUrl = `http://127.0.0.1:8111/load_and_zoom?left=${bounds.getWest()}&right=${bounds.getEast()}&top=${bounds.getNorth()}&bottom=${bounds.getSouth()}&select=node[amenity=charging_station]&changeset_hashtags=IRVE&layer_name=irve-depuis-OSM`; const josmUrl = `http://127.0.0.1:8111/load_and_zoom?left=${bounds.getWest()}&right=${bounds.getEast()}&top=${bounds.getNorth()}&bottom=${bounds.getSouth()}&select=node[amenity=charging_station]`;
return fetch(josmUrl) fetch(josmUrl)
.then(response => { .then(response => {
if (response.ok) { if (response.ok) {
console.log('Données envoyées à JOSM avec succès'); alert('Données envoyées à JOSM avec succès !');
return true;
} else { } else {
console.error('Erreur : JOSM doit être ouvert avec l\'option "Contrôle à distance" activée'); alert('Erreur : JOSM doit être ouvert avec l\'option "Contrôle à distance" activée');
throw new Error('JOSM non accessible');
} }
}) })
.catch(error => { .catch(error => {
console.error('Erreur JOSM:', error); console.error('Erreur JOSM:', error);
throw error; alert('Erreur : JOSM doit être ouvert avec l\'option "Contrôle à distance" activée');
}); });
} }
export default {
sendToJOSM const margin_josm_bbox = 0.00001
/**
* lien pour éditer une station de recharge dans JOSM
* @param {*} feature
* @returns
*/
function createJOSMEditLink(feature) {
var coordinates = feature.geometry.coordinates
var nodeId = feature.properties.id
var left = coordinates[0] - margin_josm_bbox
var right = coordinates[0] + margin_josm_bbox
var bottom = coordinates[1] - margin_josm_bbox
var top = coordinates[1] + margin_josm_bbox
var josmUrl = `http://127.0.0.1:8111/load_and_zoom?changeset_hashtags=IRVE&layer_name=irve-depuis-OSM&left=${left}&top=${top}&right=${right}&bottom=${bottom}&select=${nodeId}`
return josmUrl
}
export {
sendToJOSM,
createJOSMEditLink
}; };

View File

@ -7,9 +7,8 @@
import config from './config.js' import config from './config.js'
import utils from './utils.js' import utils from './utils.js'
import colorUtils from './color-utils.js' import colorUtils from './color-utils.js'
import editor from './editor.js' import { sendToJOSM, createJOSMEditLink } from './editor.js'
console.log('config', config)
let geojsondata; let geojsondata;
let lastLatLng; let lastLatLng;
@ -47,32 +46,21 @@ let display_chelou = 'show'; // les stations avec une valeur suspecte, plus de 4
function setRandomView() { function setRandomView() {
console.log('set random view') let randomCity = utils.cities[Math.floor(Math.random() * utils.cities.length)];
// Choix au hasard d'une ville parmi la liste map = map.setView(randomCity.coords, config.initialZoom);
let randomCity = utils.cities[Math.floor(Math.random() * utils.cities.length)]
console.log('randomCity', randomCity)
map = map.setView(randomCity.coords, config.initialZoom)
} }
function setCoordinatesOfLeafletMapFromQueryParameters() { function setCoordinatesOfLeafletMapFromQueryParameters() {
// Récupère les paramètres de l'URL const urlParams = new URLSearchParams(window.location.href);
// console.log('window.location', window.location.href, window) const lat = urlParams.get('lat');
const urlParams = new URLSearchParams(window.location.href) const lng = urlParams.get('lng');
const zoom = urlParams.get('zoom');
// console.log('urlParams', urlParams)
// Récupère les coordonnées et le zoom à partir des paramètres de l'URL
const lat = urlParams.get('lat')
const lng = urlParams.get('lng')
const zoom = urlParams.get('zoom')
// console.log('lat,lng,zoom', lat, lng, zoom) // Vérifie si les paramètres sont présents et valides
if (lat && lng && zoom) { if (lat && lng && zoom) {
// Initialise la carte avec les coordonnées et le zoom récupérés map = map.setView([lat, lng], zoom);
map = map.setView([lat, lng], zoom)
} else { } else {
// Affiche une erreur si les paramètres sont absents ou invalides console.error('Les paramètres de coordonnées et de zoom doivent être présents dans l\'URL.');
console.error('Les paramètres de coordonnées et de zoom doivent être présents dans l\'URL.') setRandomView();
setRandomView()
} }
} }
@ -127,56 +115,40 @@ tileGrey.addTo(map)
function buildOverpassApiUrl(map, overpassQuery) { function buildOverpassApiUrl(map, overpassQuery) {
let baseUrl = 'https://overpass-api.de/api/interpreter';
let baseUrl = 'https://overpass-api.de/api/interpreter' const kilometersMarginForLoading = 2;
// Ajouter une marge de 2 kilomètres autour des bounds const marginInDegrees = kilometersMarginForLoading / 111;
// Conversion approximative: 1 degré = 111km à l'équateur const south = map.getBounds().getSouth() - marginInDegrees;
const kilometersMarginForLoading = 2 const west = map.getBounds().getWest() - marginInDegrees;
const marginInDegrees = kilometersMarginForLoading / 111 // 2 kilomètres convertis en degrés const north = map.getBounds().getNorth() + marginInDegrees;
const south = map.getBounds().getSouth() - marginInDegrees const east = map.getBounds().getEast() + marginInDegrees;
const west = map.getBounds().getWest() - marginInDegrees let bounds = south + ',' + west + ',' + north + ',' + east;
const north = map.getBounds().getNorth() + marginInDegrees let resultUrl, query = '';
const east = map.getBounds().getEast() + marginInDegrees
let bounds = south + ',' + west + ',' + north + ',' + east
let resultUrl, query = ''
if (config.overrideQuery) { if (config.overrideQuery) {
query = `?data=[out:json][timeout:15];( query = `?data=[out:json][timeout:15];(
nwr[amenity=charging_station](${bounds}); nwr[amenity=charging_station](${bounds});
);out body geom;` );out body geom;`;
} else { } else {
let nodeQuery = 'node[' + overpassQuery + '](' + bounds + ');' let nodeQuery = 'node[' + overpassQuery + '](' + bounds + ');';
let wayQuery = 'way[' + overpassQuery + '](' + bounds + ');' let wayQuery = 'way[' + overpassQuery + '](' + bounds + ');';
let relationQuery = 'relation[' + overpassQuery + '](' + bounds + ');' let relationQuery = 'relation[' + overpassQuery + '](' + bounds + ');';
query = '?data=[out:json][timeout:15];(' + nodeQuery + wayQuery + relationQuery + ');out body geom;' query = '?data=[out:json][timeout:15];(' + nodeQuery + wayQuery + relationQuery + ');out body geom;';
} }
resultUrl = baseUrl + query resultUrl = baseUrl + query;
return resultUrl return resultUrl;
} }
const margin_josm_bbox = 0.00001
function createJOSMEditLink(feature) {
var coordinates = feature.geometry.coordinates
var nodeId = feature.properties.id
var left = coordinates[0] - margin_josm_bbox
var right = coordinates[0] + margin_josm_bbox
var bottom = coordinates[1] - margin_josm_bbox
var top = coordinates[1] + margin_josm_bbox
var josmUrl = `http://127.0.0.1:8111/load_and_zoom?changeset_hashtags=IRVE&layer_name=irve-depuis-OSM&left=${left}&top=${top}&right=${right}&bottom=${bottom}&select=${nodeId}`
return josmUrl
}
function supprimerMarqueurs() { function supprimerMarqueurs() {
all_stations_markers.clearLayers() all_stations_markers.clearLayers();
// stations_much_speed_wow.clearLayers()
map.eachLayer((layer) => { map.eachLayer((layer) => {
if (layer instanceof L.Marker) { if (layer instanceof L.Marker) {
layer.remove() layer.remove();
} }
}) });
} }
let coef_reduction_bars = 0.8 let coef_reduction_bars = 0.8
@ -193,72 +165,65 @@ function calculerPourcentage(partie, total, reduc) {
} }
function displayStatsFromGeoJson(resultAsGeojson) { function displayStatsFromGeoJson(resultAsGeojson) {
let count = resultAsGeojson.features.length;
let count = resultAsGeojson.features.length let count_station_output = 0;
let count_station_output = 0 let count_ref_eu = 0;
let count_ref_eu = 0 let output_more_than_300 = 0;
let output_more_than_300 = 0 let output_more_than_200 = 0;
let output_more_than_200 = 0 let output_more_than_100 = 0;
let output_more_than_100 = 0 let output_more_than_50 = 0;
let output_more_than_50 = 0 let count_station_outputoutput_between_1_and_50 = 0;
let count_station_outputoutput_between_1_and_50 = 0 let count_output_unknown = 0;
let count_output_unknown = 0 let count_estimated_type2combo = 0;
let count_estimated_type2combo = 0 let count_found_type2combo = 0;
let count_found_type2combo = 0 let count_found_type2 = 0;
let count_found_type2 = 0
resultAsGeojson.features.map(feature => { resultAsGeojson.features.map(feature => {
let found_type2_combo = false let found_type2_combo = false;
// trouver si les tags présentent un type combo let found_type2 = false;
let found_type2 = false let keys_of_object = Object.keys(feature.properties.tags);
// trouver si les tags présentent un type 2
let keys_of_object = Object.keys(feature.properties.tags)
keys_of_object.map(tagKey => { keys_of_object.map(tagKey => {
// console.log('tagKey', tagKey)
if (tagKey.indexOf('type2_combo') !== -1) { if (tagKey.indexOf('type2_combo') !== -1) {
found_type2_combo = true found_type2_combo = true;
// console.log('tagkey trouvé combo', tagKey)
} }
if (tagKey.indexOf('type2') !== -1) { if (tagKey.indexOf('type2') !== -1) {
found_type2 = true found_type2 = true;
} }
}) });
let outputPower = utils.guessOutputPowerFromFeature(feature) let outputPower = utils.guessOutputPowerFromFeature(feature);
if (found_type2_combo) { if (found_type2_combo) {
count_found_type2combo++ count_found_type2combo++;
} }
if (found_type2) { if (found_type2) {
count_found_type2++ count_found_type2++;
} }
if (outputPower == 0) { if (outputPower == 0) {
count_output_unknown++ count_output_unknown++;
} }
if (outputPower >= 200 && !found_type2_combo) { if (outputPower >= 200 && !found_type2_combo) {
/** count_estimated_type2combo++;
* si on trouve une puissance supérieure à 200kW on peut partir du principe que la station dispose d'une prise type_2_combo à minima
*/
count_estimated_type2combo++
} }
if (outputPower > 0 && outputPower < 50) { if (outputPower > 0 && outputPower < 50) {
count_station_outputoutput_between_1_and_50++ count_station_outputoutput_between_1_and_50++;
} }
if (outputPower >= 50 && outputPower < 100) { if (outputPower >= 50 && outputPower < 100) {
output_more_than_50++ output_more_than_50++;
} else if (outputPower >= 100 && outputPower < 200) { } else if (outputPower >= 100 && outputPower < 200) {
output_more_than_100++ output_more_than_100++;
} else if (outputPower >= 200 && outputPower < 300) { } else if (outputPower >= 200 && outputPower < 300) {
output_more_than_200++ output_more_than_200++;
} else if (outputPower >= 300) { } else if (outputPower >= 300) {
feature.properties.puissance_haute = true feature.properties.puissance_haute = true;
output_more_than_300++ output_more_than_300++;
} }
if (feature.properties.tags['charging_station:output']) { if (feature.properties.tags['charging_station:output']) {
count_station_output++ count_station_output++;
} }
if (feature.properties.tags['ref:EU:EVSE']) { if (feature.properties.tags['ref:EU:EVSE']) {
count_ref_eu++ count_ref_eu++;
} }
}) });
let bar_powers = `<div class="bars-container"> let bar_powers = `<div class="bars-container">
<div class="bar color-unknown" style="width: ${calculerPourcentage(count_output_unknown, count, true)}%">${count_output_unknown}</div> <div class="bar color-unknown" style="width: ${calculerPourcentage(count_output_unknown, count, true)}%">${count_output_unknown}</div>
<div class="bar color-power-lesser-than-50" style="width: ${calculerPourcentage(count_station_outputoutput_between_1_and_50, count, true)}%">${count_station_outputoutput_between_1_and_50 ? count_station_outputoutput_between_1_and_50 : ''}</div> <div class="bar color-power-lesser-than-50" style="width: ${calculerPourcentage(count_station_outputoutput_between_1_and_50, count, true)}%">${count_station_outputoutput_between_1_and_50 ? count_station_outputoutput_between_1_and_50 : ''}</div>
@ -266,8 +231,7 @@ function displayStatsFromGeoJson(resultAsGeojson) {
<div class="bar color-power-lesser-than-200" style="width: ${calculerPourcentage(output_more_than_100, count, true)}%">${output_more_than_100 ? output_more_than_100 : ''}</div> <div class="bar color-power-lesser-than-200" style="width: ${calculerPourcentage(output_more_than_100, count, true)}%">${output_more_than_100 ? output_more_than_100 : ''}</div>
<div class="bar color-power-lesser-than-300" style="width: ${calculerPourcentage(output_more_than_200, count, true)}%">${output_more_than_200 ? output_more_than_200 : '' | ''}</div> <div class="bar color-power-lesser-than-300" style="width: ${calculerPourcentage(output_more_than_200, count, true)}%">${output_more_than_200 ? output_more_than_200 : '' | ''}</div>
<div class="bar color-power-lesser-than-max" style="width: ${calculerPourcentage(output_more_than_300, count, true)}%">${output_more_than_300 ? output_more_than_300 : ''}</div> <div class="bar color-power-lesser-than-max" style="width: ${calculerPourcentage(output_more_than_300, count, true)}%">${output_more_than_300 ? output_more_than_300 : ''}</div>
</div> </div>`;
`
let stats_content = `<div class="stats-table"> let stats_content = `<div class="stats-table">
<table> <table>
@ -307,35 +271,16 @@ function displayStatsFromGeoJson(resultAsGeojson) {
<td>${calculerPourcentage(output_more_than_300, count)}%</td> <td>${calculerPourcentage(output_more_than_300, count)}%</td>
</tr> </tr>
</table> </table>
</div>` </div>`;
/** $('#found_charging_stations').html(stats_content);
$('#bars_power').html(bar_powers);
let stats_content = `<div class="stats">
Statistiques des <strong>${count}</strong> stations trouvées: <br/>
${count_station_output} (${calculerPourcentage(count_station_output, count)}%) ont une info de puissance max délivrée <i>charging_station:output</i>. <br/>
${count_ref_eu} (${calculerPourcentage(count_ref_eu, count)}%) ont une référence européenne <i>ref:EU:EVSE</i>. <br/>
${count_output_unknown} (${calculerPourcentage(count_output_unknown, count)}%) ont une puissance max inconnue <i>*output*</i>. <br/>
${output_more_than_300} (${calculerPourcentage(output_more_than_300, count)}%) ont une puissance max supérieure à 300 kW <i>*output*</i>. <br/>
${output_more_than_200} (${calculerPourcentage(output_more_than_200, count)}%) ont une puissance max supérieure à 200 kW <i>*output*</i>. <br/>
${output_more_than_100} (${calculerPourcentage(output_more_than_100, count)}%) ont une puissance max supérieure à 100 kW <i>*output*</i>. <br/>
${output_more_than_50} (${calculerPourcentage(output_more_than_50, count)}%) ont une puissance max supérieure à 50 kW <i>*output*</i>. <br/>
${count_found_type2combo} (${calculerPourcentage(count_found_type2combo, count)}%) ont un prise combo définie <i>*type2_combo*</i>. <br/>
${count_estimated_type2combo} (${calculerPourcentage(count_estimated_type2combo, count)}%) ont une prise combo présumée à partir de la puissance max trouvée mais non spécifiée <i>*type2_combo*</i>. <br/>${count_found_type2} (${calculerPourcentage(count_found_type2, count)}%) ont un prise type2 définie <i>*type2*</i>. <br/>
</div>`
*
*/
$('#found_charging_stations').html(stats_content)
$('#bars_power').html(bar_powers)
} }
function bindEventsOnJosmRemote() { function bindEventsOnJosmRemote() {
let josm_remote_buttons = $(`#sendToJOSM`) let josm_remote_buttons = $(`#sendToJOSM`)
// console.log('josm_remote_buttons', josm_remote_buttons[0])
$(josm_remote_buttons[0]).on('click', () => { $(josm_remote_buttons[0]).on('click', () => {
// console.log('link', josm_remote_buttons[0])
let josm_link = $(josm_remote_buttons[0]).attr('data-href') let josm_link = $(josm_remote_buttons[0]).attr('data-href')
// console.log('lancer la télécommande josm', josm_link)
$.get(josm_link, (res) => { $.get(josm_link, (res) => {
console.log('res', res) console.log('res', res)
}) })
@ -344,45 +289,34 @@ function bindEventsOnJosmRemote() {
function displayPointsFromApi(points) { function displayPointsFromApi(points) {
if (points) { if (points) {
geojsondata = osmtogeojson(points) geojsondata = osmtogeojson(points);
} }
// console.log('resultAsGeojson', geojsondata)
displayStatsFromGeoJson(geojsondata) displayStatsFromGeoJson(geojsondata);
let resultLayer = L.geoJson(geojsondata, { let resultLayer = L.geoJson(geojsondata, {
style: function (feature) { style: function (feature) {
return {color: '#f00'} return {color: '#f00'};
}, },
/**
* enlever les polygones, ne garder que les points
* @param feature
* @param layer
* @returns {boolean}
*/
filter: function (feature, layer) { filter: function (feature, layer) {
let isPolygon = (feature.geometry) && (feature.geometry.type !== undefined) && (feature.geometry.type === 'Polygon') let isPolygon = (feature.geometry) && (feature.geometry.type !== undefined) && (feature.geometry.type === 'Polygon');
if (isPolygon) { if (isPolygon) {
console.log('polygon feature', feature) feature.geometry.type = 'Point';
feature.geometry.type = 'Point' let polygonCenter = L.latLngBounds(feature.geometry.coordinates[0]).getCenter();
let polygonCenter = L.latLngBounds(feature.geometry.coordinates[0]).getCenter() feature.geometry.coordinates = [polygonCenter.lat, polygonCenter.lng];
feature.geometry.coordinates = [polygonCenter.lat, polygonCenter.lng]
} }
return true return true;
}, },
onmoveend: function (event) { onmoveend: function (event) {
// console.log('déplacement terminé') // console.log('déplacement terminé');
}, },
onzoomend: function (event) { onzoomend: function (event) {
supprimerMarqueurs() supprimerMarqueurs();
displayPointsFromApi() displayPointsFromApi();
}, },
onEachFeature: eachFeature, onEachFeature: eachFeature,
}) });
} }
function makePopupOfFeature(feature) { function makePopupOfFeature(feature) {
@ -423,85 +357,62 @@ function makePopupOfFeature(feature) {
} }
function eachFeature(feature, layer) { function eachFeature(feature, layer) {
let link_josm = createJOSMEditLink(feature);
let link_josm = createJOSMEditLink(feature) let popupContent = makePopupOfFeature(feature);
layer.bindPopup(popupContent);
let popupContent = makePopupOfFeature(feature) let outPowerGuessed = utils.guessOutputPowerFromFeature(feature);
layer.bindPopup(popupContent) let color = colorUtils.getColor(feature);
let displayOutPowerGuessed = '? kW';
let outPowerGuessed = utils.guessOutputPowerFromFeature(feature)
let color = colorUtils.getColor(feature)
let displayOutPowerGuessed = '? kW'
if (outPowerGuessed) { if (outPowerGuessed) {
displayOutPowerGuessed = outPowerGuessed + ' kW max' displayOutPowerGuessed = outPowerGuessed + ' kW max';
} }
if (!popupContent) { if (!popupContent) {
popupContent = `<span class="no-data"> Aucune information renseignée, popupContent = `<span class="no-data"> Aucune information renseignée,
<a class="edit-button" href="https://www.openstreetmap.org/edit?editor=remote&node=${feature.properties.id}">ajoutez la dans OpenStreetMap!</a></span>` <a class="edit-button" href="https://www.openstreetmap.org/edit?editor=remote&node=${feature.properties.id}">ajoutez la dans OpenStreetMap!</a></span>`;
} }
// boutons d'itinéraire
let html = ` <a href="https://www.openstreetmap.org/directions?from=&to=${feature.geometry.coordinates[1]},${feature.geometry.coordinates[0]}&engine=fossgis_osrm_car#map=14/${feature.geometry.coordinates[1]}/${feature.geometry.coordinates[0]}" class="navigation-link by-car" title="itinéraire en voiture vers cette station"> 🚗</a><a href="https://www.openstreetmap.org/directions?from=&to=${feature.geometry.coordinates[1]},${feature.geometry.coordinates[0]}&engine=fossgis_osrm_bike#map=14/${feature.geometry.coordinates[1]}/${feature.geometry.coordinates[0]}" class="navigation-link by-car" title="itinéraire en vélo vers cette station">🚴‍♀️</a><a href="https://www.openstreetmap.org/directions?from=&to=${feature.geometry.coordinates[1]},${feature.geometry.coordinates[0]}&engine=fossgis_osrm_foot#map=14/${feature.geometry.coordinates[1]}/${feature.geometry.coordinates[0]}" class="navigation-link by-car" title="itinéraire à pied vers cette station">👠</a> let html = ` <a href="https://www.openstreetmap.org/directions?from=&to=${feature.geometry.coordinates[1]},${feature.geometry.coordinates[0]}&engine=fossgis_osrm_car#map=14/${feature.geometry.coordinates[1]}/${feature.geometry.coordinates[0]}" class="navigation-link by-car" title="itinéraire en voiture vers cette station"> 🚗</a><a href="https://www.openstreetmap.org/directions?from=&to=${feature.geometry.coordinates[1]},${feature.geometry.coordinates[0]}&engine=fossgis_osrm_bike#map=14/${feature.geometry.coordinates[1]}/${feature.geometry.coordinates[0]}" class="navigation-link by-car" title="itinéraire en vélo vers cette station">🚴‍♀️</a><a href="https://www.openstreetmap.org/directions?from=&to=${feature.geometry.coordinates[1]},${feature.geometry.coordinates[0]}&engine=fossgis_osrm_foot#map=14/${feature.geometry.coordinates[1]}/${feature.geometry.coordinates[0]}" class="navigation-link by-car" title="itinéraire à pied vers cette station">👠</a>
<a class="edit-button" href="https://www.openstreetmap.org/edit?editor=id&node=${feature.properties.id}"></a><a class="edit-button josm" data-href="${link_josm}" href="#">JOSM</a> <span class="color-indication" style="background-color: ${color};">${displayOutPowerGuessed}</span><span class="popup-content">${popupContent}</span>` <a class="edit-button" href="https://www.openstreetmap.org/edit?editor=id&node=${feature.properties.id}"></a><a class="edit-button josm" data-href="${link_josm}" href="#">JOSM</a> <span class="color-indication" style="background-color: ${color};">${displayOutPowerGuessed}</span><span class="popup-content">${popupContent}</span>`;
let zoom = map.getZoom() let zoom = map.getZoom();
let radius = 20 let radius = 20;
let opacity = 0.5 let opacity = 0.5;
let ratio_circle = 10 let ratio_circle = 10;
// quand on est loin, montrer d'avantage de couleur, pas le centre
if (zoom < 13) { if (zoom < 13) {
ratio_circle = 5 ratio_circle = 5;
} else if (zoom < 15) { } else if (zoom < 15) {
ratio_circle = 1 ratio_circle = 1;
opacity = 0.25 opacity = 0.25;
} else if (zoom <= 16) { } else if (zoom <= 16) {
ratio_circle = 0.5 ratio_circle = 0.5;
} else if (zoom <= 18) { } else if (zoom <= 18) {
ratio_circle = 0.25 ratio_circle = 0.25;
} }
// console.log('ratio_circle', ratio_circle, feature.properties)
if (!layer._latlng) {
console.error('pas de latlng du layer', layer)
if (lastLatLng) {
layer._latlng = lastLatLng if (!layer._latlng) {
if (lastLatLng) {
layer._latlng = lastLatLng;
} }
} else { } else {
console.log('layer._latlng', layer._latlng) lastLatLng = layer._latlng;
lastLatLng = layer._latlng
} }
if (!outPowerGuessed) { if (!outPowerGuessed) {
radius = radius * ratio_circle radius = radius * ratio_circle;
} else { } else {
radius = outPowerGuessed * ratio_circle radius = outPowerGuessed * ratio_circle;
} }
// if (outPowerGuessed >= 300) {
// radius = 70 * ratio_circle
// } else if (outPowerGuessed >= 200) {
// radius = 60 * ratio_circle
// } else if (outPowerGuessed >= 100) {
// radius = 50 * ratio_circle
// } else if (outPowerGuessed >= 50) {
// radius = 40 * ratio_circle
// } else if (outPowerGuessed >= 20) {
// radius = 30 * ratio_circle
// } else if (outPowerGuessed >= 7) {
// radius = 20 * ratio_circle
// }
let circle = L.circle(layer._latlng, { let circle = L.circle(layer._latlng, {
color: color, color: color,
fillColor: color, fillColor: color,
fillOpacity: opacity, fillOpacity: opacity,
colorOpacity: opacity, colorOpacity: opacity,
radius: radius radius: radius
}).addTo(all_stations_markers) }).addTo(all_stations_markers);
// montrer les détails quand on est proche
// afficher moins de couleur, montrer le centre plus précis
if (zoom > 15) { if (zoom > 15) {
let circle_center = L.circle(layer._latlng, { let circle_center = L.circle(layer._latlng, {
color: 'black', color: 'black',
@ -509,34 +420,22 @@ function eachFeature(feature, layer) {
fillOpacity: 1, fillOpacity: 1,
radius: 0.1 radius: 0.1
}).addTo(all_stations_markers); }).addTo(all_stations_markers);
// if (!outPowerGuessed) {
//
// circle_center.bindTooltip("?", {
// permanent: true,
// className: "my-label",
// offset: [0, 0]
// });
// }
// circle_center.addTo(all_stations_markers);
} }
circle.bindPopup(html);
circle.bindPopup(html)
circle.on({ circle.on({
mouseover: function () { mouseover: function () {
this.openPopup() this.openPopup();
bindEventsOnJosmRemote() bindEventsOnJosmRemote();
}, },
mouseout: function () { mouseout: function () {
// setTimeout(() => this.closePopup(), 15000) // setTimeout(() => this.closePopup(), 15000);
}, },
click: function () { click: function () {
this.openPopup() this.openPopup();
bindEventsOnJosmRemote() bindEventsOnJosmRemote();
}, },
}) });
} }
function makeCssClassFromTags(tags) { function makeCssClassFromTags(tags) {
@ -563,52 +462,46 @@ function getIconFromTags(tags) {
} }
function toggleMinPower(showHighPower) { function toggleMinPower(showHighPower) {
console.log('toggle', showHighPower) showHighPower = !showHighPower;
showHighPower = !showHighPower addFilteredMarkers(showHighPower);
addFilteredMarkers(showHighPower) this.textContent = showHighPower ? 'Montrer puissance haute' : 'Montrer puissance normale';
this.textContent = showHighPower ? 'Montrer puissance haute' : 'Montrer puissance normale'
} }
function addFilteredMarkers(showHighPower) { function addFilteredMarkers(showHighPower) {
allMarkers.clearLayers() // Supprimer les marqueurs existants allMarkers.clearLayers();
console.log('addFilteredMarkers: clear des marqueurs fait') let counter = 0;
let counter = 0
geojsondata.features.forEach(function (feature) { geojsondata.features.forEach(function (feature) {
if (feature.properties.puissance_haute === showHighPower) { if (feature.properties.puissance_haute === showHighPower) {
counter++ counter++;
let marker = L.marker(feature.geometry.coordinates).bindPopup(feature.properties.puissance_haute ? 'Puissance haute' : 'Puissance normale') let marker = L.marker(feature.geometry.coordinates).bindPopup(feature.properties.puissance_haute ? 'Puissance haute' : 'Puissance normale');
allMarkers.addLayer(marker) allMarkers.addLayer(marker);
} }
}) });
console.log('addFilteredMarkers: ', counter)
} }
let isLoading = false let isLoading = false
function loadOverpassQuery() { function loadOverpassQuery() {
// ne pas charger si on recherche déjà
if (!isLoading) { if (!isLoading) {
isLoading = true isLoading = true;
$('#spinning_icon').fadeIn() $('#spinning_icon').fadeIn();
let queryTextfieldValue = $('#query-textfield').val() let queryTextfieldValue = $('#query-textfield').val();
let overpassApiUrl = buildOverpassApiUrl(map, queryTextfieldValue) let overpassApiUrl = buildOverpassApiUrl(map, queryTextfieldValue);
$.get(overpassApiUrl, function (geoDataPointsFromApi) { $.get(overpassApiUrl, function (geoDataPointsFromApi) {
geojsondata = geoDataPointsFromApi geojsondata = geoDataPointsFromApi;
refreshDisplay() refreshDisplay();
$('#spinning_icon').fadeOut() $('#spinning_icon').fadeOut();
$('#message-loading').fadeOut() $('#message-loading').fadeOut();
isLoading = false isLoading = false;
}) // end of the getting from overpass API });
} }
} }
function refreshDisplay() { function refreshDisplay() {
supprimerMarqueurs() supprimerMarqueurs();
console.log('geojsondata', geojsondata) displayPointsFromApi(geojsondata);
displayPointsFromApi(geojsondata)
} }
@ -644,40 +537,34 @@ setCoordinatesOfLeafletMapFromQueryParameters()
$(document).ready(function () { $(document).ready(function () {
bindEventsOnJosmRemote() bindEventsOnJosmRemote();
onMapMoveEnd() onMapMoveEnd();
map.on('moveend', onMapMoveEnd) map.on('moveend', onMapMoveEnd);
$('#spinning_icon').hide() $('#spinning_icon').hide();
// $('#messageLoading').hide()
$('#removeMarkers').on('click', function () { $('#removeMarkers').on('click', function () {
supprimerMarqueurs() supprimerMarqueurs();
}) });
$('#load').on('click', function () { $('#load').on('click', function () {
loadOverpassQuery() loadOverpassQuery();
}) });
$('#toggleSidePanel').on('click', function () { $('#toggleSidePanel').on('click', function () {
$('body').toggleClass('side-panel-open') $('body').toggleClass('side-panel-open');
}) });
// filtres
// boutons de toggle et de cycle de visibilité
//
$('#chercherButton').on('click', function () { $('#chercherButton').on('click', function () {
supprimerMarqueurs() supprimerMarqueurs();
loadOverpassQuery() loadOverpassQuery();
}) });
$('#setRandomView').on('click', function () { $('#setRandomView').on('click', function () {
setRandomView() setRandomView();
loadOverpassQuery() loadOverpassQuery();
}) });
$('#filterUnkown').on('click', function () { $('#filterUnkown').on('click', function () {
console.log('filterUnkown', filterUnkown) display_unknown_max_power_station = cycleVariableState(display_unknown_max_power_station, '#filterUnkown');
display_unknown_max_power_station = cycleVariableState(display_unknown_max_power_station, '#filterUnkown') showActiveFilter(display_unknown_max_power_station, '#filterUnkown');
showActiveFilter(display_unknown_max_power_station, '#filterUnkown') refreshDisplay();
refreshDisplay() });
}) showActiveFilter(display_unknown_max_power_station, '#filterUnkown');
showActiveFilter(display_unknown_max_power_station, '#filterUnkown') });
})
function showActiveFilter(filterVariableName, selectorId) { function showActiveFilter(filterVariableName, selectorId) {
$(selectorId).attr('class', 'filter-state-' + filterVariableName) $(selectorId).attr('class', 'filter-state-' + filterVariableName)
@ -796,12 +683,50 @@ function init() {
}); });
document.getElementById('sendToJOSM').addEventListener('click', () => { document.getElementById('sendToJOSM').addEventListener('click', () => {
editor.sendToJOSM(map) sendToJOSM(map);
.then(() => {
alert('Données envoyées à JOSM avec succès !');
})
.catch(() => {
alert('Erreur : JOSM doit être ouvert avec l\'option "Contrôle à distance" activée');
});
}); });
$('#searchButton').on('click', searchLocation);
$('#shareUrl').on('click', copyCurrentUrl);
document.getElementById('searchButton').addEventListener('click', searchLocation);
}
function copyCurrentUrl() {
const url = window.location.href;
var dummy = document.createElement('input'),
text = window.location.href;
document.body.appendChild(dummy);
dummy.value = text;
dummy.select();
document.execCommand('copy');
document.body.removeChild(dummy);
}
function searchLocation() {
const location = document.getElementById('searchLocation').value;
if (!location) {
alert('Veuillez entrer un lieu à rechercher.');
return;
}
const url = `https://nominatim.openstreetmap.org/search?format=json&q=${encodeURIComponent(location)}`;
fetch(url)
.then(response => response.json())
.then(data => {
if (data.length > 0) {
const place = data[0];
const lat = parseFloat(place.lat);
const lon = parseFloat(place.lon);
map.setView([lat, lon], 13); // Ajustez le niveau de zoom selon vos besoins
} else {
alert('Lieu non trouvé. Veuillez essayer un autre terme de recherche.');
}
})
.catch(error => {
console.error('Erreur lors de la recherche du lieu :', error);
alert('Erreur lors de la recherche du lieu.');
});
} }

View File

@ -56,7 +56,7 @@ const utils = {
} }
} }
} }
console.log('outputPower', outputPower)
feature.properties.outputPower = outputPower feature.properties.outputPower = outputPower
return outputPower return outputPower
}, },

View File

@ -1,7 +1,26 @@
:root {
--background-color: #222;
--text-color: #ddd;
--icon-background: white;
--icon-border: cornflowerblue;
--button-background: #497cd3;
--button-hover-background: #0d377b;
--button-border: #497cd3ff;
--link-color: #38f;
--popup-background: white;
--zoom-message-background: rgba(255, 255, 255, 0.9);
--zoom-message-border: #ff0000;
--color-indication-background: #c0b1b1;
--no-data-border: dodgerblue;
--no-data-link-color: dodgerblue;
--food-marker-color: #fff;
}
html, body { html, body {
height: 100%; height: 100%;
width: 100%; width: 100%;
background: #222; background: var(--background-color);
box-sizing: border-box;
} }
body { body {
@ -31,7 +50,7 @@ p {
#heading { #heading {
background: #000; background: #000;
color: #ddd; color: var(--text-color);
min-height: 5%; min-height: 5%;
height: 4rem; height: 4rem;
width: 100%; width: 100%;
@ -43,11 +62,12 @@ p {
height: 0.25rem !important; height: 0.25rem !important;
display: inline-block; display: inline-block;
margin-right: 1rem; margin-right: 1rem;
background: white; background: var(--icon-background);
border-radius: 100%; border-radius: 100%;
padding: 0.25rem; padding: 0.25rem;
margin-top: -0.5rem; margin-top: -0.5rem;
float: left; float: left;
border-color: var(--icon-border);
} }
.title { .title {
@ -86,16 +106,17 @@ img.leaflet-marker-icon.tag-socket\:type2_yes {
.rounded-button, .rounded-button,
.navigation-link, .navigation-link,
.edit-button { .edit-button {
background: #497cd3; background: var(--button-background);
padding: 0.5em 1em; padding: 0.5em 1em;
border-radius: 2em; border-radius: 2em;
color: white !important; color: white !important;
border: solid 1px #497cd3ff; border: solid 1px var(--button-border);
float: right; float: right;
} }
.side-panel button { .side-panel button {
min-width: 10em; min-width: 15em;
margin-bottom: 0.5em;
} }
.navigation-link { .navigation-link {
@ -114,7 +135,7 @@ img.leaflet-marker-icon.tag-socket\:type2_yes {
button:hover, button:hover,
.edit-button:hover { .edit-button:hover {
background: #0d377b; background: var(--button-hover-background);
border: solid 1px #08285c; border: solid 1px #08285c;
cursor: pointer; cursor: pointer;
} }
@ -139,12 +160,12 @@ button:hover,
} }
a { a {
color: #38f; color: var(--link-color);
} }
.leaflet-control-custom { .leaflet-control-custom {
padding: 1rem; padding: 1rem;
background: white; background: var(--popup-background);
} }
#spinning_icon { #spinning_icon {
@ -226,21 +247,21 @@ a {
} }
.no-data { .no-data {
border-left: 3px solid dodgerblue; border-left: 3px solid var(--no-data-border);
padding: 1em 2rem; padding: 1em 2rem;
min-height: 4rem; min-height: 4rem;
} }
.no-data a { .no-data a {
color: dodgerblue; color: var(--no-data-link-color);
} }
/** /**
marqueurs marqueurs
*/ */
.marker-demo { .marker-demo {
margin-right: 3rem; margin-right: 1rem;
} }
.map-marker-circle-demo { .map-marker-circle-demo {
@ -252,7 +273,7 @@ marqueurs
} }
.color-unknown { .color-unknown {
background: #c0b1b1; background: var(--color-indication-background);
} }
@ -343,7 +364,6 @@ button {
button + button{ button + button{
margin-left: 1rem; margin-left: 1rem;
} }
.filter-group button{ .filter-group button{
padding: 1rem 2rem; padding: 1rem 2rem;
@ -391,7 +411,7 @@ button + button{
left: 0; left: 0;
top: 0; top: 0;
width: 20vw; width: 20vw;
height: 100vh; height: 74vh;
background: white; background: white;
box-shadow: -2px 0 5px rgba(0,0,0,0.2); box-shadow: -2px 0 5px rgba(0,0,0,0.2);
overflow-y: auto; overflow-y: auto;
@ -431,13 +451,13 @@ header{
bottom: 5rem; bottom: 5rem;
left: 50%; left: 50%;
transform: translateX(-50%); transform: translateX(-50%);
background: rgba(255,255,255,0.9); background: var(--zoom-message-background);
padding: 1rem 2rem; padding: 1rem 2rem;
border-radius: 8px; border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.2); box-shadow: 0 2px 4px rgba(0,0,0,0.2);
text-align: center; text-align: center;
z-index: 10; z-index: 10;
border-left: 4px solid #ff0000; border-left: 4px solid var(--zoom-message-border);
animation: rainbow-border 4s linear infinite; animation: rainbow-border 4s linear infinite;
} }
@ -452,6 +472,65 @@ header img{
float: left; float: left;
margin-right: 1rem; margin-right: 1rem;
} }
#map {
z-index: 1;
top: 5.55rem;
}
.side-panel #map{
margin-left: 20vw;
}
.rounded-button {
display: inline-flex;
align-items: center;
justify-content: center;
font-size: 1rem;
cursor: pointer;
transition: background-color 0.3s;
}
.rounded-button:hover {
background-color: #0d377b;
}
/* Style pour mobile */
@media (max-width: 1200px) {
body{
/* border: solid 3px blue; */
}
.side-panel {
margin: 0;
position: static;
width: 95%;
height: auto;
transform: none;
box-shadow: 0 -2px 5px rgba(0,0,0,0.2);
margin-top: 20px;
}
.side-panel.active {
transform: none;
}
.side-panel-open #map,
#map {
margin: 0;
left: 0;
top: 0;
width: 100vw;
height: 90vh;
height: 55vh;
}
header{
position: static;
}
#toggleSidePanel{
right: 4.6rem;
top: 1.3rem;
}
}
@keyframes rainbow-border { @keyframes rainbow-border {
0% { border-left-color: #ff0000; } 0% { border-left-color: #ff0000; }
17% { border-left-color: #ff8000; } 17% { border-left-color: #ff8000; }
@ -462,30 +541,10 @@ header img{
100% { border-left-color: #ff0000; } 100% { border-left-color: #ff0000; }
} }
#map { .search-input {
z-index: 1; width: calc(100% - 40px);
top: 5.55rem; padding: 10px;
} margin-bottom: 10px;
.side-panel #map{ border: 1px solid var(--button-border);
margin-left: 20vw; border-radius: 5px;
}
/* Style pour mobile */
@media (max-width: 768px) {
.side-panel {
position: static;
width: 100%;
height: auto;
transform: none;
box-shadow: 0 -2px 5px rgba(0,0,0,0.2);
margin-top: 20px;
}
.side-panel.active {
transform: none;
}
#map {
margin-right: 0;
}
} }