APIs, fonctions et DOM Scripting

Cartographie

Dans ce TP nous allons réaliser une application de cartographie, c’est-à-dire afficher une carte dans une page web et la contrôler via des boutons créés par un script. Le but est d’illustrer d’une part l’implémentation de fonctions, d’autre part, l’utilisation d’une API et enfin la possibilité de manipuler la structure de la page par javascript.

Mise en place

Dans un premier temps, nous allons créer une page html simple comprenant un div ayant pour identifiant carte qui servira à contenir la carte. On pourra remplir la partie head de la page pour identifier la page, créer une feuille de style simple et mettre un titre dans notre page web.

Nous devons maintenant inclure les fichiers nécessaires à l’insertion de la carte. Nous allons utiliser la bibliothèque (API) leaflet pour afficher et configurer la carte. Il faut donc lier les fichiers définissant les fonctions et styles utilisés : dans l’entête, ajouter l’appel de la feuille de style https://unpkg.com/leaflet@1.9.3/dist/leaflet.css. En fin de body, ajouter un appel au script https://unpkg.com/leaflet@1.9.3/dist/leaflet.js.

Pour l’affichage de la carte, ses dimensions doivent être précisées. Pour cela, nous allons ajouter un nouveau fichier css dans lequel on mettra les règles donnant via son id, les valeurs de width et height du div précédemment défini.

Enfin, nous allons insérer la carte : après la ligne indiquant le chemin de leaflet.js, nous allons ajouter un script directement dans le fichier html contenant

var map = L.map('carte'); //'carte' : id du div où s'affichera la carte
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
    maxZoom: 19,
    attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
}).addTo(map); //tuile de carte depuis openstreetmap
map.setView([48.6936, 6.1846], 13); //centrer la carte à Nancy, niveau de zoom 13

Dans le code ci-dessus, les L.* indiquent des fonctions de Leaflet.

Nous avons maintenant une carte dynamique (on peut se déplacer avec la souris, zoomer/dézoomer avec la molette…)

Carte et boutons que nous obtiendrons

Ajouter une épingle

Objectif : Mettre un marqueur sur la carte en des coordonnées prédéfinies.

À l’aide de la documentation de l’api, ajouter une épingle sur la carte (avec L.marker). Il faut d’abord créer le marqueur (par exemple dans une variable marque) puis l’ajouter à la carte à l’aide de marque.addTo(map)map est la variable définie plus haut. Nous pouvons, avant d’ajouter l’épingle sur la carte, lui adjoindre un popup d’information qui apparaîtra quand on cliquera sur l’épingle. Si marque est une variable de type marker, on peut utiliser marque.bindPopup(html)html est une chaîne de caractère représentant du code html.

Question : L.marker et marque.bindPopup sont-elles des procédures ou des fonctions ?

Déplacer la carte

Objectif : Créer des boutons (input) dont l’appui changera la vue de la carte.

Nous allons maintenant ajouter des boutons permettant de se déplacer vers des lieux précis.

Dans le fichier html, ajoutons un nouveau div sous celui de la carte. Celui-ci aura pour identifiant boutons.

Dans ce div, créons un bouton nommé Biarritz dont le rôle est d’appeler map.panTo avec un paramètre tableau de nombres contenant 43.4817 et -1.556111.

Créons deux autres boutons pour Nancy (coordonnées 48.6936, 6.1846) et Brest (coordonnées 48.390834, -4.485556).

Notons que nous pouvons créer une variable nancy contenant la localisation de Nancy au lieu d’écrire en double les coordonnées et utiliser cette variable au lieu du tableau de coordonnées dans map.panTo :

var nancy = L.latLng(48.6936, 6.1846)
map.panTo(nancy)

Ajoutons enfin un bouton qui exécutera map.fitBounds([nancy, biarritz, brest]).

Question : map.panTo, map.fitBounds, L.latLng et les attributs onclick des boutons sont-elles des fonctions ou des procédures ?

Marquer un nouveau lieu

Objectif : Ajouter un bouton qui posera un marqueur au centre de la carte.

Il existe une fonction pour obtenir les coordonnées du centre de la carte affichée. Elle renvoie un objet de type LatLng, que l’on peut épingler avec L.marker. Ajouter un bouton Marquer qui va ajouter une épingle au centre de la carte.

Dessiner des lignes sur la carte

Objectif : Dessiner un segment entre deux points de la carte. Puis créer des boutons pour chaque paire de ville qui dessineront le segment entre les deux.

Nous allons maintenant ajouter des boutons pour tracer les chemins entre chaque paire de villes (pour l’instant, il y en a 3). Il va être intéressant de créer des variables brest et biarritz pour ne pas réécrire plusieurs fois les coordonnées. Un chemin pourra être ajouté par l’instruction suivante :

map.addLayer(L.polyline([nancy, biarritz]))

Nous voulons maintenant ajouter Dunkerque et Nice parmi nos villes. Si l’ajout des boutons pour centrer la carte en chacune des villes reste raisonnable (deux lignes à ajouter), les chemins de ville à ville sont trop nombreux pour tous les écrire (10 chemins !). Nous allons donc générer les boutons par un programmes et les ajouter automatiquement dans la page.

Pour cela, nous allons définir une fonction insereBouton prenant 4 arguments : les noms des 2 villes à relier et les variables représentant leur position. Cette fonction va créer un élément input, de type button, ayant une valeur cohérente. On pourra fixer l’attribut onclick en utilisant le fait que les éléments sont des dictionnaires et qu’ils peuvent avoir des fonctions comme valeurs !

bouton["onclick"] = function () {
    map.addLayer(L.polyline([v1, v2]))
}

Ensuite, nous allons mettre les noms et localisations des villes dans deux tableaux, parcourir les paires de villes différentes et pour chaque paire, appeler la fonction insereBouton avec les bons paramètres.

Question : Serait-il possible d’améliorer le code pour ne pas manipuler deux tableaux, un pour les noms, un pour les localisations mais une seule structure ?

Colorier des zones sur la carte

Objectif : Dessiner des polygones.

Il est possible d’ajouter des polygones (c’est-à-dire des polylines fermées et coloriées) sur la carte avec du code ressemblant à ce qui suit :

var polygone = L.polygon([nancy, dunkerque, brest], {color: 'red', fillColor: '#ff5050'})
map.addLayer(polygone)

La fonction L.polygon prend deux arguments : un tableau de L.latLng et un dictionnaire d’options, en particulier celles définissant la couleur de la ligne et celle de l’intérieur du polygone.

Nous devons maintenant générer tous les quadrilatères composés de villes parmi Nancy, Biarritz, Nice, Brest et Dunkerque. Puis ajoutons des cases à cocher permettant d’afficher ou non chacun de ces quadrilatères.