Suite

Cliquez sur Événements avec Leaflet et geoJSON


Comment attacher un événement click à un geoJSON qui exécute ensuite une fonction Ajax lorsqu'on clique dessus. j'ai regardé dansonEachFeaturemais cela s'exécute lorsque le geoJSON est chargé, pas lorsqu'on clique dessus, exécutant ainsi une tonne d'appels ajax !


Tu étais sur la bonne voie aveconEachFeature.

C'est juste que vous devez lier l'événement en cliquant sur chaque élément.

Voir ci-dessous (testé)

function whenClicked(e) { // e = event console.log(e); // Vous pouvez faire votre déclaration d'appel ajax ici //$.ajax(… } function onEachFeature(feature, layer) { //bind click layer.on({ click: whenClicked }); } geojson = L.geoJson(your_data, { style : style, onEachFeature : onEachFeature }).addTo(map);

Vous pouvez le faire avec un peu moins de code que la version de ThomasG77 :

function onEachFeature(feature, layer) { //lier click layer.on('click', function (e) { // e = event console.log(e); // Vous pouvez faire votre déclaration d'appel ajax ici //$ .ajax(… }); } geojson = L.geoJson(your_data, { style: style, onEachFeature: onEachFeature }).addTo(map);

juste une autre façon en tant que fonction en ligne

geojson = L.geoJson(your_data, { style: style, onEachFeature: function onEachFeature(feature, layer) { layer.on('mouseover', function (e) { // e = event console.log(e); // Vous pouvez faire votre déclaration d'appel ajax ici //$.ajax(… });}).addTo(map);

Un projet parallèle - Une carte interactive des parkings d'Innsbruck

Lorsque j'ai récemment déménagé à Innsbruck, j'ai remarqué qu'il n'y avait pas de carte interactive pour le système de stationnement disponible. La durée pendant laquelle vous pouvez garer votre voiture dépend de la zone dans laquelle se trouve votre voiture. Il y a 20 zones de stationnement et elles sont définies par leurs rues adjacentes dans la ville. Innsbruck est très dense et le stationnement est toujours un sujet brûlant. J'ai donc pensé qu'avoir une carte interactive permet de trouver plus facilement des zones où vous pouvez laisser votre voiture plus longtemps, même si vous n'êtes pas si familier avec les noms des rues. La ville d'Innsbruck propose les données SIG sur le portail de données ouvertes d'Autriche, ce qui a facilité la mise en œuvre d'une telle carte. J'ai utilisé les technologies suivantes pour créer cette carte :

    pour le rendu des données de plan de rue ouvertes pour les éléments interactifs pour les données pour la mise en page d'une seule page pour la section des commentaires

Le code source est disponible sur mon compte Github. La mise en œuvre est disponible ici et également sur le portail autrichien de données ouvertes.


Symboliser les couches vectorielles dans Leaflet

Lorsque vous importez des jeux de données vectorielles à dessiner par le navigateur, vous devrez peut-être travailler pour définir le symbole qui dessinera l'entité. Avec des formats de données tels que GeoJSON qui ne contiennent aucune information de style, vous n'obtenez pas un style prêt à l'emploi comme vous le feriez si vous veniez de demander une image au serveur. Si vous ne définissez pas de symbole pour vos graphiques, vous verrez probablement le symbole par défaut de votre API.

Dans Leaflet, il est courant de définir des styles dans les fonctions. Cela les rend faciles à réutiliser. Voici un exemple de la façon dont vous pouvez configurer un style et l'appliquer à une couche GeoJSON. Cet exemple montre des jardins urbains sous forme de polygones :

Notez que les propriétés incluent la couleur de remplissage, l'opacité du remplissage (qui contrôle la transparence), la couleur du trait et l'épaisseur du trait. Les couleurs sont définies en utilisant la notation hexadécimale. Dans ce cas, le symbole est un remplissage magenta avec un contour violet (Désolé ! Je voulais qu'il ressorte. ). Lorsque vous écrivez votre propre code, utilisez un sélecteur de couleurs en ligne pour obtenir les valeurs hexadécimales des couleurs souhaitées.

Vous pouvez voir une liste des propriétés de style vectoriel de Leaflet en lisant la documentation sur les options de chemin. Vous devriez être capable d'accomplir la plupart de ce que vous voulez faire en utilisant des exemples de travail et un peu d'expérimentation.

L'avantage de dessiner des calques vectoriels dans le navigateur est que vous pouvez rapidement modifier le style en réponse à certains événements. Par exemple, vous pouvez modifier la couleur d'un seul symbole lorsqu'un utilisateur clique dessus. À l'aide de Leaflet, vous pouvez définir différents styles et les connecter à des événements cartographiques.

Le code ci-dessous montre comment une carte de style peut être utilisée pour "mettre en évidence" une caractéristique du jardin lorsqu'on clique dessus. Le jardin sélectionné deviendrait un remplissage bleu :

Ne vous inquiétez pas de l'exécution de ce code maintenant, car vous utiliserez un code presque identique dans la procédure pas à pas de la leçon dans un exemple fonctionnel. Faites juste attention aux modèles de code et à ce qui se passe dans chaque ligne.

Tout d'abord, créez des fonctions pour définir les styles non sélectionnés et sélectionnés :

Créez ensuite la couche GeoJSON et ajoutez des fonctions pour écouter les événements de clic sur les entités GeoJSON et la carte elle-même. Le code ci-dessous contient une variable nommée selection qui contient l'entité actuellement sélectionnée. L'expression if (sélection) vérifie s'il y a une caractéristique sélectionnée. L'expression e.target signifie "la fonctionnalité sur laquelle on vient de cliquer". Remarquez comment la méthode resetStyle peut redéfinir le style d'un calque à sa forme d'origine, et la méthode setStyle peut changer le style d'une entité en quelque chose de nouveau.

Un utilisateur de carte devrait maintenant pouvoir cliquer sur n'importe quel jardin et le voir surligné en bleu. Lorsque l'utilisateur clique sur le jardin, il revient à son symbole magenta d'origine.

Pour résumer cette partie de la leçon, les couches vectorielles dessinées par le navigateur nécessitent un peu plus de travail de la part du développeur, car le développeur doit définir les symboles. Cependant, ce travail s'accompagne d'une variété d'options d'interactivité qui ne seraient pas possibles avec des tuiles d'images pixellisées ou des calques dessinés par le serveur. Bien que la fonctionnalité de resymbolisation au clic semble rudimentaire, pensez à la difficulté (sinon pure futilité) d'obtenir ce type d'effet avec un WMS ou une couche de tuiles rastérisées.

Cette section de la leçon a traité des symboles uniformes pour chaque entité de la couche (à l'exception de l'entité sélectionnée occasionnellement), cependant, Leaflet vous permet d'aller plus loin en définissant des classifications de style basées sur des valeurs attributaires. Cela ouvre la porte aux cartes choroplèthes, aux symboles proportionnels, etc. Certaines de ces techniques seront abordées dans la leçon 8.

Permettre aux développeurs non formés aux principes cartographiques de sélectionner des symboles cartographiques peut présenter certains défis en soi. Il peut être judicieux de demander au développeur de consulter un cartographe afin de déterminer les largeurs, les couleurs et les remplissages les plus appropriés pour les symboles vectoriels.


Géographique

Ce chapitre examine l'approche de D3 pour le rendu des informations géographiques.

A titre d'exemple, le globe ci-dessous est dessiné à l'aide de D3. Un fichier GeoJSON est chargé et D3 est utilisé pour projeter les données géographiques et les dessiner sur un élément Canvas :

L'approche de D3 diffère des méthodes dites raster telles que Leaflet et Google Maps. Ces caractéristiques de la carte de pré-rendu sous forme de tuiles d'image et ceux-ci sont chargés à partir d'un serveur Web et rassemblés dans le navigateur pour former une carte.

Typiquement les demandes D3 informations géographiques vectorielles sous la forme de GeoJSON et le rend en SVG ou Canvas dans le navigateur.

Les cartes matricielles ressemblent souvent davantage à des cartes imprimées traditionnelles où de nombreux détails (par exemple, noms de lieux, routes, rivières, etc.) peuvent être affichés sans impact sur les performances. Cependant, le contenu dynamique tel que l'animation et l'interaction est plus facilement mis en œuvre en utilisant une approche vectorielle. (Il est également assez courant de combiner les deux approches.)

Concepts de cartographie D3

Les 3 concepts clés pour comprendre la création de cartes à l'aide de D3 sont :

  • GeoJSON (un format basé sur JSON pour spécifier des données géographiques)
  • projections (fonctions qui convertissent les coordonnées latitude/longitude en coordonnées x & y)
  • générateurs de chemins géographiques (fonctions qui convertissent les formes GeoJSON en chemins SVG ou Canvas)

GeoJSON

GeoJSON est une norme de représentation des données géographiques au format JSON et la spécification complète se trouve sur geojson.org.

Voici un objet GeoJSON typique :

Dans l'objet ci-dessus, il y a une FeatureCollection contenant un tableau de 3 fonctionnalités :

Chaque caractéristique se compose de géométrie (polygones simples dans le cas des pays et un point pour Tombouctou) et Propriétés.

Les propriétés peuvent contenir des informations sur la fonctionnalité telles que le nom, l'identifiant et d'autres données telles que la population, le PIB, etc.

D3 s'occupe de la plupart des détails lors du rendu de GeoJSON, vous n'avez donc besoin que d'une compréhension de base de GeoJSON pour commencer avec la cartographie D3.

Projections

Une fonction de projection prend une coordonnée de longitude et de latitude (sous la forme d'un tableau [lon, lat] ) et la transforme en une coordonnée x et y :

Les mathématiques de projection peuvent devenir assez complexes, mais heureusement, D3 fournit un grand nombre de fonctions de projection.

Par exemple, vous pouvez créer une fonction de projection équirectangulaire en utilisant :

Nous examinerons les projections plus en détail plus tard.

Générateurs de chemins géographiques

Un générateur de chemin géographique est une fonction qui prend un objet GeoJSON et le convertit en une chaîne de chemin SVG. (En fait, c'est juste un autre type de générateur de forme.)

Vous pouvez créer un générateur à l'aide de la méthode .geoPath et le configurer avec une fonction de projection :

Comme d'habitude avec les générateurs de formes, la chaîne de chemin générée est utilisée pour définir l'attribut d sur un élément de chemin SVG.

Mettre tous ensemble

Étant donné certains GeoJSON, une fonction de projection et un générateur de chemin géographique vous pouvez créer une carte de base :

geoJson.features est un ensemble de fonctionnalités. Ce tableau est joint aux éléments de chemin. L'attribut d est défini à l'aide de la fonction geoGenerator . Celui-ci reçoit une caractéristique comme premier paramètre et génère une chaîne de chemin.

La dernière ligne peut sembler magique mais équivaut à :

Dans ce cas, le paramètre d est une entité GeoJSON.

Pour simplifier les choses, GeoJSON dans l'exemple ci-dessus n'utilise que quelques coordonnées pour définir les frontières du pays.

L'exemple ci-dessus montre l'essence de la création de cartes à l'aide de D3 et je recommande de passer du temps à comprendre chaque concept (GeoJSON, projections et générateurs géographiques) et comment ils s'emboîtent.

Maintenant que nous avons couvert les bases, nous allons examiner chaque concept plus en détail.

GeoJSON

GeoJSON est une structure basée sur JSON pour spécifier des données géographiques. Le plus souvent, il est converti à partir de données de fichiers de formes (un format de données vectorielles géospatiales largement utilisé dans le domaine des SIG) à l'aide d'outils tels que mapshaper, ogr2ogr, shp2json ou QGIS.

Natural Earth est une source populaire de fichiers de formes de carte du monde et si vous débutez, je vous recommande d'essayer mapshaper pour importer des fichiers de formes et les exporter au format GeoJSON. Il peut également filtrer par propriétés (par exemple, si vous vouliez filtrer les pays par continent). Pour un examen plus approfondi de la conversion, consultez le didacticiel Let's Make a Map de Mike Bostock.

Vous pouvez créer des cartes sans comprendre la spécification GeoJSON dans les moindres détails, car des outils tels que mapshaper et D3 font un très bon travail d'abstraction des détails. Cependant, si vous souhaitez comprendre GeoJSON plus en profondeur, je vous recommande de consulter la spécification officielle.

Jusqu'à présent, nous avons intégré un objet GeoJSON dans nos fichiers d'exemple. En pratique, le GeoJSON serait dans un fichier séparé et chargé à l'aide d'une requête ajax. Nous couvrons les requêtes plus en détail dans le chapitre sur les requêtes, mais pour le reste de ce chapitre, nous chargerons un fichier GeoJSON en utilisant :

Il convient de mentionner TopoJSON qui est une autre norme basée sur JSON pour décrire les données géographiques et a tendance à entraîner des tailles de fichier considérablement plus petites. Cela nécessite un peu plus de travail à utiliser, et nous ne le traitons pas dans ce chapitre. Cependant, pour plus d'informations, consultez la documentation.

Projections

Il existe de nombreuses (sinon infinies) façons de convertir (ou de « projeter ») un point sur une sphère (par exemple la terre) en un point sur une surface plane (par exemple un écran) et les gens ont écrit d'innombrables articles (comme celui-ci ) sur les avantages et les inconvénients des différentes projections.

En bref, il n'y a pas de projection parfaite car chaque projection déformera la forme, la surface, la distance et/ou la direction. Le choix d'une projection consiste à choisir la propriété que vous ne voulez pas déformer et à accepter qu'il y ait une distorsion dans les autres propriétés (ou choisissez une projection qui vise une approche équilibrée). Par exemple, s'il est important que la taille des pays soit représentée avec précision, choisissez une projection qui s'efforce de préserver la superficie (probablement au détriment de la forme, de la distance et de la direction).

D3 a un certain nombre de projections de base qui devraient couvrir la plupart des cas d'utilisation :

  • geoAzimuthalEqualArea
  • géoAzimutaleÉquidistante
  • géoGnomonique
  • géoOrthographique
  • géoStéréographique
  • géoAlbers
  • geoConicConformal
  • geoConicEqualArea
  • géoConiqueÉquidistante
  • géoÉquirectangulaire
  • géoMercator
  • geoTransverseMercator

Certaines projections préservent la zone (par exemple, geoAzimuthalEqualArea & geoConicEqualArea ), d'autres la distance (par exemple, geoAzimuthalEquidistant & geoConicEquidistant ) et d'autres angles relatifs (par exemple, geoEquirectangular & geoMercator ). Pour une discussion plus approfondie des avantages et des inconvénients de chaque projection, essayez des ressources telles que les pages de projection cartographique de Carlos A. Furuti.

La grille ci-dessous montre chaque projection centrale sur une carte du monde avec une grille de longitude/latitude et des cercles de rayon égal.

Fonctions de projection

Une fonction de projection prend en entrée [longitude, latitude] et génère une coordonnée de pixel [x, y] .

Attention à bien noter l'ordre des longitudes et latitudes dans le tableau ci-dessus !

Vous êtes libre d'écrire vos propres fonctions de projection, mais il est beaucoup plus simple de demander à D3 d'en créer une pour vous. Pour ce faire, choisissez une méthode de projection (par exemple d3.geoAzimuthalEqualArea ), appelez-la et elle renverra une fonction de projection :

Les projections de base ont des fonctions de configuration pour définir les paramètres suivants :

échelleFacteur d'échelle de la projection
centreCentre de projection [longitude, latitude]
TraduireEmplacement des pixels [x,y] du centre de projection
tournerRotation de la projection [lambda, phi, gamma] (ou [lacet, tangage, roulis])

La signification précise de chaque paramètre dépend des mathématiques derrière chaque projection, mais de manière générale :

  • l'échelle spécifie le facteur d'échelle de la projection. Plus le nombre est élevé, plus la carte est grande.
  • centre spécifie le centre de projection (avec un tableau [lon, lat])
  • translate spécifie où le le centre de projection est situé sur l'écran (avec un tableau [x, y])
  • rotation spécifie le rotation de la projection (avec un tableau [λ, φ, γ]) où les paramètres correspondent respectivement au lacet, tangage et roulis :

Par exemple, vous pouvez créer et configurer une fonction de projection telle que Tombouctou soit centrée sur une carte 960x500 en utilisant :

Pour avoir une idée du comportement de chaque paramètre, utilisez l'explorateur de projection ci-dessous. Les cercles et la grille (à rayon égal) vous permettent d'évaluer la distorsion de la surface et de l'angle de la projection.

.inverser()

Vous pouvez convertir une coordonnée de pixel [x, y] en un tableau longitude/latitude à l'aide de la méthode .invert() de la projection :

Raccord

Étant donné un objet GeoJSON, la méthode .fitExtent() d'une projection définit le échelle et Traduire de telle sorte que la géométrie s'insère dans une boîte englobante donnée :

Le premier argument de .fitExtent est un tableau contenant deux coordonnées : le point en haut à gauche ( [x, y] ) du cadre englobant et la taille ( [largeur, hauteur] ) du cadre englobant. Le deuxième argument est un objet GeoJSON.

Dans l'exemple ci-dessous, l'élément canvas a un arrière-plan gris clair et le cadre de délimitation dans lequel nous insérons le geoJSON est représenté par un contour en pointillé. Le code suivant est utilisé pour ajuster la géométrie dans la boîte englobante :

Si le coin supérieur gauche de votre cadre de délimitation est à [0, 0], vous pouvez omettre la coordonnée supérieure gauche et fournir simplement la largeur et la hauteur :

Générateurs de chemins géographiques

Un générateur de chemin géographique est une fonction qui transforme GeoJSON dans une chaîne de chemin SVG (ou dans les appels d'éléments canvas) :

Vous créez le générateur en utilisant d3.geoPath() et devez configurer son type de projection :

Vous pouvez maintenant utiliser le générateur pour vous aider à créer une carte SVG ou canevas. L'option SVG est un peu plus facile à implémenter, en particulier lorsqu'il s'agit d'interaction avec l'utilisateur (car des gestionnaires d'événements et des états de survol peuvent être ajoutés).

L'approche canvas nécessite un peu plus de travail mais est généralement plus rapide à rendre (et plus efficace en mémoire).

Rendu SVG

    un tableau de fonctionnalités GeoJSON aux éléments de chemin SVG
  • mettre à jour l'attribut d de chaque élément de chemin à l'aide du générateur de chemin géographique

geoJson.features est un ensemble de fonctionnalités. Ce tableau est joint aux éléments de chemin. L'attribut d est défini à l'aide de la fonction geoGenerator . Celui-ci reçoit une caractéristique comme premier paramètre et génère une chaîne de chemin.

Rendu sur toile

Pour effectuer un rendu dans un élément de canevas, vous passez l'élément DOM de canevas dans la méthode de contexte du générateur :

La méthode .node renvoie le premier élément DOM d'une sélection.

Vous commencez ensuite un chemin de canevas (en utilisant context.beginPath() ) et appelez geoGenerator qui produira les appels de canevas nécessaires :

Lignes et arcs

Le générateur de chemin géographique est suffisamment intelligent pour faire la distinction entre les entités polygonales (généralement pour les zones géographiques) et ponctuelles (généralement pour les emplacements lon/lat). Comme on peut le voir dans les exemples ci-dessus, il rend les polygones sous forme de segments de ligne et les points sous forme d'arcs.

Vous pouvez définir le rayon des cercles en utilisant .pointRadius() :

Géométrie du chemin

Le générateur de chemin géographique peut également être utilisé pour calculer le surface (en pixels), centre de gravité, cadre de délimitation et longueur du trajet (en pixels) d'une entité GeoJSON projetée :

Cet exemple montre la superficie et la longueur d'un chemin survolé. Il dessine également le centroïde et la boîte englobante du chemin :

Formes

Si vous devez ajouter des lignes et/ou des cercles à une carte, vous pouvez ajouter des fonctionnalités au GeoJSON.

Des lignes peuvent être ajoutées en tant que fonction LineString et seront projetées dans de grands arcs (c'est-à-dire la distance la plus courte à travers la surface du globe).

Voici un exemple où une ligne est ajoutée entre Londres et New York :

Les entités circulaires peuvent être générées à l'aide de d3.geoCircle() . Cela crée un générateur de cercle qui renvoie un objet GeoJSON représentant un cercle.

Généralement, le centre ( [lon, lat] ) et le rayon (en degrés) sont définis :

Une grille GeoJSON de lignes de longitude et de latitude (appelée graticule) peut être générée à l'aide de d3.graticule() . Cela crée un générateur de graticules qui renvoie un objet GeoJSON représentant les graticules :

(Voir la documentation officielle pour des informations détaillées sur la configuration du graticule.)

Voici un exemple où une ligne, un cercle et des graticules sont ajoutés à une carte :

Géométrie sphérique

Il existe une poignée de méthodes D3 qui peuvent être utiles de temps en temps. Le premier de ces .geoArea() , .geoBounds() , .geoCentroid() , .geoDistance() et geoLength() sont similaires aux méthodes de géométrie de chemin décrites ci-dessus mais fonctionnent dans l'espace sphérique.

Interpolation

La méthode d3.geoInterpolate() crée une fonction qui accepte les entrées entre 0 et 1 et interpole entre deux emplacements [lon, lat] :

GeoContains

Si vous utilisez un élément canvas pour rendre votre géométrie, vous n'avez pas le luxe de pouvoir ajouter des gestionnaires d'événements aux éléments de chemin SVG. Au lieu de cela, vous pouvez vérifier si des événements de souris ou tactiles se produisent à l'intérieur des limites d'une entité. Vous pouvez le faire en utilisant d3.geoContains qui accepte une fonctionnalité GeoJSON et un tableau [lon, lat] et renvoie un booléen :


Commentaires

Bonjour, j'ai suivi le

Bonjour, j'ai suivi les instructions ci-dessus, mais je peux obtenir la carte à afficher.
Sur la page du panneau, je reçois juste un espace vide. Aucune carte n'est rendue. Pas même la couche de base. Quel peut être le problème ?
J'ai les dernières versions des modules d'exigences


Procédure pas à pas : carte thématique avec contrôles Leaflet et framework Bootstrap

Dans cette procédure pas à pas, vous rassemblerez certaines des choses que vous avez apprises dans cette leçon pour créer une carte d'informations complète contenant un style thématique et des commandes Leaflet. La carte utilisera le cadre de présentation Web Bootstrap afin qu'elle puisse être étendue avec un contenu supplémentaire d'une manière esthétique. Vous construirez une partie de ce contenu à la volée en lisant les attributs des entités cartographiques sélectionnées.

Pour cet exercice, nous nous en tiendrons aux données du métro d'Amérique du Sud. L'application finale permettra aux utilisateurs de cliquer sur n'importe quel métro et de voir du texte d'information et une image de Flickr. Une image de légende statique est également introduite dans la mise en page.

Bien que cette leçon s'appelle "Aller au-delà des "points sur une carte", j'ai délibérément choisi des données ponctuelles pour cette procédure pas à pas afin que vous puissiez apprécier les possibilités offertes par Leaflet, en particulier lorsqu'elles sont liées à d'autres cadres. Bien que vous ne vous sentiez peut-être pas comme un gourou de JavaScript à ce stade, vous devez au moins savoir que vous n'avez pas à vous contenter des mashups « larmes rouges et popup » que vous voyez partout sur Internet.

Téléchargement des données et examen de la mise en page

    et décompressez-le n'importe où. Si vous le souhaitez, vous pouvez placer les fichiers dans votre dossier de départ Jetty, mais la procédure pas à pas n'utilise pas GeoServer et ce n'est pas nécessaire. Les fichiers incluent une image de légende, les images Metro SVG et un fichier GeoJSON des emplacements et des attributs de métro. Notez également que, contrairement aux procédures pas à pas précédentes, j'ai déjà fourni un fichier HTML contenant le balisage de mise en page de base. Nous examinerons certains des éléments clés du balisage dans les étapes ci-dessous. Vous ajouterez également du JavaScript pour donner un peu de vie à cette application. Veuillez également noter que les fichiers incluent un fichier style.css comme nous l'avons utilisé dans les leçons précédentes, mais avec un changement important : largeur L'attribut de la carte a été modifié d'un nombre absolu fixe de pixels à une valeur relative (90%) pour s'assurer que la section div de la carte fonctionnera avec le modèle de mise en page Bootstrap que nous utiliserons dans cette procédure pas à pas.
  1. Ouvrez lesson8_walkthrough.html dans un navigateur Web et jetez-y un œil. Vous devriez voir le shell vide de l'application sans carte encore.

Avant d'ajouter JavaScript, je vais juste souligner quelques éléments importants dans la mise en page. Tout d'abord, notez comment Bootstrap est introduit dans l'application via une référence à un fichier JavaScript (.js) et un fichier CSS (.css) dans les lignes en gras ci-dessous. Nous référençons les fichiers à partir d'un CDN, mais vous pouvez également les télécharger et les héberger (et les modifier) ​​vous-même.

Notez également le remplacement de la feuille de style dans la balise <style>. Cela empêchera le contenu de notre page de s'écraser sur la bannière supérieure.

Si vous n'aimez pas quelque chose dans les styles par défaut de Bootstrap (ou Leaflet), les remplacements de feuille de style sont l'endroit où vous pouvez appliquer une modification.

Dans le corps de la page, observez comment les classes sont utilisées pour organiser la page en barres de navigation (navbar-*), conteneurs (container-fluid) et étendues. Les classes span5 et span7 divisent la page verticalement afin que des proportions cohérentes de la zone de la page soient consacrées à la carte (à gauche) et au matériel supplémentaire (à droite). Ne vous inquiétez pas de comprendre toutes ces classes à ce stade. Sachez simplement que les frameworks de développement Web tels que Bootstrap, Dojo, etc., peuvent vous fournir des classes CSS pour organiser les éléments de page d'une manière qui devrait se comporter de manière cohérente dans tous les navigateurs.

Enfin, notez que l'image de la légende et le texte « Cliquez sur un métro. » sont organisés dans un tableau HTML pour les garder à niveau. Les bordures de table sont invisibles par conception.

Un div attend une image Flickr, mais cela n'apparaîtra pas tant que quelqu'un n'aura pas cliqué sur un symbole de métro sur la carte.

Donnons maintenant un peu de vie à cette application en ajoutant du code JavaScript.

Ajout de la logique JavaScript

Vous utiliserez JavaScript pour effectuer trois tâches principales dans cette application : ajouter la carte, définir les symboles et gérer les événements de clic. Examinons-les dans l'ordre.

Dans votre lesson8_walkthrough.html, recherchez les balises de script. Vous mettrez tout votre code immédiatement après : <script type="text/javascript"> .

Ajoutez les lignes de code suivantes pour créer la carte et une fonction d'initialisation. Cette fonction contient des variables que nous utiliserons pour gérer les sélections tout au long, similaires à ce que vous avez vu dans la leçon 7 :

Remplace le . . . dans le code ci-dessus avec ce qui suit. Bien que ce soit beaucoup, tout cela devrait sembler assez familier si vous avez prêté attention aux extraits de code plus tôt dans la leçon :

Vous avez peut-être remarqué que metroLayer repose sur deux fonctions : iconByPassday et metrosOnEachFeature. Nous les aborderons dans quelques minutes. Mais d'abord, le sélecteur de couches.

Remplace le . . . dans le code ci-dessus pour ajouter un contrôle de changement de couche à la carte :

Maintenant, pour ces fonctions que j'ai mentionnées. Le premier, iconByPassday, examine le nombre de passagers par jour qui voyagent dans chaque système de métro, puis décide quelle icône utiliser. C'est la clé pour classer la couche et la symboliser avec les différentes couleurs. Remplace le . . . dans le code ci-dessus avec ce qui suit :

Maintenant, pour cette fonction metrosOnEachFeature. Celui-ci est un peu plus long. Il ajoute un écouteur d'événement de clic à la couche metros, puis définit une fonction pour gérer cet événement. Remplace le . . . dans le code ci-dessus avec ce qui suit :

Examinez les commentaires de code ci-dessus pour comprendre ce que fait chaque section. Il y a beaucoup de code, mais la majeure partie consiste à construire le code HTML d'information décrivant le système de métro. Rappelez-vous que la table attributaire ressemble à ceci :

Vous devriez remarquer un grand nombre de ces noms de champs d'attribut référencés dans le code ci-dessus. La valeur du champ est récupérée, en utilisant une syntaxe spéciale || (opérateur OU logique qui, en JavaScript, renvoie le premier opérande qui est VRAI) pour définir une valeur de secours au cas où aucun attribut ne reviendrait. Le reste de la fonction construit des chaînes HTML, en insérant les attributs le cas échéant. Une fois les chaînes HTML construites, innerHTML est mis à jour pour les éléments « summaryLabel » et « metroImage ». Cela fait apparaître le nouveau texte et la photo sur le côté droit de la page.

Le champ PHOTO mérite une discussion supplémentaire ici. Anticipant que ce champ serait utilisé pour intégrer une photo dans une application, l'intégralité du code HTML de l'iframe est placé dans ce champ sous la forme d'une longue chaîne. Où obtenez-vous ce code si vous voulez créer un ensemble de données comme celui-ci ? Directement à partir de la fonctionnalité d'intégration de Flickr :

Enfin, ajoutez un gestionnaire d'événements de clic à la carte qui réinitialisera la sélection. Ceci est nécessaire si quelqu'un clique sur la carte, mais pas sur une icône de métro. Remplace le . . . dans le code ci-dessus avec ce qui suit :

Notez que du code a été ajouté ici pour effacer également le code HTML d'information et la photo.

Testez l'application en ouvrant lesson8_walkthrough.html dans un navigateur Web. (Si vous ouvrez simplement le fichier HTML directement à partir du système de fichiers, je vous recommande d'utiliser Firefox pour tester. En effet, les implémentations de sécurité des demandes d'origine croisée dans Chrome et Internet Explorer n'autorisent le chargement de GeoJSON que si vous hébergez les deux les fichiers HTML et GeoJSON sur un serveur Web.)

Vous devriez pouvoir basculer entre les différentes couches de base (notez que la couche ouverte Map Quest illustrée ci-dessous n'est plus disponible). Cliquez sur une icône de métro pour voir le symbole en surbrillance, l'image Flickr et le texte descriptif.

Code final pour la procédure pas à pas

Si la procédure pas à pas ne fonctionne pas, vérifiez que vous êtes connecté à Internet et que votre code correspond au code ci-dessous :


8.6 Ajouter une légende

8.6.1 Réglage du contenu de la légende avec L.control

Une carte Légende résume la signification de toutes les catégories affichées dans la symbologie de la carte. Dans la section 6.8, nous avons utilisé la fonction L.control pour ajouter une description de carte. Dans cette section, nous utilisons la même technique pour créer une légende pour notre carte. Le workflow de création d'une légende implique la création d'un contrôle personnalisé avec L.control , en le remplissant avec du HTML qui représente les composants de la légende, puis en le stylisant avec CSS pour que le contenu apparaisse correctement à l'écran. La section de code suivante fait tout cela, en ajoutant une légende à la carte de population des villes du dernier exemple ( example-08-04.html ):

Alors, qu'avons-nous fait ici? Tout d'abord, nous avons créé une instance d'un objet de contrôle personnalisé, en le nommant legend . Nous avons utilisé l'option de position pour localiser le contrôle dans le coin supérieur droit de notre carte. Ensuite, nous avons utilisé la méthode .onAdd du contrôle de légende pour exécuter une fonction lorsque la légende est ajoutée. La fonction crée un nouveau <div> dans le DOM, lui donnant une classe de "légende" . Cela nous permettra d'utiliser CSS pour styliser toute la légende à l'aide du sélecteur .legend (Section 8.6.2). Nous remplissons ensuite le nouveau <div> avec du HTML en utilisant la méthode .innerHTML, comme nous l'avons déjà fait dans la section 6.8.

La plupart du code HTML devrait être familier depuis le chapitre 1. Un type d'élément que nous n'avons pas encore vu est <small> , utilisé pour créer du texte relativement plus petit, ce qui est pratique pour afficher les unités de mesure (Figure 8.7) :

Le code HTML des entrées de légende utilise les éléments <div> pour dessiner la légende symboles, qui sont des rectangles carrés de 18px. Chaque symbole est suivi d'une description textuelle de la catégorie respective, telle que 2090+ . Les éléments <div> sont utiles dans ce contexte grâce au fait qu'ils sont colorés à l'aide de CSS en ligne (Section 2.7.2) et de la propriété background-color (Section 2.8.2.1). Les cinq éléments <div> reflètent ainsi les couleurs correspondant à la symbologie de la couche (Section 8.4.3). Par exemple, voici le code HTML qui crée la première icône colorée (rouge foncé) dans notre légende :

Une fois le code HTML ajouté, l'élément <div> de toute la légende est renvoyé avec return div . Enfin, la légende est ajoutée sur la carte à l'aide de la méthode .addTo.

Il est important de noter que, dans le code ci-dessus, la légende est générée manuellement. En d'autres termes, les coupures et les couleurs dans la légende et dans la symbologie de la carte (Section 8.4.3) sont spécifiées à deux endroits distincts dans notre code. C'est à nous de nous assurer que les étiquettes et les couleurs de la légende de la carte correspondent bien à celles avec lesquelles nous avons stylisé la couche. Une approche plus générale consiste à générer la légende par programmation, par exemple, en utilisant une boucle for passant par les mêmes tableaux de ruptures et de couleurs que nous avons utilisés lors de la définition de la symbologie de la carte (Section 8.4.3 ci-dessus). Voici une version alternative de la définition de la légende utilisant une boucle for et les tableaux de ruptures et de couleurs 83 que nous avons définis dans la section 8.4.3 :

Avec cette définition alternative, la symbologie de la couche et la légende sont toujours synchronisées, car elles dépendent des mêmes tableaux de ruptures et de couleurs. De cette façon, la modification de la symbologie (ajout de coupures supplémentaires, modification des couleurs, etc.) sera automatiquement reflétée à la fois dans les couleurs du polygone de la ville et dans les couleurs des icônes de légende.

8.6.2 Utiliser CSS pour styliser la légende

Une autre chose que nous devons faire concernant notre légende est de lui donner le bon emplacement et la bonne apparence, en utilisant CSS. Le code CSS suivant est utilisé pour styliser notre légende :

Dans la première règle CSS, nous avons défini des propriétés pour la légende dans son ensemble, en faisant référence à .legend . Nous définissons le remplissage, la couleur d'arrière-plan, l'ombre de la boîte et le rayon de la bordure. Dans la deuxième règle, nous définissons les dimensions de nos symboles de légende (éléments <div>) et définissons également float: left afin que les symboles soient alignés en colonnes. La propriété float:left (Section 7.6.2) garantit que les symboles et les descriptions textuelles de chaque entrée de légende sont placés ensemble, côte à côte, sur la même ligne. Enfin, la troisième règle garantit que les éléments de légende sont correctement alignés quel que soit le niveau de zoom du navigateur.

La carte des villes example-08-05.html , maintenant avec une légende de carte, est illustrée à la Figure 8.7.

  • Faites une copie locale de example-08-05.html .
  • Remplacez la section de code pour définir la fonction towns_color, pour utiliser une boucle for au lieu des conditionnels if / else. La section de code alternative est donnée dans la section 8.4.3. N'oubliez pas d'ajouter les définitions du tableau des breaks et des couleurs, en plus de la boucle for !
  • Remplacez la section de code pour générer le contenu HTML de la légende, pour utiliser une boucle for au lieu de la chaîne HTML fixe. La section de code alternative est donnée dans la section 8.6.
  • You should see few small differences between the Étiquettes of each color category in the legends of example-08-05.html (Figure 8.7) and your modified version. Can you figure out which parts of the code are responsible for those differences?

This step-by-step guide will quickly get you started on Leaflet basics, including setting up a Leaflet map, working with markers, polylines and popups, and dealing with events.

Preparing your page

Before writing any code for the map, you need to do the following preparation steps on your page:

Include Leaflet CSS file in the head section of your document:

Include Leaflet JavaScript file après Leaflet’s CSS:

Put a div element with a certain id where you want your map to be:

Make sure the map container has a defined height, for example by setting it in CSS:

Now you’re ready to initialize the map and do some stuff with it.

Setting up the map

Let’s create a map of the center of London with pretty Mapbox Streets tiles. First we’ll initialize the map and set its view to our chosen geographical coordinates and a zoom level:

By default (as we didn’t pass any options when creating the map instance), all mouse and touch interactions on the map are enabled, and it has zoom and attribution controls.

Note that setView call also returns the map object — most Leaflet methods act like this when they don’t return an explicit value, which allows convenient jQuery-like method chaining.

Next we’ll add a tile layer to add to our map, in this case it’s a Mapbox Streets tile layer. Creating a tile layer usually involves setting the URL template for the tile images, the attribution text and the maximum zoom level of the layer. In this example we’ll use the mapbox/streets-v11 tiles from Mapbox’s Static Tiles API (in order to use tiles from Mapbox, you must also request an access token). Because this API returns 512x512 tiles by default (instead of 256x256), we will also have to explicitly specify this and offset our zoom by a value of -1.

Make sure all the code is called after the div and leaflet.js inclusion. C'est tout ! You have a working Leaflet map now.

It’s worth noting that Leaflet is provider-agnostic, meaning that it doesn’t enforce a particular choice of providers for tiles. You can try replacing mapbox/streets-v11 with mapbox/satellite-v9 , and see what happens. Also, Leaflet doesn’t even contain a single provider-specific line of code, so you’re free to use other providers if you need to (we’d suggest Mapbox though, it looks beautiful).

Whenever using anything based on OpenStreetMap, an attribution is obligatory as per the copyright notice. Most other tile providers (such as Mapbox, Stamen or Thunderforest) require an attribution as well. Make sure to give credit where credit is due.

Markers, circles and polygons

Besides tile layers, you can easily add other things to your map, including markers, polylines, polygons, circles, and popups. Let’s add a marker:

Adding a circle is the same (except for specifying the radius in meters as a second argument), but lets you control how it looks by passing options as the last argument when creating the object:

Adding a polygon is as easy:

Working with popups

Popups are usually used when you want to attach some information to a particular object on a map. Leaflet has a very handy shortcut for this:

Try clicking on our objects. The bindPopup method attaches a popup with the specified HTML content to your marker so the popup appears when you click on the object, and the openPopup method (for markers only) immediately opens the attached popup.

You can also use popups as layers (when you need something more than attaching a popup to an object):

Here we use openOn instead of addTo because it handles automatic closing of a previously opened popup when opening a new one which is good for usability.

Dealing with events

Every time something happens in Leaflet, e.g. user clicks on a marker or map zoom changes, the corresponding object sends an event which you can subscribe to with a function. It allows you to react to user interaction:

Each object has its own set of events — see documentation for details. The first argument of the listener function is an event object — it contains useful information about the event that happened. For example, map click event object ( e in the example above) has latlng property which is a location at which the click occurred.

Let’s improve our example by using a popup instead of an alert:

Try clicking on the map and you will see the coordinates in a popup. View the full example &rarr

Now you’ve learned Leaflet basics and can start building map apps straight away! Don’t forget to take a look at the detailed documentation or other examples.


Click Events with Leaflet and geoJSON - Geographic Information Systems

Learn GeoJSON (and build cool collaborative datasets!)

Learn GeoJSON is a project to learn about the GeoJSON data format using git, GitHub, and geojson.io. It can be taught as a standalone exercise, or can be used to build real live collaborative datasets! There are a few in here to get you started.

The following sections are intended for absolute beginners. If you'e an intermediate or advanced user, great! Skip to the section where you're having trouble or need instructions.

The goal of this project is to build an awesome, collaborative map, showing off cool places, generated by the people who live in those places. It uses git for version control, GitHub to house the data, and provides editing examples using geojson.io, a great tool for editing GeoJSON files.

  • A tool to teach about GeoJSON, git, and GitHub in an easy and accessible way.
  • A way to learn about git and GitHub without using the command line.
  • A collaboration technique for building crowd-sourced geographic datasets.
  • A gentle introduction to GitHub for beginners.
  • A git tutorial / an overview of how to use git in the command line.
  • Comprehensive.
  • Scalable.
  • A silver bullet.

GeoJSON is an open and popular geographic data format commonly used in web applications. It is an extension of a format called JSON, which stands for Notation d'objet JavaScript. Basically, JSON is a table turned on its side. GeoJSON extends JSON by adding a section called "geometry" such that you can define coordinates for the particular object (point, line, polygon, multi-polygon, etc). A point in a GeoJSON file might look like this:

GeoJSON files have to have both a "geometry" section and a "properties" section. The "geometry" section houses the geographic information of the feature (its location and type) and the "properties" section houses all of the descriptive information about the feature (like fields in an attribute table).

Git is a tool that allows multiple people to work on the same files at the same time without overwriting each other’s changes. This general concept is called version control, and git is a version control system. There are several other version control systems out there, but git is popular because it does its job more efficiently than many (if not all) of the others.

In order for multiple people to work on a project, the data has to live in a place where multiple people can access it. GitHub is one of those places: the site houses thousands and thousands of projects, in individual workspaces called repositories, ou alors repos, that multiple people can access, copy, edit, and update using the tools available via git. (Guess what: You're inside of a repo right now!) These repositories also have a tracking element when someone makes a change to a project, or a commit, information is stored about the user, the time, the exact changes that were made (all the way down to the individual line inside the file!), and a unique ID that allows the project owner to restore back to that particular moment.

Why are we using GitHub and GeoJSON?

Tom MacWright over at MapBox has built an amazing, browser-based tool for editing GeoJSON files called geojson.io. Using some of the great tools available via MapBox.js, Leaflet, and some internal GitHub functionality, geojson.io allows users to easily edit and create geographic data in the browser.

Génial! How do I contribute?

There are a few things that are required for you to contribute to this dataset. First of all, you need to make yourself a GitHub account, if you don't have one already. It's free and easy to set up, and should take less than five minutes.

I would also advise downloading git. Click the link and download the recommended version.

Beyond that, there are two main ways to contribute to this dataset: one is to edit existing files by adding points to them. The other is to add your own files to the repository and make them available for editing. There are step-by-step instructions for doing each of these, below.

These are the files that are currently in the repository and can be edited:


Introducing HumanGeo’s Leaflet Data Visualization Framework

At HumanGeo, we’re fans of Leaflet, Cloudmade’s JavaScript web mapping framework. In the past, we’ve used other JavaScript mapping frameworks like OpenLayers and Google Maps, and while these frameworks are great, we like Leaflet for its smooth animation, simple API, and good documentation and examples. In fact, we like Leaflet so much, we’ve been using it in all of our web projects that require a mapping component. Since Leaflet is a relative newcomer in the world of JavaScript mapping frameworks (2011), and since the developers have focused on keeping the library lightweight, there are plenty of opportunities to extend the basic functionality that Leaflet offers.

As a side project at HumanGeo, we’ve been working on extending Leaflet’s capabilities to better support visualizing data, and these efforts have produced HumanGeo’s Leaflet Data Visualization Framework. Before I delve into some of the features of the framework, I’d like to provide a little background on why we created the framework in the first place, in particular, I’d like to focus on the challenges that developers face when creating data-driven geospatial visualizations.

When visualizing data on a 2D map we often wish to illustrate differences in data values geographically by varying point, line, and polygon styles (color, fill color, line weight, opacity, etc.) dynamically based on the values of those data. The goal is for users to look at our map and quickly understand geographic differences in the data being visualized. This technique is commonly referred to as thematic mapping, and is a frequently employed technique used in infographics and for illustrating concepts related to human geography. Within the realm of thematic mapping, proportional symbols and choropleth maps are two widely used approaches for illustrating variations in data.

Symbol Styling Options

The proportional symbol approach highlights variations in data values at point locations using symbols sized proportionally to a given data value. In addition to varying symbol size, we can also vary symbol color or other style properties in order to highlight multiple data properties at each point. The image on the right shows some of the available style properties that we can vary for circle markers in Leaflet.

A good example of this approach is the USGS Earthquake Map, which by default shows earthquakes of magnitude 2.5 or greater occurring in the past week. This map denotes earthquakes using circles that are sized by magnitude and colored by age (white – older to yellow – past week to red – past hour). In an upcoming blog post, I’ll describe how we can use the Leaflet Data Visualization Framework along with USGS’ real-time earthquakes web service to easily reproduce this map.

Choropleth mapping involves styling polygons – typically country, state, or other administrative/political boundaries – based on statistical data associated with each polygon. In US election years, we see tons of maps and infographics showing breakdowns of voter preferences and predicted winners/losers by state, county, or other US political boundary. Infographics are becoming more and more popular, and there’s no shortage of news outlets like the New York Times, The Washington Post, and others producing maps illustrating various statistics at a range of administrative boundary levels. On the web, these choropleth maps are often custom developed, static or potentially interactive, single purpose maps that typically make use of a variety of frameworks, including more advanced all-purpose visualization frameworks like D3 rather than web mapping frameworks like Leaflet. This single purpose approach is not a problem when you’re using the map to show only one thing, but what if you want to show multiple data views or a variety of data on the same map? Nothing against D3 (which is awesome) or other general purpose visualization frameworks, but why would I want to learn the intricacies of some other framework in order to produce a choropleth map? If I’m already using Leaflet for all of my web mapping activities, why wouldn’t I use it for creating thematic maps?

Fortunately, Leaflet provides a number of built-in capabilities that enable creating thematic maps, including excellent support for GeoJSON and the ability to draw points using image-based, HTML-based, and circle markers as well as support for drawing lines and polygons and styling those features dynamically. There are a few tutorials on the Leaflet website that explain how to use Leaflet’s GeoJSON capabilities for displaying point, line, and polygon data and creating choropleth maps. I recommend checking these tutorials out if you’re interested in using Leaflet or want to better understand what capabilities Leaflet provides out of the box (screenshots of these tutorials plus links to the tutorials appear below).

Loading GeoJSON using Leaflet Creating a Choropleth Map using Leaflet

While Leaflet’s out of the box capabilities simplify thematic map creation, there are still several challenges that developers face when trying to create thematic maps using Leaflet or any web mapping framework for that matter, particularly when GeoJSON data is not available. The first challenge is a common one for developers – no standard format. The Internet is full of data that can be used to build thematic maps, but this data comes in a variety of formats (CSV, TSV, XML, JSON, GeoJSON, etc.). This makes building reusable code that works with and across most datasets challenging. The underlying issue here, and perhaps the main reason that data is and will continue to be created in a variety of formats, is that the people creating this data aren’t typically creating the data with geospatial visualization in mind, so there will almost always be some aspect of massaging the data so that it can be loaded and displayed using the desired mapping framework.

Mapping data on a political/admin boundary level comes with its own set of challenges. Often the data driving choropleth and thematic map visualizations related to political boundaries are numbers and categories associated with a code for a given boundary. These codes can include (among other options): two digit state code, Federal Information Processing Standard (FIPS) code, International Organization for Standardization (ISO) two or three digit country code, state name, country name, etc. This again comes back to the issue of a lack of standardization for country level statistics, for instance, you might see country name, two digit, three digit, numeric codes, or other codes being used across data providers. Very rarely are the geometries associated with each boundary included in the source data, and even more rare is pre-packaged GeoJSON that contains boundary polygons along with statistics as properties of each polygon. This introduces a challenge for developers in that we must find and associate boundary polygons with those boundary identifiers on the client-side or on the server in order to build a thematic map. On the client side, this may involve interacting with a web service (e.g. an OGC Web Feature Service (WFS)) that serves up those polygons, particularly in the case where we’re creating choropleth maps for lower level admin/political boundaries. In general, the two most common types of choropleth maps that people tend to create are country and state level maps. If I’m building a state or country choropleth, I’m probably going to be using all of the state or country polygons that are available, so making requests to a web service to get each polygon might be a little excessive. In addition, if we’re trying to display symbols based on state or country codes, we need the centroids of each political boundary in order to position each symbol correctly. This requires the need to calculate the centroid dynamically or to include it as a property of the boundary polygon.

In addition to challenges with data formats, there are often redundant tasks that developers must perform when creating thematic maps. Ceux-ci inclus:

  1. Retrieving data from a local/remote web server and translating those data into JavaScript objects
  2. Translating data locations into web mapping framework appropriate point/layer objects
  3. Dynamically styling point/layer objects based on some combination of data properties
  4. Setting up interactive features – handling mouseover and click events
  5. Displaying a legend to make it easier for the user to understand what’s being shown

In the grand scheme of things, these are not monumental challenges, but they do make the jobs of developers more difficult. HumanGeo’s Leaflet Data Visualization Framework helps to alleviate some of these challenges by abstracting many of these details from the developer. In particular, the framework seeks to:

  • Enable cool, interactive, infographic style visualizations
  • Support displaying data in any JSON-based data format (not just GeoJSON)
  • Eliminate redundant code/tasks related to displaying data
  • Provide tools for simplifying mapping one value to another (e.g. temperature to radius, count to color, etc.)
  • Standardize the way in which data are loaded/displayed
  • Minimize dependency on server-side components for typical use cases (e.g. visualizing data by US state or country)
  • Remain consistent with Leaflet’s API/coding style so that it’s easy to pickup and use if you’re already familiar with Leaflet

It wouldn’t be a proper introduction to a framework that’s all about visuals without showing you some sample visualizations, so here are a few example maps created using the framework to give you an idea of the type of maps you can create:

Election Mapping Country Level Data Display Ethnic Enclaves in New York City

In the next few blog entries, I’ll provide more details and examples illustrating how HumanGeo’s Leaflet Data Visualization Framework simplifies geospatial data visualization and thematic map creation. In the meantime, check out the code and examples on GitHub, and send me an e-mail if you’re interested, have questions, or want to contribute.