Série : Tutoriels OpenStreetMap
Nous avons parfois besoin d'obtenir, par l'intermédiaire d'un formulaire, la localisation précise d'un lieu, comme dans l'exemple ci-dessous.
Dans ce cas, il sera nécessaire de mettre en place un certain nombre "d'automatisations" afin de rendre ce formulaire simple à utiliser.
Nous ajouterons dans cet article :
- Le placement automatique du marqueur et des coordonnées lors de la saisie d'une adresse
- La possibilité de placer le marqueur en cliquant sur la carte
- La possibilité de déplacer le marqueur
Créer le formulaire
Le formulaire sera créé de façon "classique" en HTML comme ci-dessous
<!-- Remplacer # par votre fichier de traitement du formulaire -->
<form action="#" method="post">
<div>
<label for="adresse">Adresse</label>
<input type="text" name="adresse" id="adresse">
</div>
<div>
<label for="cp">Code postal</label>
<input type="text" name="cp" id="cp">
</div>
<div>
<label for="ville">Ville</label>
<input type="text" name="ville" id="ville">
</div>
<!-- Cette DIV affichera la carte -->
<div id="detailsMap"></div>
<!-- Les champs ci-dessous afficheront la latitude et la longitude -->
<div>
<label for="lat">Latitude</label>
<input type="text" name="lat" id="lat" readonly>
</div>
<div>
<label for="lon">Longitude</label>
<input type="text" name="lon" id="lon" readonly>
</div>
<button>Valider</button>
</form>
La "div" appelée "detailsMap" nous servira à afficher la carte. Nous allons devoir ajouter un peu de CSS pour lui donner une hauteur (obligatoire)
#detailsMap{
height: 400px;
}
Initialiser la carte
La carte pourra être initialisée en utilisant la méthode décrite dans l'article Insérer une carte OpenStreetMap sur votre site en utilisant le code suivant
let mymap // Variable qui permettra de stocker la carte
// On attend que le DOM soit chargé
window.onload = () => {
// Nous initialisons la carte et nous la centrons sur Paris
mymap = L.map('detailsMap').setView([48.852969, 2.349903], 11)
L.tileLayer('https://maps.wikimedia.org/osm-intl/{z}/{x}/{y}.png', {
attribution: 'Carte fournie par Wikimedia',
minZoom: 1,
maxZoom: 20
}).addTo(mymap)
}
A ce moment, la carte est initialisée et centrée sur Paris.
Placer un marqueur "au clic"
Nous allons maintenant permettre à l'utilisateur de placer un marqueur en cliquant sur la carte. Ce marqueur devra pouvoir être déplacé en glisser/déposer et être remplacé lors d'un clic à un autre emplacement de la carte.
L'écouteur d'évènement
Nous allons commencer par ajouter un "écouteur d'évènement" pour détecter le clic sur la carte
// On écoute le clic sur la carte et on lance la fonction "mapClickListen"
mymap.on('click', mapClickListen)
L'ajout du marqueur
La fonction "mapClickListen" sera déclenchée par le clic sur la carte.
Elle devra récupérer les coordonnées du clic, créer un marqueur en conséquence et afficher les coordonnées dans le formulaire
/**
* Cette fonction se déclenche au clic, crée un marqueur et remplit les champs latitude et longitude
* @param {event} e
*/
function mapClickListen(e) {
// On récupère les coordonnées du clic
pos = e.latlng
// On crée un marqueur
addMarker(pos)
// On affiche les coordonnées dans le formulaire
document.querySelector("#lat").value=pos.lat
document.querySelector("#lon").value=pos.lng
}
Nous devons ensuite créer la fonction "addMarker" dont l'objectif est d'afficher le marqueur. Celui-ci devra être supprimé au préalable si il existe déjà afin de ne jamais avoir 2 marqueurs au même instant. Attention à bien penser à le déclarer en variable globale comme la variable "mymap".
/**
* Ajoute un marqueur sur la carte
* @param {*} pos
*/
function addMarker(pos){
// On vérifie si le marqueur existe déjà
if (marqueur != undefined) {
// Si oui, on le retire
mymap.removeLayer(marqueur);
}
// On crée le marqueur aux coordonnées "pos"
marqueur = L.marker(
pos, {
// On rend le marqueur déplaçable
draggable: true
}
)
// On ajoute le marqueur
marqueur.addTo(mymap)
}
Gérer le déplacement du marqueur
Si l'utilisateur veut déplacer le marqueur, il faut penser à mettre à jour les coordonnées inscrites dans les champs latitude et longitude.
Pour ce faire, nous écouterons l'évènement "dragend" qui correspond au moment auquel le bouton de la souris est relâché. A ce moment, nous récupérons les coordonnées et mettons à jour les champs du formulaire.
Nous modifions donc la fonction "addMarker" de cette façon.
/**
* Ajoute un marqueur sur la carte
* @param {*} pos
*/
function addMarker(pos){
// On vérifie si le marqueur existe déjà
if (marqueur != undefined) {
// Si oui, on le retire
mymap.removeLayer(marqueur);
}
// On crée le marqueur aux coordonnées "pos"
marqueur = L.marker(
pos, {
// On rend le marqueur déplaçable
draggable: true
}
)
// On écoute le glisser/déposer et on met à jour les coordonnées
marqueur.on('dragend', function(e) {
pos = e.target.getLatLng();
document.querySelector("#lat").value=pos.lat;
document.querySelector("#lon").value=pos.lng;
});
// On ajoute le marqueur
marqueur.addTo(mymap)
}
Utiliser l'adresse saisie par l'utilisateur
Lors de la saisie de l'adresse, il peut être intéressant de trouver l'emplacement sur la carte et d'y afficher le marqueur.
Dans l'exemple ci-dessous, nous ferons appel au service "Nominatim" pour obtenir les coordonnées GPS correspondant à l'adresse lorsque le champ "ville" perd le focus et a été modifié (évènement "blur")
Voici le code correspondant.
ATTENTION : il conviendra d'ajouter des contrôles de données et d'erreurs Ajax, ce code est le code minimal.
/**
* Récupérer les coordonnées de l'adresse et placer le marqueur
*/
function getCity(){
// On "fabrique" l'adresse complète (des vérifications préalables seront nécessaires)
let adresse = document.querySelector("#adresse").value + ", " + document.querySelector("#cp").value+ " " + document.querySelector("#ville").value;
// On initialise la requête Ajax
const xmlhttp = new XMLHttpRequest
// On détecte les changements d'état de la requête
xmlhttp.onreadystatechange = () => {
// Si la requête est terminée
if(xmlhttp.readyState == 4){
// Si nous avons une réponse
if(xmlhttp.status == 200){
// On récupère la réponse
let response = JSON.parse(xmlhttp.response)
// On récupère la latitude et la longitude
let lat = response[0]['lat']
let lon = response[0]['lon']
// On écrit les valeurs dans le formulaire
document.querySelector("#lat").value= lat;
document.querySelector("#lon").value= lon;
// On crée le marqueur
pos = [lat, lon];
addMarker(pos);
// On centre la carte sur l'adresse
mymap.setView(pos, 11);
}
}
}
// On ouvre la requête
xmlhttp.open('get', `https://nominatim.openstreetmap.org/search?q=${adresse}&format=json&addressdetails=1&limit=1&polygon_svg=1`)
// On envoie la requête
xmlhttp.send();
}
Voilà, ça doit fonctionner, normalement ;-)
Obtenir de l'aide
Pour obtenir de l'aide, vous pouvez accéder au serveur Discord pour une entraide par chat
Catégories : HTML Javascript Tutoriel Live-Coding openstreetmap
Mots-clés : Javascript Ajax Openstreetmap Live-Coding html html5 Formulaires leafletjs