Fiche Javascript : API de cartographie

Objet de la fiche :

État de la fiche


Plan de la fiche :

Avant propos :

Avertissement sur l'API Google

Ce service n'est plus disponible avec google map simplement car ce dernier devient payant et ne fonctionne plus que sur des pages sécurisées de type https.

La démo ci dessous ne fonctionne donc pas pour les raisons précédentes, toutefois vous pourrez consulter le code qui fontionnait avant les restrictions et qui normalement devrait fonctionner si vous respectez les nouvelles règles de Google.

Présentation

Le but est de permettre d'implanter rapidement sur son site une partie localisation basée sur l'API (application programing interface) map de google.
Pour les curieux, il faudra consulter le site de google pour obtenir plus de renseignements sur cette interface, pour afficher des informations complémentaires comme par exemple les pistes cyclabes, des précisions sur certains points particuliers etc.

Intégration

Remarques

5 points principaux de cette intégration :

  • 1 => Le chargement du mécanisme de l'API google,
    <script src="https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=weather"></script>
  • 2 => L'initialisation de l'objet MAP,
    map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
    avec 2 paramètres :
    • l'id de la fenêtre qui va recevoir la carte,
    • les options (position, zoom etc) que l'on souhaite appliquer qui sont à définir dans le tableau (mapOptions).
  • 3 => L'analyse de la réponse à la requête,
    if (status == google.maps.GeocoderStatus.OK)
  • 4 => L'affichage d'informations,
    infowindow = new google.maps.InfoWindow()
  • 5 => La déclaration dans le body du div devant recevoir la cartographie.

Autre solution sans API

Il s'agit là d'une toute petite commande pour se positionner sur la carte de google en fonction de l'adresse renseignée.
C'est simple mais peut être utile si vous voulez à partir de votre site indiquer une localisation.

Exemple


Open-source Leaflet : Configuration de base. Mise en oeuvre

Cette bibliothèque JavaScript moderne et open-source est rapidement devenue très populaire parmi les développeurs en raison de sa flexibilité. Si vous cherchez une liberté totale, c'est une bonne option de se raccorder sur OpenStreetMap, puis de se connecter en utilisant Leaflet.

Ce chapitre va permettre de prendre connaissance de l'initialisation du mode de fonctionnement ainsi que des fonctionnalités de contrôle sur les cartes Leaflet. Il est bien sûr possible d'aller beaucoup plus loin et d'avoir un panneau de contrôle plus complexe intégrant filtres, informations diverses. Cette fiche est faite pour pouvoir démarrer rapidement avec un résultat sur ce type de produit. A vous de l'enrichir à votre guise.

Volontairements les démos ont été codées de façon la plus simple possible afin d'en améliorer la compréhension.

Les démos sont basées sur les documents de référence https://leafletjs.com/reference-1.6.0.html et https://esri.github.io/esri-leaflet/tutorials/

On va commenter étape par étape le code de base pour vous permettre de commencer rapidement sur les bases de Leaflet, puis voir dans les démos le travail avec des marqueurs, des polylines, des popups etc. et le traitement des événements.

