Les applications Web ont grandement bénéficié de l'inclusion de cartes, fournissant aux utilisateurs de précieuses informations de localisation. Les cartes ont transformé notre interaction avec le monde, de la navigation dans des lieux inconnus à la découverte de restaurants à proximité. En conséquence, l’intégration de cartes dans des sites Web est devenue de plus en plus populaire ces derniers temps. Néanmoins, concevoir des cartes à la fois fonctionnelles et conviviales peut présenter un défi, en particulier pour ceux qui manquent d’expérience dans ce domaine. Dans cet article, je partagerai des conseils utiles sur la façon de créer des cartes efficaces dans votre navigateur.
Parlons des technologies. Lorsque nous travaillons avec des cartes, nous utilisons généralement trois couches :
Rendu de l'interface utilisateur, qui comprend des boutons et des formulaires. Dans notre stack, React remplit ce rôle ;
Rendu de la carte et activation de l'interaction de l'utilisateur. Nous utilisons Mapbox pour cela ;
Récupérer des données depuis le serveur, telles que des informations sur des marqueurs ou des polygones. Pour récupérer des données, nous utilisons la fonction de récupération intégrée du navigateur.
Passons en revue chaque élément pour mieux comprendre notre pile technologique lorsque nous travaillons avec des cartes.
Le
La modification d'éléments sur une page étant l'opération la plus coûteuse pour un navigateur, il est essentiel de le faire le plus efficacement possible. Pour résoudre ce problème, les ingénieurs de Facebook ont développé la bibliothèque React, qui permet des modifications rapides et simples des éléments d'une page. En plus de fournir des changements d'état rapides sur une page, React nous permet de le faire de manière déclarative sans travailler directement avec les éléments DOM. Au lieu de cela, nous utilisons une abstraction, généralement
// It's our state. Is the user our friend or not? // false by default const [isFriend, setIsFriend] = useState(false) // Depending on the state, we show the text on the button const buttonText = isFriend ? 'Your my Friend' : 'Add as Friend' // There is JSX, syntax for UI // In this case, we display a button, when clicked, we change the state return ( <button onClick={() => setIsFriend(true)}>{buttonText}</button> )
Il est possible d'imbriquer des composants avec des éléments DOM ordinaires comme des formulaires, des boutons et des entrées au bas de la hiérarchie. En assemblant ces éléments simples, nous pouvons en créer des plus complexes, comme un formulaire complet :
const Form = () => ( <form> <input name="Email"/> <input name="Password"/> </form> ) const App = () => ( <main> <h1>My form!</h1> <Form /> </main> )
Comment React nous aide-t-il dans le contexte des cartes ? La carte sur la page étant interactive, semblable à un bouton ou un formulaire, nous visons à optimiser son rendu et son interaction via des événements comme les clics sur la carte. React peut aider à réaliser cette optimisation. Voici un exemple de la façon dont cela fonctionne :
// Use React to render the map with different event handlers // and render markers return ( <BaseMap onInitMap={() => console.log('I am alive!')} onClickMap={() => console.log('Click!')} onDestroyMap={() => console.log('Oh no!')} > <ClustersMarkers /> <PostsMarkers /> <ListingsMarkers /> </BaseMap> )
Lorsque vous travaillez avec React, il est essentiel de se rappeler qu'il permet une manipulation efficace des éléments de la page, des changements rapides et une interaction avec eux via des événements. Ceci est réalisé grâce à une abstraction qui ressemble à HTML, ce qui facilite la création de composants complexes à partir de composants plus simples.
Parlons maintenant de la carte elle-même. La création et l'utilisation de cartes peuvent s'avérer difficiles, et seules quelques sociétés de produits peuvent concevoir des cartes à partir de zéro. En règle générale, la plupart des gens s'appuient sur des bibliothèques prédéfinies dotées d'une API conviviale qui a été éprouvée et testée.
De nombreux fournisseurs de cartes dynamiques sont disponibles, notamment Google Maps, Leaflet, Bing Maps, Mapbox, etc. Cependant, nous nous concentrerons sur
Offres Mapbox
De plus, Mapbox fournit un
Mapbox propose une variété de
Revisitons les cartes Mapbox. Que fait le
Il initialise la carte dans un élément HTML de la page ;
Il charge et restitue les images qui composent la carte ;
Il dessine des éléments supplémentaires, tels que des marqueurs, en utilisant GeoJson comme données d'entrée ;
Il génère des événements, tels que des clics ou des changements de zoom, qui peuvent être gérés.
Examinons de plus près chacun de ces éléments.
Mapbox est spécialisé dans le rendu de cartes à l'aide de tuiles. Les tuiles sont de petites images carrées qui constituent la carte plus grande. La taille par défaut d'une vignette est de 512 x 512 pixels, et elle peut être soit
Juste pour que vous le sachiez, Mapbox Studio nous permet de choisir les données spécifiques que nous souhaitons inclure dans les tuiles de la carte. Ces tuiles sont ensuite placées sur un
<canvas width="100" height="100" />
Mapbox gère le chargement, l'insertion et la mise à jour des tuiles. Il suffit de préciser où nous voulons que la carte soit affichée et les conditions initiales, comme le niveau de zoom ou les coordonnées de la carte. Pour utiliser Mapbox, vous aurez besoin d'un
mapboxgl.accessToken = 'YOUR_MAPBOX_ACCESS_TOKEN'; const map = new mapboxgl.Map({ container: 'map', // we can use an Id or an element style: 'mapbox://styles/mapbox/streets-v11', // URL for styles center: [-74.5, 40], // initial coordinates [lng, lat] zoom: 9, // initial zoom });
Après cela, nous obtiendrons une carte sur la page dans un élément avec l'identifiant « map ».
Pour fournir aux utilisateurs plus d'informations sur la carte, nous affichons souvent l'emplacement d'un certain établissement ou les limites d'une zone spécifique. Pour y parvenir, nous utilisons un format de données spécifique appelé
GeoJSON est le format standard pour stocker des structures géographiques sur des cartes. Il peut stocker divers types primitifs décrivant des objets géographiques tels que des adresses, des emplacements, des rues, des autoroutes, des frontières, des pays, des états et des combinaisons de ceux-ci, appelées multiparts. GeoJSON a été introduit en 2008 et est représenté comme ceci :
{ "type": "Feature", // also can be FeatureCollection, it's collection of Feature "geometry": { "type": "Point", // also can be LineString, Polygon, MultiPolygon "coordinates": [125.6, 10.1] // for other types you can use Array with coordinates }, "properties": { // it's metadata, we can you that to show something on the map "name": "Dinagat Islands" } }
Parlons du système de coordonnées utilisé dans Mapbox. Par défaut, Mapbox emploiemap.setProjection
.
Nous allons maintenant voir comment afficher GeoJSON sur la carte. Mapbox propose deux entités qui nous seront utiles :
Pour afficher des polygones ou des marqueurs sur la carte, il faut récupérer les données au format GeoJson depuis le serveur. Ensuite, nous créons une source, y saisissons les données et la connectons à la couche requise.
const geoJsonFeature = { 'type': 'Feature', 'geometry': { 'type': 'Polygon', 'coordinates': [ [-67.13734, 45.13745], [-66.96466, 44.8097], [-68.03252, 44.3252], [-67.13734, 45.13745] ] } } // Create source with our data map.addSource('ourSource', { 'type': 'geojson', 'data': geoJsonFeature }); // Add layer for background map.addLayer({ 'id': 'background', 'type': 'fill', 'source': 'ourSource', // название нашего source 'layout': {}, 'paint': { 'fill-color': '#0080ff', 'fill-opacity': 0.5 } }); // Add layer for border map.addLayer({ 'id': 'border', 'type': 'line', 'source': 'ourSource', 'layout': {}, 'paint': { 'line-color': '#000', 'line-width': 3 } });
Après avoir exécuté ce code, nous obtenons le résultat :
Pour en savoir plus sur ce sujet, vous pouvez vous référer auon
avec le type d’événement souhaité, de la même manière que nous travaillons avec les éléments DOM.
map.on('mousemove', (e) => { console.log(JSON.stringify(e.point)); }); // Result: {"x":330,"y":49}
En résumé, que faut-il retenir ? Mapbox nous permet d'afficher une carte, d'y dessiner nos données et de traiter les événements de la carte. Parallèlement, Mapbox s'occupe du chargement et de l'affichage des images (tuiles).
Un mot sur
Que faut-il retenir ? Nous récupérons les données du serveur et il existe de nombreuses bibliothèques pour cela, mais nous utiliserons fetch. Ensuite, nous verrons comment procéder spécifiquement lorsque nous travaillons avec des cartes, car il existe des nuances.
Voyons maintenant comment les technologies décrites ci-dessus fonctionnent ensemble. Tout d’abord, nous allons récupérer les données permettant d’afficher le polygone à l’aide de fetch. Ensuite, nous déclarerons l'initialisation de la carte, et après son chargement, nous ajouterons le polygone à la carte.
Vous pouvez également trouver un exemple concret sur le site
const useFetch = () => { /* Our data { 'type': 'Feature', 'geometry': { 'type': 'Polygon', 'coordinates': [ [ [-67.13734, 45.13745], [-68.03252, 44.3252], [-68.90478, 47.18479], [-67.13734, 45.13745], ] ] } } */ const [data, setData] = useState(null) useEffect(() => { fetch('https://our-api.com/polygon') .then(response => response.json()) .then(setData) .catch(e => { console.error(e) }) }, [setData]) return { data } } const BaseMap = () => { // Use the hook to fetch data const { data } = useFetch(GET_REGION); // Map instance const map = useRef(null); // DOM element const mapContainer = useRef(null); // Main logic - init the map and add the event useEffect(() => { if (map.current) { return; // initialize map only once } mapboxgl.accessToken = 'YOUR_MAPBOX_ACCESS_TOKEN'; map.current = new mapboxgl.Map({ container: mapContainer.current, style: 'mapbox://styles/mapbox/light-v10', // style URL (it's Mapbox's core style) center: [-68.137343, 45.137451], // starting position zoom: 5 // starting zoom }); // Handle event map.on('load', () => { const sourceId = 'source-region' // Add a data source containing GeoJSON data map.addSource(sourceId, { 'type': 'geojson', 'data': data.region // our data from Apollo }); // Add a new layer to visualize the polygon map.addLayer({ 'id': 'background', 'type': 'fill', 'source': sourceId, // reference the data source 'paint': { 'fill-color': '#0080ff', // blue color fill 'fill-opacity': 0.5 } }); // Add a black outline around the polygon map.addLayer({ 'id': 'outline', 'type': 'line', 'source': sourceId, 'paint': { 'line-color': '#000', 'line-width': 3 } }); }); }); return <div ref={mapContainer} />; }
Nous avons examiné la pile technologique qui sous-tend notre future architecture. Dans l'article suivant, nous aborderons les principes qui aident à concevoir une architecture de carte, comment obtenir un faible couplage maximal et une cohésion élevée des modules, et comment maintenir et développer un système de carte évolutif.
Merci beaucoup pour votre attention! Passe une bonne journée.