mirror of
https://forge.chapril.org/tykayn/libre-charge-map
synced 2025-06-20 01:34:43 +02:00
add calcul itineraire et décharge
This commit is contained in:
parent
872d14e17c
commit
da7292e746
8 changed files with 502 additions and 53 deletions
38
index.html
38
index.html
|
@ -141,6 +141,44 @@
|
||||||
la nuit, ou bien où l'on séjourne plus longtemps.
|
la nuit, ou bien où l'on séjourne plus longtemps.
|
||||||
</span>
|
</span>
|
||||||
</p>
|
</p>
|
||||||
|
<div class="filter-battery" id="filterBattery">
|
||||||
|
<h3>Paramètres de la batterie</h3>
|
||||||
|
<p>
|
||||||
|
<label for="battery_capacity">
|
||||||
|
Capacité de la batterie (kWh) :
|
||||||
|
</label>
|
||||||
|
<input type="number" id="battery_capacity" min="20" max="200" value="40" step="1"
|
||||||
|
style="width: 4em;">
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<label for="battery_start_level">
|
||||||
|
Niveau de départ (%) :
|
||||||
|
</label>
|
||||||
|
<input type="number" id="battery_start_level" min="0" max="100" value="90" step="1"
|
||||||
|
style="width: 4em;">
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<label for="consumption_per_km">
|
||||||
|
Consommation (Wh/km) :
|
||||||
|
</label>
|
||||||
|
<input type="number" id="consumption_per_km" min="100" max="300" value="160" step="1"
|
||||||
|
style="width: 4em;">
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<label for="min_battery_level">
|
||||||
|
Niveau minimum recommandé (%) :
|
||||||
|
</label>
|
||||||
|
<input type="number" id="min_battery_level" min="0" max="100" value="15" step="1"
|
||||||
|
style="width: 4em;">
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<label for="charge_to_level">
|
||||||
|
Niveau de charge visé (%) :
|
||||||
|
</label>
|
||||||
|
<input type="number" id="charge_to_level" min="0" max="100" value="80" step="1"
|
||||||
|
style="width: 4em;">
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
<div class="filter-sockets" id="filterSockets">
|
<div class="filter-sockets" id="filterSockets">
|
||||||
|
|
||||||
<h3>Types de prises</h3>
|
<h3>Types de prises</h3>
|
||||||
|
|
466
js/lcm_main.js
466
js/lcm_main.js
|
@ -4,10 +4,18 @@
|
||||||
* lister les bornes trouvées dans la page
|
* lister les bornes trouvées dans la page
|
||||||
* @type {boolean}
|
* @type {boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import {lcm_i18n} from './lcm_i18n.js';
|
||||||
|
|
||||||
|
// Détecter la langue du navigateur
|
||||||
|
const currentLanguage = lcm_i18n.detectLanguage();
|
||||||
|
console.log('Langue détectée:', currentLanguage);
|
||||||
|
|
||||||
import lcm_config from './lcm_config.js'
|
import lcm_config from './lcm_config.js'
|
||||||
import lcm_utils, { valid_qa_message } from './lcm_utils.js'
|
import lcm_utils, { valid_qa_message } from './lcm_utils.js'
|
||||||
import lcm_color_utils from './lcm_color_utils.js'
|
import lcm_color_utils from './lcm_color_utils.js'
|
||||||
import { sendToJOSM, createJOSMEditLink } from './lcm_editor.js'
|
import { sendToJOSM, createJOSMEditLink } from './lcm_editor.js'
|
||||||
|
import routing from './lcm_routing.js'
|
||||||
|
|
||||||
let geojsondata;
|
let geojsondata;
|
||||||
let lastLatLng;
|
let lastLatLng;
|
||||||
|
@ -15,7 +23,16 @@ let searchLocationMarker = null;
|
||||||
let count_hidden_by_filters = 0;
|
let count_hidden_by_filters = 0;
|
||||||
let averageChargeKwh = 26;
|
let averageChargeKwh = 26;
|
||||||
|
|
||||||
|
let routePolyline = null;
|
||||||
|
let routeMarkers = [];
|
||||||
|
let startMarker = null;
|
||||||
|
let endMarker = null;
|
||||||
|
let startCoords = null;
|
||||||
|
let endCoords = null;
|
||||||
|
|
||||||
|
// Déclarer les variables d'itinéraire au début
|
||||||
|
let startItinerary = [0, 0];
|
||||||
|
let endItinerary = [0, 0];
|
||||||
|
|
||||||
// serveurs de tuiles: https://wiki.openstreetmap.org/wiki/Tile_servers
|
// serveurs de tuiles: https://wiki.openstreetmap.org/wiki/Tile_servers
|
||||||
// https://stamen-tiles.a.ssl.fastly.net/toner/{z}/{x}/{y}.png
|
// https://stamen-tiles.a.ssl.fastly.net/toner/{z}/{x}/{y}.png
|
||||||
|
@ -31,28 +48,22 @@ let averageChargeKwh = 26;
|
||||||
let map = L.map('map')
|
let map = L.map('map')
|
||||||
L.control.scale().addTo(map)
|
L.control.scale().addTo(map)
|
||||||
|
|
||||||
|
setCoordinatesOfLeafletMapFromQueryParameters()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* filtres à toggle par des boutons dans la page
|
* filtres à toggle par des boutons dans la page
|
||||||
* à appliquer à chaque rafraîchissement des points geojson
|
* à appliquer à chaque rafraîchissement des points geojson
|
||||||
* TODO: make buttons and filter in refresh circles
|
* TODO: make buttons and filter in refresh circles
|
||||||
*/
|
*/
|
||||||
let filterStatesAvailable = ['hide', 'show', 'showOnly']
|
let filterStatesAvailable = ['hide', 'show', 'showOnly']
|
||||||
|
|
||||||
|
|
||||||
let filters_features = {
|
|
||||||
display_unknown_max_power_station: filterStatesAvailable[1]
|
|
||||||
}
|
|
||||||
let display_type2_sockets = 'show';
|
|
||||||
let display_type2_combo_sockets = 'show';
|
|
||||||
let display_unknown_max_power_station = 'show';
|
let display_unknown_max_power_station = 'show';
|
||||||
let display_alert_cable_missing = 'show';
|
let display_alert_cable_missing = 'show';
|
||||||
let display_known_max_power_station = 'show';
|
|
||||||
let display_type2_combo_sockets_with_cable = 'show';
|
|
||||||
let display_lower_than_50kw = 'show';
|
|
||||||
let display_higer_than_50kw = 'show';
|
|
||||||
let display_lower_than_200kw = 'show';
|
|
||||||
let display_higer_than_200kw = 'show';
|
|
||||||
let display_chelou = 'show'; // les stations avec une valeur suspecte, plus de 400kW
|
|
||||||
|
|
||||||
|
const start = map.getCenter();
|
||||||
|
const startLat = start.lat;
|
||||||
|
const startLon = start.lng;
|
||||||
|
|
||||||
// Ajouter cette fonction avant searchLocation
|
// Ajouter cette fonction avant searchLocation
|
||||||
function moveToLocation(place) {
|
function moveToLocation(place) {
|
||||||
|
@ -198,7 +209,19 @@ function searchLocation() {
|
||||||
.val(index)
|
.val(index)
|
||||||
.text(displayText)
|
.text(displayText)
|
||||||
.data('place', place);
|
.data('place', place);
|
||||||
|
|
||||||
|
// Création du bouton itinéraire
|
||||||
|
const routeBtn = $('<button>')
|
||||||
|
.addClass('route-to-place')
|
||||||
|
.text('Itinéraire '+index)
|
||||||
|
.on('click', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
calculerEtAfficherItineraire(place, 'car');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Ajoute le bouton à côté de l'option (ou dans une div, selon ton HTML)
|
||||||
resultsDropdown.append(option);
|
resultsDropdown.append(option);
|
||||||
|
resultsDropdown.after(routeBtn);
|
||||||
});
|
});
|
||||||
resultsDropdown.show();
|
resultsDropdown.show();
|
||||||
$('.close-results-button').show();
|
$('.close-results-button').show();
|
||||||
|
@ -226,25 +249,62 @@ function setCoordinatesOfLeafletMapFromQueryParameters() {
|
||||||
const lat = urlParams.get('lat');
|
const lat = urlParams.get('lat');
|
||||||
const lng = urlParams.get('lng');
|
const lng = urlParams.get('lng');
|
||||||
const zoom = urlParams.get('zoom');
|
const zoom = urlParams.get('zoom');
|
||||||
|
const startLat = urlParams.get('startLat');
|
||||||
|
const startLng = urlParams.get('startLng');
|
||||||
|
const endLat = urlParams.get('endLat');
|
||||||
|
const endLng = urlParams.get('endLng');
|
||||||
|
const batteryCapacity = urlParams.get('batteryCapacity');
|
||||||
|
const consumptionPerKm = urlParams.get('consumptionPerKm');
|
||||||
|
|
||||||
|
// Mettre à jour les champs de batterie si présents dans l'URL
|
||||||
|
if (batteryCapacity) {
|
||||||
|
$('#battery_capacity').val(batteryCapacity);
|
||||||
|
}
|
||||||
|
if (consumptionPerKm) {
|
||||||
|
$('#consumption_per_km').val(consumptionPerKm);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mettre à jour les coordonnées de départ et d'arrivée si présentes
|
||||||
|
if (startLat && startLng) {
|
||||||
|
startItinerary = [parseFloat(startLat), parseFloat(startLng)];
|
||||||
|
}
|
||||||
|
if (endLat && endLng) {
|
||||||
|
endItinerary = [parseFloat(endLat), parseFloat(endLng)];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialiser la carte avec les coordonnées par défaut
|
||||||
|
if (!map) {
|
||||||
|
map = L.map('map');
|
||||||
|
L.control.scale().addTo(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Si des coordonnées sont fournies dans l'URL, les utiliser
|
||||||
if (lat && lng && zoom) {
|
if (lat && lng && zoom) {
|
||||||
map = map.setView([lat, lng], zoom);
|
map.setView([lat, lng], zoom);
|
||||||
} else {
|
} else {
|
||||||
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();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
calculerEtAfficherItineraire(endItinerary)
|
||||||
|
}
|
||||||
|
// mettre à jour les infos queryparam dans l'url pour passer le lien avec l'état inclus
|
||||||
function updateURLWithMapCoordinatesAndZoom() {
|
function updateURLWithMapCoordinatesAndZoom() {
|
||||||
// Récupère les coordonnées et le niveau de zoom de la carte
|
// Récupère les coordonnées et le niveau de zoom de la carte
|
||||||
const center = map.getCenter()
|
const center = map.getCenter();
|
||||||
const zoom = map.getZoom()
|
const zoom = map.getZoom();
|
||||||
|
|
||||||
// Construit l'URL avec les paramètres de coordonnées et de zoom
|
const batteryCapacity = $('#battery_capacity').val();
|
||||||
const url = `#coords=1&lat=${center.lat}&lng=${center.lng}&zoom=${zoom}`
|
const consumptionPerKm = $('#consumption_per_km').val();
|
||||||
// Met à jour l'URL de la page
|
|
||||||
history.replaceState(null, null, url)
|
// Construit l'URL avec tous les paramètres
|
||||||
updateExternalEditorsLinks()
|
const url = `#coords=1&lat=${center.lat}&lng=${center.lng}&zoom=${zoom}` +
|
||||||
|
`&startLat=${startItinerary[0]}&startLng=${startItinerary[1]}` +
|
||||||
|
`&endLat=${endItinerary[0]}&endLng=${endItinerary[1]}` +
|
||||||
|
`&batteryCapacity=${batteryCapacity}&consumptionPerKm=${consumptionPerKm}`;
|
||||||
|
|
||||||
|
history.replaceState(null, null, url);
|
||||||
|
updateExternalEditorsLinks();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1034,7 +1094,7 @@ function onMapMoveEnd() {
|
||||||
// Calculer la distance en km entre l'ancienne et la nouvelle position
|
// Calculer la distance en km entre l'ancienne et la nouvelle position
|
||||||
const distanceKm = map.distance(center, window.lastKnownPosition) / 1000;
|
const distanceKm = map.distance(center, window.lastKnownPosition) / 1000;
|
||||||
|
|
||||||
console.log('déplacement de ', distanceKm, 'km')
|
// console.log('déplacement de ', distanceKm, 'km')
|
||||||
// Ne mettre à jour que si on s'est déplacé de plus de 2km
|
// Ne mettre à jour que si on s'est déplacé de plus de 2km
|
||||||
if (distanceKm > 2) {
|
if (distanceKm > 2) {
|
||||||
window.lastKnownPosition = center;
|
window.lastKnownPosition = center;
|
||||||
|
@ -1049,21 +1109,16 @@ function onMapMoveEnd() {
|
||||||
// console.log("Recherche des issues Osmose...");
|
// console.log("Recherche des issues Osmose...");
|
||||||
searchOsmoseIssues(map);
|
searchOsmoseIssues(map);
|
||||||
} else {
|
} else {
|
||||||
console.log("Zoom trop faible pour les issues Osmose");
|
// console.log("Zoom trop faible pour les issues Osmose");
|
||||||
osmose_markers.clearLayers();
|
osmose_markers.clearLayers();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setCoordinatesOfLeafletMapFromQueryParameters()
|
|
||||||
|
|
||||||
|
|
||||||
import { lcm_i18n } from './lcm_i18n.js';
|
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
// Charger le service de traduction
|
// Charger le service de traduction
|
||||||
|
|
||||||
// Détecter la langue du navigateur
|
|
||||||
const currentLanguage = lcm_i18n.detectLanguage();
|
|
||||||
console.log('Langue détectée:', currentLanguage);
|
|
||||||
init()
|
init()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1080,7 +1135,7 @@ function updateExternalEditorsLinks() {
|
||||||
const zoom = map.getZoom()
|
const zoom = map.getZoom()
|
||||||
|
|
||||||
mapCompleteLink(center.lat, center.lng, zoom)
|
mapCompleteLink(center.lat, center.lng, zoom)
|
||||||
idLink(center.lat, center.lng, zoom)
|
idEditorLink(center.lat, center.lng, zoom)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1088,10 +1143,10 @@ function mapCompleteLink(lat, lon, zoom) {
|
||||||
$("mapCompleteLink").attr('href', `https://mapcomplete.org/charging_stations?z=${zoom}&lat=${lat}&lon=${lon}`)
|
$("mapCompleteLink").attr('href', `https://mapcomplete.org/charging_stations?z=${zoom}&lat=${lat}&lon=${lon}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
function idLink(lat, lon, zoom) {
|
function idEditorLink(lat, lon, zoom) {
|
||||||
let href = `https://www.openstreetmap.org/edit?editor=id#map=${zoom}/${lat}/${lon}`
|
let href = `https://www.openstreetmap.org/edit?editor=id#map=${zoom}/${lat}/${lon}`
|
||||||
console.log('idlink', href)
|
|
||||||
$("idLink").attr('href', href)
|
$("idEditorLink").attr('href', href)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1211,7 +1266,7 @@ function searchOsmoseIssues(map) {
|
||||||
// Modifier la vérification des stations existantes
|
// Modifier la vérification des stations existantes
|
||||||
const existingStations = [];
|
const existingStations = [];
|
||||||
if (lcm_config.hide_osmose_markers_if_close_to_existing_charging_stations &&
|
if (lcm_config.hide_osmose_markers_if_close_to_existing_charging_stations &&
|
||||||
isChargingStationLayerActive() && // Nouvelle condition
|
isChargingStationLayerActive() &&
|
||||||
geojsondata &&
|
geojsondata &&
|
||||||
geojsondata.features) {
|
geojsondata.features) {
|
||||||
geojsondata.features.forEach(feature => {
|
geojsondata.features.forEach(feature => {
|
||||||
|
@ -1243,13 +1298,21 @@ function searchOsmoseIssues(map) {
|
||||||
osmoseIssuesCount = issuesList.length;
|
osmoseIssuesCount = issuesList.length;
|
||||||
|
|
||||||
issuesList.forEach(issueInfo => {
|
issuesList.forEach(issueInfo => {
|
||||||
if (issueInfo.lat == null || issueInfo.lon == null || !issueInfo.id) {
|
// Vérifier que les coordonnées existent et sont valides
|
||||||
|
if (!issueInfo || issueInfo.lat == null || issueInfo.lon == null || !issueInfo.id) {
|
||||||
|
console.warn("Issue Osmose invalide:", issueInfo);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const lat = parseFloat(issueInfo.lat);
|
const lat = parseFloat(issueInfo.lat);
|
||||||
const lon = parseFloat(issueInfo.lon);
|
const lon = parseFloat(issueInfo.lon);
|
||||||
|
|
||||||
|
// Vérifier que les coordonnées sont des nombres valides
|
||||||
|
if (isNaN(lat) || isNaN(lon)) {
|
||||||
|
console.warn("Coordonnées invalides pour l'issue Osmose:", issueInfo);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Vérifier la distance avec les stations existantes
|
// Vérifier la distance avec les stations existantes
|
||||||
if (lcm_config.hide_osmose_markers_if_close_to_existing_charging_stations) {
|
if (lcm_config.hide_osmose_markers_if_close_to_existing_charging_stations) {
|
||||||
const tooClose = existingStations.some(station => {
|
const tooClose = existingStations.some(station => {
|
||||||
|
@ -1258,14 +1321,13 @@ function searchOsmoseIssues(map) {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (tooClose) {
|
if (tooClose) {
|
||||||
// console.log(`Marqueur Osmose ignoré car trop proche d'une station existante: ${lat},${lon}`);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lcm_config.osmoseIssuesList.push(issueInfo);
|
lcm_config.osmoseIssuesList.push(issueInfo);
|
||||||
|
|
||||||
// Créer le marqueur Osmose si il n'est pas trop proche d'une station existante
|
// Créer le marqueur Osmose
|
||||||
const osmoseMarker = L.circle([lat, lon], {
|
const osmoseMarker = L.circle([lat, lon], {
|
||||||
color: "purple",
|
color: "purple",
|
||||||
fillColor: "purple",
|
fillColor: "purple",
|
||||||
|
@ -1283,6 +1345,10 @@ function searchOsmoseIssues(map) {
|
||||||
const clickedMarker = e.target;
|
const clickedMarker = e.target;
|
||||||
const storedIssueId = clickedMarker.options.issueId;
|
const storedIssueId = clickedMarker.options.issueId;
|
||||||
|
|
||||||
|
if (!storedIssueId) {
|
||||||
|
console.warn("ID d'issue manquant pour le marqueur:", clickedMarker);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const detailUrl = `https://osmose.openstreetmap.fr/api/0.3/issue/${storedIssueId}?langs=auto`;
|
const detailUrl = `https://osmose.openstreetmap.fr/api/0.3/issue/${storedIssueId}?langs=auto`;
|
||||||
console.log("Récupération des détails pour l'issue:", detailUrl);
|
console.log("Récupération des détails pour l'issue:", detailUrl);
|
||||||
|
@ -1295,6 +1361,10 @@ function searchOsmoseIssues(map) {
|
||||||
return response.json();
|
return response.json();
|
||||||
})
|
})
|
||||||
.then(issueDetails => {
|
.then(issueDetails => {
|
||||||
|
if (!issueDetails) {
|
||||||
|
throw new Error("Détails de l'issue non reçus");
|
||||||
|
}
|
||||||
|
|
||||||
// Construire le contenu de la popup avec les détails
|
// Construire le contenu de la popup avec les détails
|
||||||
let popupContent = `<strong>${issueDetails.title?.auto || 'Titre non disponible'}</strong><br>`;
|
let popupContent = `<strong>${issueDetails.title?.auto || 'Titre non disponible'}</strong><br>`;
|
||||||
if (issueDetails.subtitle?.auto) {
|
if (issueDetails.subtitle?.auto) {
|
||||||
|
@ -1308,10 +1378,8 @@ function searchOsmoseIssues(map) {
|
||||||
proposedTags += `<tr><td>${tag.k}</td><td>${tag.v}</td></tr>`;
|
proposedTags += `<tr><td>${tag.k}</td><td>${tag.v}</td></tr>`;
|
||||||
});
|
});
|
||||||
proposedTags += '</table>';
|
proposedTags += '</table>';
|
||||||
// popupContent += `<div class="proposed-tags-container"><h4>Tags proposés :</h4>${proposedTags}</div>`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Construire le lien JOSM /import
|
|
||||||
const josmFixUrl = `http://localhost:8111/import?url=https://osmose.openstreetmap.fr/api/0.3/issue/${storedIssueId}/fix/0`;
|
const josmFixUrl = `http://localhost:8111/import?url=https://osmose.openstreetmap.fr/api/0.3/issue/${storedIssueId}/fix/0`;
|
||||||
|
|
||||||
let josm_buttons = `
|
let josm_buttons = `
|
||||||
|
@ -1320,30 +1388,26 @@ function searchOsmoseIssues(map) {
|
||||||
<a href="https://osmose.openstreetmap.fr/fr/issue/${storedIssueId}" target="_blank" title="Voir les détails de l'alerte sur le site Osmose">Voir sur Osmose</a>
|
<a href="https://osmose.openstreetmap.fr/fr/issue/${storedIssueId}" target="_blank" title="Voir les détails de l'alerte sur le site Osmose">Voir sur Osmose</a>
|
||||||
</div>`;
|
</div>`;
|
||||||
|
|
||||||
popupContent += josm_buttons
|
popupContent += josm_buttons;
|
||||||
// Mettre à jour le contenu de la popup et s'assurer qu'elle est ouverte
|
|
||||||
clickedMarker.setPopupContent(popupContent);
|
clickedMarker.setPopupContent(popupContent);
|
||||||
// clickedMarker.openPopup(); // Rouvrir pour ajuster la taille si nécessaire
|
|
||||||
|
|
||||||
$('#current_station_infos').html(`<div class='island osmose-details'><h2>Analyse Osmose</h2>${josm_buttons}
|
$('#current_station_infos').html(`<div class='island osmose-details'><h2>Analyse Osmose</h2>${josm_buttons}
|
||||||
${proposedTags}
|
${proposedTags}
|
||||||
</div>`);
|
</div>`);
|
||||||
|
|
||||||
// Lier l'événement au bouton JOSM DANS la popup
|
|
||||||
bindEventsOnJosmRemote(clickedMarker.getPopup().getElement());
|
bindEventsOnJosmRemote(clickedMarker.getPopup().getElement());
|
||||||
|
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
console.error("Erreur lors de la récupération des détails de l'issue Osmose:", error);
|
console.error("Erreur lors de la récupération des détails de l'issue Osmose:", error);
|
||||||
clickedMarker.setPopupContent(`Erreur lors du chargement des détails.<br><a href="https://osmose.openstreetmap.fr/fr/issue/${storedIssueId}" target="_blank">Voir sur Osmose</a>`);
|
clickedMarker.setPopupContent(`Erreur lors du chargement des détails.<br><a href="https://osmose.openstreetmap.fr/fr/issue/${storedIssueId}" target="_blank">Voir sur Osmose</a>`);
|
||||||
// clickedMarker.openPopup();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
osmose_markers.addLayer(osmoseMarker);
|
osmose_markers.addLayer(osmoseMarker);
|
||||||
});
|
});
|
||||||
|
|
||||||
updateCounters(); // Mettre à jour l'affichage après le traitement
|
updateCounters();
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
console.error('Erreur détaillée lors de la recherche de la liste des issues Osmose:', error);
|
console.error('Erreur détaillée lors de la recherche de la liste des issues Osmose:', error);
|
||||||
|
@ -1355,11 +1419,19 @@ function searchOsmoseIssues(map) {
|
||||||
|
|
||||||
// Ajouter un écouteur d'événements pour le changement de visibilité des calques
|
// Ajouter un écouteur d'événements pour le changement de visibilité des calques
|
||||||
function init() {
|
function init() {
|
||||||
|
|
||||||
|
|
||||||
bindEventsOnJosmRemote();
|
bindEventsOnJosmRemote();
|
||||||
onMapMoveEnd();
|
onMapMoveEnd();
|
||||||
map.on('moveend', onMapMoveEnd);
|
map.on('moveend', onMapMoveEnd);
|
||||||
$('#spinning_icon').hide();
|
$('#spinning_icon').hide();
|
||||||
|
|
||||||
|
// ... dans la gestion du clic sur un résultat Addok ...
|
||||||
|
$('.route-to-place').on('click', function() {
|
||||||
|
const place = $(this).data('place');
|
||||||
|
calculerEtAfficherItineraire(place, 'car');
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* boutons de changement de filtres et de rechargement des bornes à l'affichage
|
* boutons de changement de filtres et de rechargement des bornes à l'affichage
|
||||||
*/
|
*/
|
||||||
|
@ -1547,4 +1619,310 @@ function updateFilteredStationsCount() {
|
||||||
} else {
|
} else {
|
||||||
$('#filter_max_output_display').after(filterStats);
|
$('#filter_max_output_display').after(filterStats);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
// au clic droit, proposer les points d'itinéraire
|
||||||
|
map.on('contextmenu', function(e) {
|
||||||
|
// Créer un menu contextuel simple
|
||||||
|
let popup = L.popup()
|
||||||
|
.setLatLng(e.latlng)
|
||||||
|
.setContent(`
|
||||||
|
<button onclick="window.setStartMarkerFromPopup([${e.latlng.lat},${e.latlng.lng}])">Choisir comme départ</button><br>
|
||||||
|
<button onclick="window.setEndMarkerFromPopup([${e.latlng.lat},${e.latlng.lng}])">Choisir comme arrivée</button>
|
||||||
|
`)
|
||||||
|
.openOn(map);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Fonctions globales pour le menu contextuel
|
||||||
|
window.setStartMarkerFromPopup = function(latlng) {
|
||||||
|
startItinerary = [latlng[0], latlng[1]]
|
||||||
|
|
||||||
|
setStartMarker({lat: latlng[0], lng: latlng[1]});
|
||||||
|
map.closePopup();
|
||||||
|
if (endItinerary) calculerEtAfficherItineraire();
|
||||||
|
};
|
||||||
|
window.setEndMarkerFromPopup = function(latlng) {
|
||||||
|
setEndMarker({lat: latlng[0], lng: latlng[1]});
|
||||||
|
endItinerary = [latlng[0], latlng[1]]
|
||||||
|
map.closePopup();
|
||||||
|
if (startItinerary) calculerEtAfficherItineraire();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Déclarer une variable globale pour le tracé
|
||||||
|
window.routePolyline = null;
|
||||||
|
window.lastRouteDestination = null;
|
||||||
|
|
||||||
|
// Ajouter cette fonction avant calculerEtAfficherItineraire
|
||||||
|
async function searchChargingStationsAroundPoint(lat, lon, radius = 1500) {
|
||||||
|
const query = `
|
||||||
|
[out:json][timeout:25];
|
||||||
|
(
|
||||||
|
node["amenity"="charging_station"](around:${radius},${lat},${lon});
|
||||||
|
way["amenity"="charging_station"](around:${radius},${lat},${lon});
|
||||||
|
relation["amenity"="charging_station"](around:${radius},${lat},${lon});
|
||||||
|
);
|
||||||
|
out body;
|
||||||
|
>;
|
||||||
|
out skel qt;`;
|
||||||
|
|
||||||
|
const url = `https://overpass-api.de/api/interpreter?data=${encodeURIComponent(query)}`;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(url);
|
||||||
|
const data = await response.json();
|
||||||
|
return data.elements || [];
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erreur lors de la recherche des stations de recharge:', error);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function calculerEtAfficherItineraire(destination, mode = 'car') {
|
||||||
|
// Récupérer le point de départ (centre de la carte)
|
||||||
|
const startLat = startItinerary[0];
|
||||||
|
const startLon = startItinerary[1];
|
||||||
|
const endLat = endItinerary[0];
|
||||||
|
const endLon = endItinerary[1];
|
||||||
|
|
||||||
|
// Récupérer les paramètres de la batterie
|
||||||
|
const batteryCapacity = parseFloat($('#battery_capacity').val()) || 40;
|
||||||
|
const batteryStartLevel = parseFloat($('#battery_start_level').val()) || 90;
|
||||||
|
const consumptionPerKm = parseFloat($('#consumption_per_km').val()) || 160;
|
||||||
|
const minBatteryLevel = parseFloat($('#min_battery_level').val()) || 15;
|
||||||
|
const chargeToLevel = parseFloat($('#charge_to_level').val()) || 80;
|
||||||
|
|
||||||
|
// Construire l'URL OSRM
|
||||||
|
const url = `https://router.project-osrm.org/route/v1/${mode}/${startLon},${startLat};${endLon},${endLat}?overview=full&geometries=geojson&alternatives=false&steps=false`;
|
||||||
|
|
||||||
|
$('#current_station_infos').html('Calcul de l\'itinéraire en cours…');
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(url);
|
||||||
|
const data = await response.json();
|
||||||
|
|
||||||
|
if (!data.routes || !data.routes.length) {
|
||||||
|
$('#current_station_infos').html('Aucun itinéraire trouvé.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const route = data.routes[0];
|
||||||
|
const coords = route.geometry.coordinates.map(c => [c[1], c[0]]); // [lat, lon]
|
||||||
|
|
||||||
|
// Supprimer l'ancien tracé et les marqueurs
|
||||||
|
if (window.routePolyline) {
|
||||||
|
map.removeLayer(window.routePolyline);
|
||||||
|
}
|
||||||
|
if (window.pauseMarkers) {
|
||||||
|
window.pauseMarkers.forEach(marker => map.removeLayer(marker));
|
||||||
|
}
|
||||||
|
if (window.batteryMarkers) {
|
||||||
|
window.batteryMarkers.forEach(marker => map.removeLayer(marker));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Afficher le nouveau tracé sur la carte
|
||||||
|
window.routePolyline = L.polyline(coords, {color: '#0059ce', weight: 5}).addTo(map);
|
||||||
|
// Supprimer le fitBounds qui déplace la vue
|
||||||
|
// map.fitBounds(window.routePolyline.getBounds());
|
||||||
|
|
||||||
|
// Calculer la consommation totale
|
||||||
|
const totalDistanceKm = route.distance / 1000;
|
||||||
|
const totalConsumptionKwh = (totalDistanceKm * consumptionPerKm) / 1000;
|
||||||
|
const batteryStartKwh = (batteryCapacity * batteryStartLevel) / 100;
|
||||||
|
const batteryEndKwh = batteryStartKwh - totalConsumptionKwh;
|
||||||
|
const batteryEndLevel = (batteryEndKwh / batteryCapacity) * 100;
|
||||||
|
|
||||||
|
// Ajouter les marqueurs de niveau de batterie
|
||||||
|
window.batteryMarkers = [];
|
||||||
|
const batteryLevels = [90, 80, 70, 60, 50, 40, 30, 20, 15];
|
||||||
|
let accumulatedDistance = 0;
|
||||||
|
let currentBatteryLevel = batteryStartLevel;
|
||||||
|
|
||||||
|
for (let i = 0; i < coords.length - 1; i++) {
|
||||||
|
const segmentDistance = L.latLng(coords[i]).distanceTo(coords[i + 1]) / 1000; // en km
|
||||||
|
const segmentConsumption = (segmentDistance * consumptionPerKm) / 1000; // en kWh
|
||||||
|
const nextBatteryLevel = ((batteryStartKwh - (accumulatedDistance * consumptionPerKm / 1000)) / batteryCapacity) * 100;
|
||||||
|
|
||||||
|
// Vérifier si on atteint un niveau de batterie à marquer
|
||||||
|
for (const level of batteryLevels) {
|
||||||
|
if (currentBatteryLevel > level && nextBatteryLevel <= level) {
|
||||||
|
const ratio = (level - currentBatteryLevel) / (nextBatteryLevel - currentBatteryLevel);
|
||||||
|
const markerCoords = [
|
||||||
|
coords[i][0] + (coords[i + 1][0] - coords[i][0]) * ratio,
|
||||||
|
coords[i][1] + (coords[i + 1][1] - coords[i][1]) * ratio
|
||||||
|
];
|
||||||
|
|
||||||
|
const batteryMarker = L.marker(markerCoords, {
|
||||||
|
icon: L.divIcon({
|
||||||
|
className: 'battery-marker',
|
||||||
|
html: `🔋 ${level}%`,
|
||||||
|
iconSize: [30, 30]
|
||||||
|
})
|
||||||
|
}).addTo(map);
|
||||||
|
|
||||||
|
let popupContent = `<div class="battery-info">
|
||||||
|
<h3>Niveau de batterie : ${level}%</h3>`;
|
||||||
|
|
||||||
|
if (level <= minBatteryLevel) {
|
||||||
|
popupContent += `<p class="warning">⚠️ Recharge recommandée !</p>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
popupContent += `<p>Distance parcourue : ${(accumulatedDistance + segmentDistance * ratio).toFixed(1)} km</p>
|
||||||
|
<p>Consommation : ${((accumulatedDistance + segmentDistance * ratio) * consumptionPerKm / 1000).toFixed(1)} kWh</p>
|
||||||
|
</div>`;
|
||||||
|
|
||||||
|
batteryMarker.bindPopup(popupContent);
|
||||||
|
window.batteryMarkers.push(batteryMarker);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
accumulatedDistance += segmentDistance;
|
||||||
|
currentBatteryLevel = nextBatteryLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculer le nombre de pauses nécessaires (1 pause toutes les 2 heures)
|
||||||
|
const durationHours = route.duration / 3600;
|
||||||
|
const numberOfPauses = Math.floor(durationHours / 2);
|
||||||
|
const pauseDurationMinutes = 10;
|
||||||
|
const totalPauseTimeMinutes = numberOfPauses * pauseDurationMinutes;
|
||||||
|
|
||||||
|
// Ajouter les marqueurs de pause
|
||||||
|
window.pauseMarkers = [];
|
||||||
|
if (numberOfPauses > 0) {
|
||||||
|
const totalDistance = route.distance;
|
||||||
|
const pauseInterval = totalDistance / (numberOfPauses + 1);
|
||||||
|
|
||||||
|
for (let i = 1; i <= numberOfPauses; i++) {
|
||||||
|
const pauseDistance = pauseInterval * i;
|
||||||
|
let accumulatedDistance = 0;
|
||||||
|
let pauseCoords;
|
||||||
|
|
||||||
|
// Trouver les coordonnées pour cette pause
|
||||||
|
for (let j = 0; j < coords.length - 1; j++) {
|
||||||
|
const segmentDistance = L.latLng(coords[j]).distanceTo(coords[j + 1]);
|
||||||
|
if (accumulatedDistance + segmentDistance >= pauseDistance) {
|
||||||
|
const ratio = (pauseDistance - accumulatedDistance) / segmentDistance;
|
||||||
|
pauseCoords = [
|
||||||
|
coords[j][0] + (coords[j + 1][0] - coords[j][0]) * ratio,
|
||||||
|
coords[j][1] + (coords[j + 1][1] - coords[j][1]) * ratio
|
||||||
|
];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
accumulatedDistance += segmentDistance;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pauseCoords) {
|
||||||
|
// Calculer la distance restante jusqu'à la prochaine pause ou la fin
|
||||||
|
const nextPauseDistance = (i < numberOfPauses) ? pauseInterval : (totalDistance - pauseDistance);
|
||||||
|
const consumptionToNextPause = (nextPauseDistance / 1000) * consumptionPerKm / 1000; // en kWh
|
||||||
|
const batteryLevelNeeded = (consumptionToNextPause / batteryCapacity) * 100 + minBatteryLevel;
|
||||||
|
|
||||||
|
// Calculer le niveau de batterie actuel à ce point
|
||||||
|
const currentBatteryLevel = ((batteryStartKwh - (pauseDistance / 1000 * consumptionPerKm / 1000)) / batteryCapacity) * 100;
|
||||||
|
|
||||||
|
// Rechercher les stations de recharge autour du point de pause
|
||||||
|
const chargingStations = await searchChargingStationsAroundPoint(pauseCoords[0], pauseCoords[1]);
|
||||||
|
|
||||||
|
// Créer le contenu du popup avec les stations trouvées
|
||||||
|
let popupContent = `<div class="pause-info">
|
||||||
|
<h3>Pause recommandée n°${i}</h3>
|
||||||
|
<p>Durée : 10 minutes</p>
|
||||||
|
<p>Niveau de batterie actuel : ${currentBatteryLevel.toFixed(1)}%</p>
|
||||||
|
<p>Niveau de batterie nécessaire : ${batteryLevelNeeded.toFixed(1)}%</p>
|
||||||
|
<p>Distance jusqu'à la prochaine pause : ${(nextPauseDistance / 1000).toFixed(1)} km</p>`;
|
||||||
|
|
||||||
|
if (chargingStations.length > 0) {
|
||||||
|
popupContent += `<div class="charging-stations">
|
||||||
|
<h4>Stations de recharge à proximité (${chargingStations.length}) :</h4>
|
||||||
|
<ul>`;
|
||||||
|
|
||||||
|
chargingStations.forEach(station => {
|
||||||
|
const name = station.tags?.name || 'Sans nom';
|
||||||
|
const operator = station.tags?.operator || 'Opérateur inconnu';
|
||||||
|
const distance = L.latLng(pauseCoords).distanceTo([station.lat, station.lon]).toFixed(0);
|
||||||
|
|
||||||
|
popupContent += `<li>
|
||||||
|
<strong>${name}</strong><br>
|
||||||
|
Opérateur : ${operator}<br>
|
||||||
|
Distance : ${distance} m
|
||||||
|
</li>`;
|
||||||
|
});
|
||||||
|
|
||||||
|
popupContent += `</ul></div>`;
|
||||||
|
} else {
|
||||||
|
popupContent += `<p>Aucune station de recharge trouvée dans un rayon de 1.5 km</p>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
popupContent += `</div>`;
|
||||||
|
|
||||||
|
const pauseMarker = L.marker(pauseCoords, {
|
||||||
|
icon: L.divIcon({
|
||||||
|
className: 'pause-marker',
|
||||||
|
html: '⏸️',
|
||||||
|
iconSize: [30, 30]
|
||||||
|
})
|
||||||
|
}).addTo(map);
|
||||||
|
|
||||||
|
pauseMarker.bindPopup(popupContent);
|
||||||
|
window.pauseMarkers.push(pauseMarker);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Afficher distance, durée, et boutons de mode de transport
|
||||||
|
const distanceKm = (route.distance / 1000).toFixed(1);
|
||||||
|
const durationMin = Math.round(route.duration / 60);
|
||||||
|
const totalDurationMin = durationMin + totalPauseTimeMinutes;
|
||||||
|
|
||||||
|
// Convertir la durée totale en heures et minutes si nécessaire
|
||||||
|
let durationDisplay = '';
|
||||||
|
if (totalDurationMin >= 60) {
|
||||||
|
const hours = Math.floor(totalDurationMin / 60);
|
||||||
|
const minutes = totalDurationMin % 60;
|
||||||
|
durationDisplay = `${hours}h${minutes > 0 ? ` ${minutes}min` : ''}`;
|
||||||
|
} else {
|
||||||
|
durationDisplay = `${totalDurationMin} min`;
|
||||||
|
}
|
||||||
|
|
||||||
|
$('#current_station_infos').html(`
|
||||||
|
<section class="routing">
|
||||||
|
<h2>Itinéraire</h2>
|
||||||
|
<div>Distance : <strong>${distanceKm} km</strong></div>
|
||||||
|
<div>Durée estimée : <strong>${durationDisplay}</strong> (dont ${totalPauseTimeMinutes} min de pause)</div>
|
||||||
|
<div>Nombre de pauses recommandées : <strong>${numberOfPauses}</strong> (10 min toutes les 2h)</div>
|
||||||
|
<div>Niveau de batterie final estimé : <strong>${batteryEndLevel.toFixed(1)}%</strong></div>
|
||||||
|
<div>Consommation totale estimée : <strong>${totalConsumptionKwh.toFixed(1)} kWh</strong></div>
|
||||||
|
<div>
|
||||||
|
<button onclick="calculerEtAfficherItineraire(window.lastRouteDestination, 'car')">🚗 Voiture</button>
|
||||||
|
<button onclick="calculerEtAfficherItineraire(window.lastRouteDestination, 'bike')">🚴 Vélo</button>
|
||||||
|
<button onclick="calculerEtAfficherItineraire(window.lastRouteDestination, 'foot')">🚶 Piéton</button>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
`);
|
||||||
|
|
||||||
|
// Stocker la destination pour recalculer facilement
|
||||||
|
window.lastRouteDestination = destination;
|
||||||
|
} catch (e) {
|
||||||
|
$('#current_station_infos').html('Erreur lors du calcul de l\'itinéraire.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setStartMarker(latlng) {
|
||||||
|
if (startMarker) map.removeLayer(startMarker);
|
||||||
|
startMarker = L.marker(latlng, { draggable: true, icon: L.divIcon({className: 'start-marker', html: '🟢', iconSize: [30, 30]}) }).addTo(map);
|
||||||
|
startCoords = [latlng.lat, latlng.lng];
|
||||||
|
startMarker.on('dragend', function(e) {
|
||||||
|
startCoords = [e.target.getLatLng().lat, e.target.getLatLng().lng];
|
||||||
|
if (endCoords) calculerEtAfficherItineraire();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function setEndMarker(latlng) {
|
||||||
|
if (endMarker) map.removeLayer(endMarker);
|
||||||
|
endMarker = L.marker(latlng, { draggable: true, icon: L.divIcon({className: 'end-marker', html: '🔴', iconSize: [30, 30]}) }).addTo(map);
|
||||||
|
endCoords = [latlng.lat, latlng.lng];
|
||||||
|
endMarker.on('dragend', function(e) {
|
||||||
|
endCoords = [e.target.getLatLng().lat, e.target.getLatLng().lng];
|
||||||
|
if (startCoords) calculerEtAfficherItineraire();
|
||||||
|
});
|
||||||
}
|
}
|
8
js/lcm_routing.js
Normal file
8
js/lcm_routing.js
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
/**
|
||||||
|
* gestion des itinéraires pour libre charge map
|
||||||
|
*/
|
||||||
|
class routing{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default routing
|
|
@ -159,6 +159,7 @@ function compterFeaturesInOpenStreetMapFromFile() {
|
||||||
const nombreFeaturesInOSM = data.elements.length;
|
const nombreFeaturesInOSM = data.elements.length;
|
||||||
|
|
||||||
let countPointsDeChargeOSM = 0;
|
let countPointsDeChargeOSM = 0;
|
||||||
|
let validationErrors = {}
|
||||||
|
|
||||||
// Initialiser le compteur pour chaque tag
|
// Initialiser le compteur pour chaque tag
|
||||||
let tagsCountOSM = {};
|
let tagsCountOSM = {};
|
||||||
|
@ -176,11 +177,15 @@ function compterFeaturesInOpenStreetMapFromFile() {
|
||||||
}
|
}
|
||||||
// Compter les tags présents
|
// Compter les tags présents
|
||||||
if (element.tags) {
|
if (element.tags) {
|
||||||
|
|
||||||
|
let tags = Object.keys(element.tags)
|
||||||
|
|
||||||
lcm_config.tags_to_display_in_popup.forEach(tag => {
|
lcm_config.tags_to_display_in_popup.forEach(tag => {
|
||||||
if (element.tags[tag] !== undefined && element.tags[tag] !== null && element.tags[tag] !== "") {
|
if (element.tags[tag] !== undefined && element.tags[tag] !== null && element.tags[tag] !== "") {
|
||||||
tagsCountOSM[tag]++;
|
tagsCountOSM[tag]++;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -188,7 +193,8 @@ function compterFeaturesInOpenStreetMapFromFile() {
|
||||||
...stats,
|
...stats,
|
||||||
countStationsOSM: nombreFeaturesInOSM,
|
countStationsOSM: nombreFeaturesInOSM,
|
||||||
countPointsDeChargeOSM: countPointsDeChargeOSM,
|
countPointsDeChargeOSM: countPointsDeChargeOSM,
|
||||||
tagsCountOSM
|
tagsCountOSM,
|
||||||
|
validationErrors
|
||||||
};
|
};
|
||||||
} catch (erreur) {
|
} catch (erreur) {
|
||||||
console.error('Erreur lors du traitement du fichier OSM:', erreur.message);
|
console.error('Erreur lors du traitement du fichier OSM:', erreur.message);
|
||||||
|
|
|
@ -3,9 +3,9 @@ overrides leaflet
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
.leaflet-interactive {
|
// .leaflet-interactive {
|
||||||
border: solid 3px white;
|
// border: solid 3px white;
|
||||||
}
|
// }
|
||||||
|
|
||||||
.leaflet-control-layers {
|
.leaflet-control-layers {
|
||||||
&.leaflet-control-layers-toggle {
|
&.leaflet-control-layers-toggle {
|
||||||
|
|
|
@ -700,6 +700,16 @@ header {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.routing{
|
||||||
|
|
||||||
|
.start-marker { font-size: 2em; }
|
||||||
|
.end-marker { font-size: 2em; }
|
||||||
|
.pause-marker { font-size: 2em; }
|
||||||
|
|
||||||
|
.route-color{
|
||||||
|
fill: #0059ce;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@include meta.load-css('_osmose.scss');
|
@include meta.load-css('_osmose.scss');
|
||||||
@include meta.load-css('_recherche.scss');
|
@include meta.load-css('_recherche.scss');
|
||||||
|
|
|
@ -624,6 +624,19 @@ header img {
|
||||||
height: 1rem;
|
height: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.routing .start-marker {
|
||||||
|
font-size: 2em;
|
||||||
|
}
|
||||||
|
.routing .end-marker {
|
||||||
|
font-size: 2em;
|
||||||
|
}
|
||||||
|
.routing .pause-marker {
|
||||||
|
font-size: 2em;
|
||||||
|
}
|
||||||
|
.routing .route-color {
|
||||||
|
fill: #0059ce;
|
||||||
|
}
|
||||||
|
|
||||||
.osmose-marker-drop:hover .osmose-marker-inner {
|
.osmose-marker-drop:hover .osmose-marker-inner {
|
||||||
animation: bounce 0.5s ease infinite;
|
animation: bounce 0.5s ease infinite;
|
||||||
background-color: #9F2BFF;
|
background-color: #9F2BFF;
|
||||||
|
@ -997,10 +1010,6 @@ label:hover .island .checkbox-custom {
|
||||||
/**
|
/**
|
||||||
overrides leaflet
|
overrides leaflet
|
||||||
*/
|
*/
|
||||||
.leaflet-interactive {
|
|
||||||
border: solid 3px white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.leaflet-control-layers.leaflet-control-layers-toggle {
|
.leaflet-control-layers.leaflet-control-layers-toggle {
|
||||||
background: url("img/burger.png");
|
background: url("img/burger.png");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
{"version":3,"sourceRoot":"","sources":["main.scss","_osmose.scss","_recherche.scss","_filters.scss","_mobile.scss","_overrides.scss","_animations.scss","_stats.scss"],"names":[],"mappings":";AAIA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;;;AAKA;EACE;;AAGE;EACE;EACA;;AAKJ;EACE;;;AAMN;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;;AAIJ;EACE;;;AAGF;EACE;EACA;EACA;;;AAGF;AAAA;AAAA;AAAA;EAIE;EACA;EACA;EACA;EACA;;;AAKA;EACE;EACA;;;AAIJ;EACE;EACA;;;AAGF;EACE;EACA;;AAGA;EACE;EACA;;;AAIJ;EACE;;;AAGF;EACE;EACA;EACA;;;AAGF;EAOE;;AANA;EACE;EACA;EACA;;;AAMJ;EACE;;;AAGF;EACE;IACE;;EAGF;IACE;;;AAIJ;EACE;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAIJ;EACE;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAIF;EACE;EACA;EACA;;AAEA;EACE;;;AAIJ;AAAA;AAAA;AAIA;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;AAAA;EAEE;;;AAGF;AAAA;EAEE;;;AAGF;AAAA;EAEE;;;AAGF;AAAA;EAEE;;;AAGF;AAAA;EAEE;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;;AAEA;EACE;;;AAIJ;EACE;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;;;AAIF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;;;AAIA;EACE;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;;;AAIJ;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;;AAEA;EACE;EACA;EACA;;AAGF;EACE;EACA;;;AAIJ;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;;AAIJ;EACE;EACA;EACA;EACA;;AAEA;EACE;EACA;;;AAOF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;;AAIA;EACE;EACA;;;AAKN;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAMA;EACE;EACA;EACA;EACA;EACA;EACA;;;AAIJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAIA;EACE;;;AAIJ;EACE;;AAUE;EACE;EACA;EACA;;AAcJ;EACE;;AAGF;EACE;;AAGF;EACE;EACA;;AAEA;EACE;EACA;EACA;;AAIJ;EACE;;AAGF;EACE;EACA;EACA;EACA;EACA;;AAIA;EACE;EACA;;;AC1rBN;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;;;AAEA;EACE;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;EACA;;;AAKJ;EACE;EACA;EACA;EACA;;;AAEA;EACE;EACA;EACA;EACA;;;AAEA;EACE;;;AAIJ;EACE;EACA;;;AC3DJ;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;;AAEA;EACE;EACA;;;AAEA;EACE;;;AAKN;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;;;AAEA;EACE;EACA;EACA;;;AAGF;EACE;;;AASJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;;ACpEF;EACE;;;AAEA;EACE;EACA;EACA;;;AAGF;EACE;;;AAIJ;EACE;EACA;EACA;EACA;;;AAGF;EACE;EACA;;;AAcF;AAAA;EAEE;EACA;EACA;EACA;EACA;;;AAEA;AAAA;EACE;EACA,OApDS;EAqDT;;;AAGF;AAAA;EAvBA;EACA;EAwBE;EACA;EArBF;EAuBE;EACA;;;AAEA;AAAA;EACE,YA/DK;;;AAmET;AAAA;EACE;EACA;EACA;EACA;EACA;;;AAGF;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EA/CF;;;AAkDE;AAAA;EACE;;;AAIJ;AAAA;EACE,YA/FY;EAgGZ,cAhGY;EAiGZ;;;AAEA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAIJ;AAAA;EACE;EACA;EACA;EACA;;;AAGF;AAAA;EACE;EACA,OAxHS;EAsCX;;;AAsFA;AAAA;EACE;;;AAIA;AAAA;EACE,YAhIK;EAiIL,cAhIW;EAiIX;;;AAGF;AAAA;EACE,OArIW;EAsIX;;;AAMN;EACE;IACE;;EAGF;IACE;;EAGF;IACE;;;AC9JJ;AACA;EACE;IACE;IACA;;EAKA;AAAA;IAEE;IACA;;EAIJ;IACE;;EAGF;IAEE;IACA;IACA;IACA;IACA;IACA;IACA;;EAGF;IACE;IACA;IACA;;EAGF;IACE;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;;EAGF;AACE;;EAGF;IACE;IACA;IACA;IACA;IACA;;EAGF;IACE;;EAGF;AAAA;IAEE;IACA;IACA;IACA;IACA;IACA;;EAIF;IACE;;EAGF;IACE;;EAGF;IACE;IACA;IACA;IACA;IAEA;IACA;IACA;IACA;IACA;;EAIF;IAEE;;;ACrGJ;AAAA;AAAA;AAKA;EACE;;;AAIA;EACE;;;AAGF;EACE;;;AAKF;EACE;;;AAEA;EACE;EACA;;;AAKN;EACE;EACA;;;AAGF;AAEE;EACE;EACA;EACA;EACA;EACA;;;AAEA;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAIJ;EACE;EACA;EACA;EACA;EACA;;;AAEA;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAMN;EAyBE;EACA;EACA;EACA;;;AA1BE;EACE;EACA;EACA;EACA;EACA;EACA;;;AAKF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;;ACnGN;EACE;IACE;;EAGF;IACE;;EAGF;IACE;;EAGF;IACE;;EAGF;IACE;;EAGF;IACE;;EAGF;IACE;;;AAIJ;EAEE;IAEE;;EAGF;IACE;;;ACtCJ;EACE;EACA;EACA;;;AAEA;EACE;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;;;AAKA;EACE;;;AAIJ;EACE;;;AAGF;EACE;EACA;;;AAEA;EACE;EACA;EACA;;;AP6pBN;EACE;EACA","file":"style.css"}
|
{"version":3,"sourceRoot":"","sources":["main.scss","_osmose.scss","_recherche.scss","_filters.scss","_mobile.scss","_overrides.scss","_animations.scss","_stats.scss"],"names":[],"mappings":";AAIA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;;;AAKA;EACE;;AAGE;EACE;EACA;;AAKJ;EACE;;;AAMN;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;;AAIJ;EACE;;;AAGF;EACE;EACA;EACA;;;AAGF;AAAA;AAAA;AAAA;EAIE;EACA;EACA;EACA;EACA;;;AAKA;EACE;EACA;;;AAIJ;EACE;EACA;;;AAGF;EACE;EACA;;AAGA;EACE;EACA;;;AAIJ;EACE;;;AAGF;EACE;EACA;EACA;;;AAGF;EAOE;;AANA;EACE;EACA;EACA;;;AAMJ;EACE;;;AAGF;EACE;IACE;;EAGF;IACE;;;AAIJ;EACE;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAIJ;EACE;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAIF;EACE;EACA;EACA;;AAEA;EACE;;;AAIJ;AAAA;AAAA;AAIA;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;AAAA;EAEE;;;AAGF;AAAA;EAEE;;;AAGF;AAAA;EAEE;;;AAGF;AAAA;EAEE;;;AAGF;AAAA;EAEE;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;;AAEA;EACE;;;AAIJ;EACE;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;;;AAIF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;;;AAIA;EACE;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;;;AAIJ;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;;AAEA;EACE;EACA;EACA;;AAGF;EACE;EACA;;;AAIJ;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;;AAIJ;EACE;EACA;EACA;EACA;;AAEA;EACE;EACA;;;AAOF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;;AAIA;EACE;EACA;;;AAKN;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAMA;EACE;EACA;EACA;EACA;EACA;EACA;;;AAIJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAIA;EACE;;;AAIJ;EACE;;AAUE;EACE;EACA;EACA;;AAcJ;EACE;;AAGF;EACE;;AAGF;EACE;EACA;;AAEA;EACE;EACA;EACA;;AAIJ;EACE;;AAGF;EACE;EACA;EACA;EACA;EACA;;AAIA;EACE;EACA;;;AAMJ;EAAgB;;AAChB;EAAc;;AACd;EAAgB;;AAEhB;EACE;;;ACrsBJ;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;;;AAEA;EACE;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;EACA;;;AAKJ;EACE;EACA;EACA;EACA;;;AAEA;EACE;EACA;EACA;EACA;;;AAEA;EACE;;;AAIJ;EACE;EACA;;;AC3DJ;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;;AAEA;EACE;EACA;;;AAEA;EACE;;;AAKN;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;;;AAEA;EACE;EACA;EACA;;;AAGF;EACE;;;AASJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;;ACpEF;EACE;;;AAEA;EACE;EACA;EACA;;;AAGF;EACE;;;AAIJ;EACE;EACA;EACA;EACA;;;AAGF;EACE;EACA;;;AAcF;AAAA;EAEE;EACA;EACA;EACA;EACA;;;AAEA;AAAA;EACE;EACA,OApDS;EAqDT;;;AAGF;AAAA;EAvBA;EACA;EAwBE;EACA;EArBF;EAuBE;EACA;;;AAEA;AAAA;EACE,YA/DK;;;AAmET;AAAA;EACE;EACA;EACA;EACA;EACA;;;AAGF;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EA/CF;;;AAkDE;AAAA;EACE;;;AAIJ;AAAA;EACE,YA/FY;EAgGZ,cAhGY;EAiGZ;;;AAEA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAIJ;AAAA;EACE;EACA;EACA;EACA;;;AAGF;AAAA;EACE;EACA,OAxHS;EAsCX;;;AAsFA;AAAA;EACE;;;AAIA;AAAA;EACE,YAhIK;EAiIL,cAhIW;EAiIX;;;AAGF;AAAA;EACE,OArIW;EAsIX;;;AAMN;EACE;IACE;;EAGF;IACE;;EAGF;IACE;;;AC9JJ;AACA;EACE;IACE;IACA;;EAKA;AAAA;IAEE;IACA;;EAIJ;IACE;;EAGF;IAEE;IACA;IACA;IACA;IACA;IACA;IACA;;EAGF;IACE;IACA;IACA;;EAGF;IACE;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;;EAGF;AACE;;EAGF;IACE;IACA;IACA;IACA;IACA;;EAGF;IACE;;EAGF;AAAA;IAEE;IACA;IACA;IACA;IACA;IACA;;EAIF;IACE;;EAGF;IACE;;EAGF;IACE;IACA;IACA;IACA;IAEA;IACA;IACA;IACA;IACA;;EAIF;IAEE;;;ACrGJ;AAAA;AAAA;AAUE;EACE;;;AAGF;EACE;;;AAKF;EACE;;;AAEA;EACE;EACA;;;AAKN;EACE;EACA;;;AAGF;AAEE;EACE;EACA;EACA;EACA;EACA;;;AAEA;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAIJ;EACE;EACA;EACA;EACA;EACA;;;AAEA;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAMN;EAyBE;EACA;EACA;EACA;;;AA1BE;EACE;EACA;EACA;EACA;EACA;EACA;;;AAKF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;;ACnGN;EACE;IACE;;EAGF;IACE;;EAGF;IACE;;EAGF;IACE;;EAGF;IACE;;EAGF;IACE;;EAGF;IACE;;;AAIJ;EAEE;IAEE;;EAGF;IACE;;;ACtCJ;EACE;EACA;EACA;;;AAEA;EACE;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;;;AAKA;EACE;;;AAIJ;EACE;;;AAGF;EACE;EACA;;;AAEA;EACE;EACA;EACA;;;APuqBN;EACE;EACA","file":"style.css"}
|
Loading…
Add table
Add a link
Reference in a new issue