Pour la suite nous n'allons pas réécrire le code des l'exemples, mais explicitez chaque action proposée par les démos. Le but étant de préciser quelques syntaxes et objets de base afin que vous puissiez comprendre le mécanisme, et mettre en application par vous même, plus facilement les différentes propriétés, méthodes, et évènements utilisables avec l'API Leaflet.

  • Démarrer
    • Insérer(2) le fichier CCS Leaflet dans la section <head> de la page HTML (balise <link>). Note 1
    • Insérer(2) le fichier Javascript Leaflet aprés le fichier CCS Leaflet toujours dans la section <head> de la page HTML.
    • Définir le style client (balise <style>) et en particulier les dimensions à réserver pour l'affichage de la cartographie (id map dans notre exemple). Attention la carte DOIT avoir une hauteur sinon elle n'apparaît pas dans l'élément.
    • Créer les variables générale de base.
      • Instancier la variable map référence de l'objet
      • Définir la vue avec des coordonnées géographiques de base (ici Paris).
      • Le niveau de zoom.

    • Créer une fonction d'initialisation de la carte dont le contenu est défini dans l'exemple. Dans cette exemple on appelera notre fonction : initMap()
      .
    • Dans la balise <body> déclarer et définir l'attribut onload afin d'exécuter l'initialisation qu'une fois la page entièrement chargée.
    • Dans la partie <body> définir un <div> ou autre (canevas) avec son identifiant (id) pour la réception de la cartographie.

  • Instancier et initialiser la carte
    • En premier lieu on instancie un objet carte en fonction de l’ID DOM d’un élément div et en option un objet littéral avec des options de carte : objet map = L.map(id du div) => map = L.map('map');
    • Ensuite on définit la vue de la carte (centre géographique et zoom) avec éventuellemnt des options d’animation données : setView(initOriginLatLng(3), initZoom);
    • A ce stade on a la table mais pas le couvert !.
      L.tileLayer(URL template,options) va se connecter à un serveur de tiles et nous permettre de charger et afficher les couches de tiles sur la carte.Pour ce projet, nous récupérons ces tiles de Open Street Map.
      • URL template = 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png' (4)
      • options
        • attribution : Chaîne à afficher dans le contrôle d’attribution, par ex. " contributeurs Openstreetmap". Il décrit les données de la couche et est souvent une obligation légale envers les titulaires de droits d’auteur et les fournisseurs de tuiles.
        • minZoom : Agrandissement maximun autorisé.
        • maxZoom : Zoom maximun autorisé.

      Les Tiles sont les fichiers image de la carte. Il existe beaucoup de sites certains payants comme Mapbox, d'autres gratuits ou open sources fournies par OpenStreetMap (ICI), soit par Github(ICI).

    • Reste plus qu'appliquer la méthode addTo(map) pour afficher une belle carte.

  • Note 1 :
    L'attribut integrity est une fonction de sécurité qui permet aux navigateurs de vérifier que les fichiers qu'ils vont chercher sont reçus sans manipulation inattendue. Cela fonctionne en permettant de fournir un hachage cryptographique (« hash ») auquel le fichier récupéré doit correspondre. Lorsqu'un navigateur rencontre un élément <script> ou <link> avec un attribut integrity, avant d'exécuter le script ou avant d'appliquer les styles spécifiés par l'élément <link>, la navigateur doit comparer le script ou la feuille de style à la valeur donnée dans l'attribut integrity.
    Si le script ou la feuille de styles ne correspond pas à la valeur de l'attribut integrity qui lui est associée, alors le navigateur doit refuser d'exécuter le script ou d'appliquer la feuille de style et doit retourner une erreur indiquant que le chargement de la ressource a échoué.
    L'attribut crossorigin permet d'envoyer les informations d'authentification de l'utilisateur avec ou sans certificat : le mot clé anonymous associé à crossorigin indique que les requêtes pour cet élément auront la balise de certificat vide. Le mot clé use-credentials au contraire indiquera que la requête fournira un certificat.
  • Note 2 :
    Pour éviter certains petits problèmes pouvant survenir, veillez à insérer ces 2 fichiers dans l'ordre et après avoir chargé vos propres fichiers javascpt et vos propres feuilles de style.
  • Note 3 :
    Objet ( L.latLng(48.853,2.35) ) représentant un point géographique avec une latitude et une longitude données (et éventuellement l’altitude). Les notations de latitude et de longitude suivantes sont acceptées par toutes les méthodes de la librairie :
    • [50, 30] Exemple setView([50, 30], initZoom);
    • {lon: 30, lat: 50} Exemple setView({lon: 30, lat: 50}, initZoom);
    • {lat: 30, lon: 50} Exemple setView({lat: 50, lng: 30}, initZoom);
    • L.latLng(50, 30) Exemple setView(L.latLng(50, 30), initZoom);
  • Note 4 :
    {z}, {x}, {y} Ces variables indiquent respectivement la valeur de zoom, la coordonnée X du zoom sur notre carte, et la coordonnée Y de notre zoom.
    {s}, pour signaler au serveur que la librairie Leaflet doit fournir des informations complémentaires pour notre carte basés sur l'api des tuiles.




