Live Coding : Intégrer OpenStreetMap à un formulaire

27 mars 2020 - : HTML Javascript Tutoriel Live-Coding - : 1 commentaire - Javascript Ajax Openstreetmap Live-Coding html html5

Dernière modification le 28 mars 2020

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.

Capture

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.

/**
 * 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 relaché. 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

Partager

Partager sur Facebook Partager sur Twitter Partager sur LinkedIn

Commentaires

Ecrire un commentaire

Fifilafifi a écrit le 4 mai 2020 à 13:04

Encore un tuto de qualité ... Et utile!! Merci pour tout ;)

Répondre

Ecrire un commentaire