Article original : How to create a Coronavirus (COVID-19) Dashboard & Map App in React with Gatsby and Leaflet
La pandémie de Coronavirus (COVID-19) a rapidement changé la façon dont nous interagissons au quotidien. Comment pouvons-nous utiliser les API disponibles pour créer une application de cartographie qui montre l'impact qu'elle a eu sur le monde ?
Mise à jour : Le point de terminaison original de l'API NovelCOVID v1 a été obsolète. Veuillez mettre à jour et utiliser plutôt : https://corona.lmao.ninja/v2/countries
Note de l'auteur : Ceci est destiné à être une démonstration et une preuve de concept pour mettre ensemble une application de cartographie impactante utilisant des données de la vie réelle. Pour une analyse complète et précise, assurez-vous d'utiliser des outils comme le tableau de bord de l'Université Johns Hopkins. Restez chez vous et soyez en sécurité ! ❤️
- Qu'allons-nous construire ?
- Qu'avons-nous besoin avant de commencer ?
- Étape 1 : Nettoyer du code inutile
- Étape 2 : Récupérer les données du Coronavirus
- Étape 3 : Transformer les données du Coronavirus en un format de données géographiques
- Étape 4 : Ajouter les données du Coronavirus à la carte
- Que pouvons-nous faire d'autre ?
- Restez en sécurité et informé
- Vous voulez en savoir plus sur les cartes ?
Qu'allons-nous construire ?
Nous allons mettre ensemble une application de cartographie qui utilise une API contenant des statistiques récentes sur le Coronavirus et cartographie les emplacements et l'impact auquel chaque pays est confronté.
Démonstration du tableau de bord de la carte du Coronavirus
Sur la carte, nous allons montrer un marqueur pour chaque pays avec le nombre de cas confirmés. En plus de cela, nous inclurons une petite info-bulle qui montre des informations plus détaillées.
La carte que nous allons construire ressemblera principalement à celle ci-dessus, mais sera un peu plus simple. Nous utiliserons le serveur de tuiles public OpenStreetMap au lieu d'utiliser une Mapbox personnalisée.
Pour commencer, nous allons utiliser ce Leaflet Gatsby Starter que j'ai créé pour rendre le démarrage initial un peu plus fluide. Avec notre application démarrée, nous allons récupérer nos données et ajouter des marqueurs à la carte avec nos données.
Woah, une application de cartographie ?
Oui. Si vous n'avez pas joué avec des cartes auparavant, ne vous découragez pas ! Ce n'est pas aussi compliqué que vous le pensez probablement. Si vous préférez commencer par les bases de la cartographie, vous pouvez lire plus sur le fonctionnement de la cartographie d'abord.
Qu'avons-nous besoin avant de commencer ?
Si vous avez suivi mes tutoriels précédents pour construire un suiveur du Père Noël ou créer une carte de voyage d'été, vous pouvez suivre les mêmes étapes pour commencer. Sinon, nous voudrons nous assurer que nous avons les éléments suivants configurés :
- node ou yarn - J'utiliserai yarn, mais vous pouvez substituer avec npm lorsque cela est approprié
- CLI de Gatsby -
yarn global add gatsby-cli
Si vous n'êtes pas sûr de l'un des éléments ci-dessus, vous pouvez essayer de consulter le début de mon tutoriel précédent.
Nous voudrons également mettre en place une base pour notre carte. Nous pouvons le faire en utilisant le Leaflet Gatsby Starter que j'ai mis ensemble et qui nous fournit une configuration de base avec Leaflet et React Leaflet.
gatsby new my-coronavirus-map https://github.com/colbyfayock/gatsby-starter-leaflet
Création d'une nouvelle application Leaflet Gatsby dans le terminal
Une fois que cela a fini de s'exécuter, vous pouvez naviguer vers le répertoire du projet nouvellement créé et démarrer votre serveur de développement local :
cd my-coronavirus-map
yarn develop
Démarrage de votre application Gatsby dans le terminal
Si tout se passe comme prévu, votre serveur devrait démarrer et vous devriez maintenant pouvoir voir votre application de cartographie de base dans votre navigateur !
Nouvelle application Leaflet Gatsby dans le navigateur
Étape 1 : Nettoyer du code inutile
Le Gatsby Starter que nous utilisons pour démarrer cette application contient du code de démonstration dont nous n'avons pas besoin ici. Nous voudrons apporter toutes les modifications ci-dessous dans le fichier src/pages/index.js, qui est la page d'accueil de notre application.
Tout d'abord, supprimons tout le contenu de la fonction mapEffect. Cette fonction est utilisée pour exécuter du code qui se déclenche lorsque la carte est rendue.
// Dans src/pages/index.js
async function mapEffect({ leafletElement } = {}) {
// Supprimez tout ce qui se trouve ici
}
Nous allons également changer le nom de la variable de notre leafletElement simplement pour pouvoir comprendre plus facilement le code lorsque nous l'écrirons.
async function mapEffect({ leafletElement: map } = {}) {
}
Ensuite, nous ne voulons pas de marqueur cette fois, alors supprimons le composant <Marker de notre composant <Map :
<Map {...mapSettings} />
Maintenant que nous avons supprimé ces éléments, nous pouvons supprimer toutes les importations et variables suivantes du haut de notre fichier :
- useRef
- Marker
- promiseToFlyTo
- getCurrentLocation
- gatsby_astronaut
- timeToZoom
- timeToOpenPopupAfterZoom
- timeToUpdatePopupAfterZoom
- ZOOM
- popupContentHello
- popupContentGatsby
- markerRef
Après cela, notre carte devrait toujours fonctionner, mais ne rien faire.
Nouvelle application de cartographie sans rien faire
Étape 2 : Récupérer les données du Coronavirus
Pour notre application, nous allons utiliser l'API NovelCOVID. Plus particulièrement, nous allons utiliser le point de terminaison des pays pour récupérer la liste de nos pays et les statistiques qui leur sont associées.
Pour faire des requêtes, j'aime personnellement utiliser axios car il a une API agréable à utiliser. Si vous voulez utiliser fetch ou votre propre bibliothèque de requêtes préférée, substituez-la pour cette étape.
Nous allons commencer par installer axios :
yarn add axios
Une fois que cela est installé, n'oubliez pas de redémarrer votre serveur.
Importez le package axios en haut de notre fichier pages/index.js :
import axios from 'axios';
Ensuite, nous allons effectivement faire notre requête. À l'intérieur de notre fonction mapEffect, essayons de faire une requête au point de terminaison de l'API :
async function mapEffect({ leafletElement: map } = {}) {
let response;
try {
response = await axios.get('https://corona.lmao.ninja/v2/countries');
} catch(e) {
console.log(`Échec de la récupération des pays : ${e.message}`, e);
return;
}
const { data = [] } = response;
}
Dans cet extrait, nous faisons ce qui suit :
- Nous configurons une variable
responsequi nous permettra de stocker la réponse - Nous ajoutons un bloc
try/catchqui attrapera toute erreur d'API si la requête échoue - Si la requête est réussie, nous stockons la réponse dans la variable
response - Si la requête échoue, nous enregistrons l'erreur dans la console et quittons la fonction pour ne pas continuer à exécuter le code avec une requête échouée
- Une fois que nous avons notre réponse, nous pouvons déstructurer
datade la réponse et définir la valeur par défaut à un tableau vide, car ce sera le type de données dont nous avons besoin
Après cela, nous pouvons enregistrer l'objet data dans la console et nous verrons nos données récupérées avec succès !
Enregistrement des données de localisation du Coronavirus dans la console du navigateur
Mise à jour : Le commit précédent inclut un lien vers le point de terminaison original de l'API NovelCOVID v1 qui est maintenant obsolète. Veuillez utiliser ceci à la place : https://corona.lmao.ninja/v2/countries.
Étape 3 : Transformer les données du Coronavirus en un format de données géographiques
Maintenant que nous avons nos données, nous pouvons les transformer en un format de données géographiques, en particulier GeoJSON, qui nous permettra d'interfacer avec Leaflet.
Commençons par ajouter ce bloc de code :
const { data = [] } = response;
const hasData = Array.isArray(data) && data.length > 0;
if ( !hasData ) return;
const geoJson = {
type: 'FeatureCollection',
features: data.map((country = {}) => {
const { countryInfo = {} } = country;
const { lat, long: lng } = countryInfo;
return {
type: 'Feature',
properties: {
...country,
},
geometry: {
type: 'Point',
coordinates: [ lng, lat ]
}
}
})
}
Alors, que faisons-nous ici ?
- Nous créons une nouvelle constante appelée
hasDataqui vérifie si notre variabledataest un tableau et contient des données - Si nous n'avons pas de données, nous voulons quitter la fonction, car nous ne voulons pas essayer d'ajouter des données que nous n'avons pas
- Nous créons un objet
geoJsonqui sera notre document GeoJSON - Notre document est de type
FeatureCollectionet en tant que nosfeatures, nous parcourons notre ensemble de données - Pour chaque pays dans nos données, nous obtenons la
latet lalngpour créer un point pour notre carte - Nous ajoutons également nos données de pays en tant que propriétés afin de pouvoir y accéder dans nos API de cartographie
Si vous console.log cet objet dans votre navigateur et copiez le contenu, vous pouvez coller ceci dans geojson.io et voir les données de localisation s'afficher correctement.
Aperçu des données de localisation du Coronavirus sur geojson.io
Avec ce document GeoJSON, nous pourrons maintenant l'ajouter à notre carte.
Étape 4 : Ajouter les données du Coronavirus à la carte
Nous avons notre document GeoJSON avec nos données de localisation, alors ajoutons-le à la carte.
Commençons par ce bloc de code. Il est long, mais nous allons le décomposer pièce par pièce :
const geoJsonLayers = new L.GeoJSON(geoJson, {
pointToLayer: (feature = {}, latlng) => {
const { properties = {} } = feature;
let updatedFormatted;
let casesString;
const {
country,
updated,
cases,
deaths,
recovered
} = properties
casesString = `${cases}`;
if ( cases > 1000 ) {
casesString = `${casesString.slice(0, -3)}k+`
}
if ( updated ) {
updatedFormatted = new Date(updated).toLocaleString();
}
const html = `
<span class="icon-marker">
<span class="icon-marker-tooltip">
<h2>${country}</h2>
<ul>
<li><strong>Confirmés :</strong> ${cases}</li>
<li><strong>Décès :</strong> ${deaths}</li>
<li><strong>Rétablis :</strong> ${recovered}</li>
<li><strong>Dernière mise à jour :</strong> ${updatedFormatted}</li>
</ul>
</span>
${ casesString }
</span>
`;
return L.marker( latlng, {
icon: L.divIcon({
className: 'icon',
html
}),
riseOnHover: true
});
}
});
Alors, que faisons-nous ici ?
- Nous créons une nouvelle instance de
L.GeoJSONqui transformera notre document GeoJSON en quelque chose que Leaflet comprendra - À l'intérieur de cette instance, nous définissons une fonction
pointToLayerpersonnalisée. Cela nous permet de personnaliser la couche de carte que Leaflet crée pour notre carte - Dans notre fonction, nous assignons et créons nos points de données que nous voulons. La plupart est de la déstructuration, mais nous formatons le compte des cas pour afficher
1k+au lieu de1000et une date formatée au lieu du timestamp - Nous créons un bloc de chaîne HTML qui est utilisé pour définir notre marqueur de carte qui sera ajouté à la carte. Cela inclut également le HTML pour l'info-bulle qui apparaîtra lorsque vous survolez un marqueur
- Nous retournons
L.markeravec notre configuration personnalisée qui inclut une classe deiconpour le conteneur et notre HTML personnalisé. - De plus, nous ajoutons la propriété
riseOnHoverafin que lorsque vous survolez un marqueur, il se place au-dessus des autres marqueurs sur la carte
Nous voulons également ajouter un peu de CSS ici pour nous assurer que nos marqueurs apparaissent sur la carte et sont utilisables. Ajoutons cet extrait à notre fichier assets/stylesheets/components/_map.scss :
.icon-marker {
display: flex;
position: relative;
justify-content: center;
align-items: center;
color: white;
width: 3.6em;
height: 3.6em;
font-size: .7em;
font-weight: bold;
background-color: $red-800;
border-radius: 100%;
box-shadow: 0 2px 5px rgba(black, .9);
&:hover {
.icon-marker-tooltip {
display: block;
}
}
}
.icon-marker-tooltip {
display: none;
position: absolute;
bottom: 100%;
width: 16em;
font-size: 1.4em;
padding: 1em;
background-color: $blue-grey-900;
border-radius: .4em;
margin-bottom: 1em;
box-shadow: 0 3px 5px rgba(black, .9);
&:before {
display: block;
position: absolute;
bottom: -.6em;
left: 50%;
content: '';
width: 1.4em;
height: 1.4em;
background-color: $blue-grey-900;
transform: rotate(45deg);
margin-left: -.7em;
}
h2 {
font-size: 1.5em;
line-height: 1.2;
margin-bottom: .1em;
margin-top: 0;
}
h3 {
font-size: 1.2em;
margin: .1em 0;
font-weight: normal;
color: $blue-grey-100;
}
ul,
p {
font-weight: normal;
}
ul {
list-style: none;
padding: 0;
margin: .6em 0 0;
}
}
Ce que nous faisons :
- Nous créons nos marqueurs ronds en utilisant la classe
.icon-markeret configurons notre classe.icon-marker-tooltippour qu'elle apparaisse lorsque l'on survole - Notre classe
.icon-marker-tooltipest masquée par défaut, car c'est notre info-bulle, mais nous la positionnons de manière absolue pour qu'elle apparaisse au-dessus de notre marqueur et formatée comme nous le voulons
Et enfin, une fois que nous avons créé nos geoJsonLayers avec notre style ajouté, nous pouvons l'ajouter à la carte !
geoJsonLayers.addTo(map)
Carte avec les données de localisation du Coronavirus
Maintenant, vous vous demandez peut-être pourquoi elle ne semble pas être centrée correctement. Allez-y et changez la variable LOCATION en haut du fichier index.js en :
const LOCATION = {
lat: 0,
lng: 0
};
Une fois que cela est défini, lorsque la page se recharge, la carte devrait être centrée au milieu du monde !
Carte avec les données de localisation du Coronavirus centrées avec une info-bulle
Hourra, nous l'avons fait ! ?
Si vous avez suivi, vous avez maintenant créé votre propre tableau de bord de carte du Coronavirus qui donne quelques statistiques rapides sur les cas dans le monde.
Prenez ce que vous avez appris et courez avec. Vous pouvez appliquer cela à tout autre type de données que vous pouvez imaginer.
Que pouvons-nous faire d'autre ?
Ajouter plus de styles et une carte de base personnalisée
Dans ma démonstration originale, j'ai configuré une carte de base personnalisée en utilisant Mapbox qui me permet d'avoir un fond sombre rendant les marqueurs plus faciles à voir.
Création d'une nouvelle carte de base dans Mapbox Studio
Mapbox est génial et a un bon niveau gratuit si vous êtes intéressé à commencer.
Une fois que vous avez un compte Mapbox, vous pouvez même copier le style que j'ai utilisé et le rendre vôtre.
Pour apprendre comment l'intégrer, vous pouvez essayer de consulter le code source de ma démonstration originale :
https://github.com/colbyfayock/coronavirus-map-dashboard
Ajouter des statistiques de tableau de bord général
Les tableaux de bord avec des cartes comme l'application de l'Université Johns Hopkins nous permettent de voir plus qu'un simple aperçu de la carte, mais un aperçu des statistiques rapides sur les cas dans le monde.
Tableau de bord de la carte du Coronavirus de l'Université Johns Hopkins - 29 mars 2020
L'API NovelCOVID a plus de points de terminaison comme /all qui fournissent quelques statistiques globales.
Restez en sécurité et informé
Je veux réitérer que vous devez vous assurer de rester à jour en utilisant des sources officielles d'information, comme le tableau de bord de l'Université Johns Hopkins. Bien que les données devraient être fiables, elles devraient également être considérées comme une preuve de concept pour construire une carte et y faire référence, mais ne devraient pas être considérées pour une quelconque analyse statistique.
Veuillez prendre soin de vous pendant ces périodes. Nous sommes tous dans le même bateau ! ❤️
Vous voulez en savoir plus sur les cartes ?
Vous pouvez consulter quelques-unes de mes autres ressources pour commencer :
- Tout le monde peut cartographier ! Inspiration et une introduction au monde de la cartographie
- Comment configurer un style de carte de base Mapbox personnalisé avec React Leaflet et Leaflet Gatsby Starter
- Comment créer une application de cartographie de voyage d'été avec Gatsby et Leaflet
- Comment créer votre propre suiveur du Père Noël avec Gatsby et React Leaflet
- Comment construire une application de cartographie en React facilement avec Leaflet