Open-source Leaflet : Gérer les évènements sur la carte (demo 1)

De façon générique : .on('Evènement', function(e){};

Parmi tant d'autres les évènements que l'on active dans la démo (principalement pour le journal) sont :

Evènements Quoi Syntaxes
load disponible lorsque la carte et entièrement chargée. Attention : Cet évènement doit être placé avant setview. Si on le fait aprés la carte sera déjà chargée et on ne recevra pas l'évènement. map.on('load', function(e){});
zoomstart disponible au démarrage d'un zoom. map.on('zoomstart',function(e){});
zoomend disponible à la fin d'un zoom. map.on('zoomend',function(e){});
popupopen disponible dès l'ouverture d'un popup. map.on('popupopen',function(e){});
popupclose disponible dès la fermeture d'un popup. map.on('popupclose',function(e){});
dblclick disponible aprés chaque double click sur la carte. map.on('dblclick',function(e){});
click(1) disponible aprés chaque click sur la carte. map.on('click',function(e){});

Note(1) : L'activation de l'évènement click par lui même ne pose aucun problème, c'est plutot sa désactivation qui a était embêtante.

Je n'ai put résoudre cela qu'avec l'utilisation d'un flag (true ou false) suivant si l'évènement a été activé ou pas, et de la façon suivante :

Open-source Leaflet : Les boutons contrôle de zoom (demo 1)

Propriétés

Le zoom sur la carte peut être initialisé de différentes manières : les boutons de la carte, la roulette de la souris, les touches clavier plus et moins, par double click, par 2 doigts pour les écran tactiles.

Les principales options de zoom
OptionsActions
zoomControl positionné à true ou false pour disposer ou non des boutons de zoom sur la carte. Par défaut à true.
doubleClickZoom zoom sur double click. La valeur de cette option peut être true ou false ou "center" (le double click déclenchera un zoom au centre de la vue en fonction de la position du curseur).
keyboard Zoom par utilisation des touches plus et moins du clavier. Valeurs true (par défaut) ou false
scrollWheelZoom Déclenchement du zoom por la molette de la souris. Valeurs true (par défaut) ou false.

Modes d'initialisation

  • A l'initialisation =>

    map = L.map('map',{..options..}).setView(loc.Paris, initZoom); avec par exemple les options suivantes {zoomControl:false,doubleClickZoom:"center"}

Personnaliser de nouveaux boutons de zoom

Les boutons de contrôle de zoom sont initialisés par défaut, mais on peut facilement ne plus faire apparaitre ces boutons, en créer de nouveaux, les supprimer, les déplacer.

Au départ les boutons de zoom c'est celà =>

Démarrer avec l'option zoomControl à false

Pour cela il faut déclarer l'option zoomControl à false lors de l'instanciation de la carte map = L.map('map', {maxZoom: x,minZoom: y,zoomControl: false)

Créer les boutons avec quelques options

On va utiler la classe L.control.zoom et ses options pour créer de nouveaux boutons de zoom sur la carte.


Style des boutons

On modifier les feuilles de style liées au zoom control


Positionnement des boutons

A partir de son identifiant de création on pourra positionner les boutons par la méthode setPosition("paramètre position");. Le paramètre position peut prendre les valeurs "topleft", "topright", "bottomleft" ou "bottomright" correspondant à chacun des coins de la carte.

Effacement

A partir de son identifiant de création on pourra supprimer les boutons par la méthode remove();.

Résultat

On obtient quelque chose comme celà, un peu plus engageant


Généralités

L'avantage de cette solution est que nous n'utilisons aucune API spécifique.

Pour cela nous allons utiliser Nominatim qui est un moteur de recherche pour les données Openstreetmap. On peut y rechercher un nom ou une adresse (recherche prospective) ou rechercher des données par ses coordonnées géographiques (recherche inverse).

Plusieurs modes de recherche avec leurs options associées sont possibles :

  • /search - recherche par nom (adresse) ou type.
  • /reverse - recherche par coordonnées géographiques.
  • /lookup - rechercher les détails d’adresse pour les objets OSM par leur ID.

Pour plus de détails consultez le site : nominatim.org.

Nous utiliserons (via une connection XMLHttpRequest) le type de format d'URL suivant pour la conversion adresse vers coordonnées géographiques. Dans cet exemple ce sont les coordonnées d'une adresse à Montrouge (rue henri ginoux montrouge) qui sont demandées

https://nominatim.openstreetmap.org/search/?format=json&limit=2&q=avenue henri ginoux montrouge france

Comme paramètres passés par l'url on notera le format : on demande la réponse dans un fichier de type json ?
et limit : qui donne le nombre limite d'adresse à renvoyer à l'utilisateur. En effet si l'adresse est plus ou moins bien renseignée, le serveur renvoie dans le fichier plusieurs informations possibles.
et enfin q qui donne l'adresse elle même.

Données brutes reçues

[{"place_id":108028477,"licence":"Data © OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright","osm_type":"way","osm_id":98888400,"boundingbox":["48.8180197","48.8193267","2.3223094","2.3233936"],"lat":"48.8186535","lon":"2.3228631","display_name":"Avenue Henri Ginoux, Quartier Vieux Montrouge, Montrouge, Antony, Hauts-de-Seine, Île-de-France, France métropolitaine, 92120, France","class":"highway","type":"secondary","importance":0.6},{"place_id":279135444,"licence":"Data © OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright","osm_type":"way","osm_id":776764634,"boundingbox":["48.8167147","48.81704","2.3214366","2.3216293"],"lat":"48.8168304","lon":"2.3215072","display_name":"Avenue Henri Ginoux, Quartier Vieux Montrouge, Montrouge, Antony, Hauts-de-Seine, Île-de-France, France métropolitaine, 92120, France","class":"highway","type":"tertiary","importance":0.6}]

Création du bouton de recherche

Le bouton se compose d'un champ d'entrée de l'adresse, d'un bouton d'activation de la recherche, d'une zone à cliquer de résultats disponibles.

  • layoutRecherche : Définition HTML du bloc de recherche.
  • command : Classe générale du bloc de recherche..searchClass{font-size:10px}
  • topright : positionnement du block (un des coins de l'écran). Valeurs possibles : 'topleft', 'topright', 'bottomleft' , 'bottomright'

On rajoute aussi quelques éléments de style liés à la liste de choix d'adresses proposées par le serveur :

Interrogation du serveur (requête XMLHttpRequest) et exploitation des résultats.

Le mécanisme met en oeuvre 4 fonctions :

  • UseControls pour la génération et l'affichage du block de recherche.
  • addr_search qui interroge, et reçois les données du serveur.
  • decodeRecherche pour décoder et afficher les choix disponibles.
  • onClickResults pour afficher sur la carte le résultat final.

La séquence est la suivante:

Une fois le champ adresse complété, l'appui sur le bouton "Rechercher" active la fonction addr_search("adresse recherchée"); tel que défini dans la variable layoutRecherche. Cette fonction est classique d'une requête XMLHttpRequest que nous avons déjà vue dans une fiche précédente ( ICI ).

La réponse du serveur est récupérée dans le call back sous forme de données JSON que l'on parse pour obtenir une structure de tableau.

Une fois ces résultats obtenus ils sont stockés dans le tableau myArrBack qui va être décodé par la fonction decodeRecherche et affiché sous forme de liste dans la zône results (zône elle aussi préalablement définie dans la variable layoutRecherche).

A l'issue du choix de l'utilisateur la fonction onClickResults est appelée pour finalement générer un marker et ses informations sur le point de la carte recherché.

Open-source Leaflet : Marqueurs


leaflet a un intéressant contrôle qui permet aux utilisateurs de contrôler les couches qu’ils voient sur la carte. Comment l'utiliseret plus :

Il existe deux types de couches :

  • Les couches de base qui sont mutuellement exclusives (une seule peut être visible sur votre carte à la fois) comme les tiles.
  • Les superpositions, qui sont toutes les autres choses que vous mettez sur les couches de base.

Application au projet de site web



Respectons la propriété intellectuelle