Cartes et Géolocalisation
Règles
- Mapbox GL JS pour des cartes interactives riches –
react-map-gl comme wrapper React
- Leaflet comme alternative gratuite –
react-leaflet pour React, aucune clé API requise pour les tuiles de base
- Gestion des clés API :
NEXT_PUBLIC_MAPBOX_TOKEN pour Mapbox côté client, ne jamais exposer les secrets côté serveur
- Géocodage : convertir des adresses en coordonnées – API de géocodage Mapbox ou OpenStreetMap Nominatim (gratuit)
- Regroupement de marqueurs : utiliser
supercluster ou le regroupement intégré de Mapbox pour les grands ensembles de marqueurs (100+)
- Modèle de localisateur de magasins : géocoder la position de l'utilisateur → interroger les magasins à proximité avec Haversine/PostGIS → afficher sur la carte
- Affichage d'itinéraires : API Directions Mapbox pour les itinéraires en voiture/à pied, rendu sous forme de couche GeoJSON LineString
- Géolocalisation du navigateur :
navigator.geolocation.getCurrentPosition() – toujours gérer gracieusement le refus d'autorisation
- Charger paresseusement le composant cartographique – les cartes sont lourdes ; utiliser
dynamic(() => import("./Map"), { ssr: false })
Modèles
import Map, { Marker, NavigationControl } from "react-map-gl";
import "mapbox-gl/dist/mapbox-gl.css";
function StoreMap({ stores }: { stores: Store[] }) {
return (
<Map
initialViewState={{ longitude: -122.4, latitude: 37.8, zoom: 11 }}
mapboxAccessToken={process.env.NEXT_PUBLIC_MAPBOX_TOKEN}
mapStyle="mapbox://styles/mapbox/streets-v12"
style={{ width: "100%", height: 400 }}
>
<NavigationControl position="top-right" />
{stores.map((store) => (
<Marker key={store.id} longitude={store.lng} latitude={store.lat}>
<Pin />
</Marker>
))}
</Map>
);
}
function haversineDistance(lat1: number, lon1: number, lat2: number, lon2: number): number {
const R = 6371;
const dLat = ((lat2 - lat1) * Math.PI) / 180;
const dLon = ((lon2 - lon1) * Math.PI) / 180;
const a = Math.sin(dLat / 2) ** 2 + Math.cos((lat1 * Math.PI) / 180) * Math.cos((lat2 * Math.PI) / 180) * Math.sin(dLon / 2) ** 2;
return R * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
}
À éviter
- Rendre côté serveur les composants cartographiques – toujours charger avec
ssr: false ou "use client"
- Rendre 1000+ marqueurs sans regroupement – tue les performances ; utiliser supercluster
- Coordonnées codées en dur – géocoder les adresses au moment de la construction ou à la demande
- Ignorer le refus d'autorisation de géolocalisation – toujours fournir un repli (saisie manuelle de l'adresse)