@navigoo/map-components 1.0.4 → 1.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/components/MapView.tsx +33 -104
package/package.json
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
import React, { useEffect, useRef
|
1
|
+
import React, { useEffect, useRef } from 'react';
|
2
2
|
import L from 'leaflet';
|
3
3
|
import 'leaflet/dist/leaflet.css';
|
4
4
|
import { parse } from 'wellknown';
|
@@ -28,77 +28,6 @@ const MapView: React.FC<MapViewProps> = ({
|
|
28
28
|
const routeLayerRef = useRef<L.LayerGroup | null>(null);
|
29
29
|
const clickMarkerRef = useRef<L.Marker | null>(null);
|
30
30
|
const routePolylinesRef = useRef<L.Polyline[]>([]);
|
31
|
-
const [ipLocation, setIpLocation] = useState<{ lat: number; lng: number } | null>(null);
|
32
|
-
|
33
|
-
// Fonction pour obtenir la localisation par IP
|
34
|
-
const getLocationByIP = async (): Promise<{ lat: number; lng: number } | null> => {
|
35
|
-
try {
|
36
|
-
const response = await fetch('https://ipapi.co/json/');
|
37
|
-
const data = await response.json();
|
38
|
-
|
39
|
-
if (data.latitude && data.longitude) {
|
40
|
-
return {
|
41
|
-
lat: data.latitude,
|
42
|
-
lng: data.longitude
|
43
|
-
};
|
44
|
-
}
|
45
|
-
return null;
|
46
|
-
} catch (error) {
|
47
|
-
console.error('Erreur de géolocalisation par IP:', error);
|
48
|
-
return null;
|
49
|
-
}
|
50
|
-
};
|
51
|
-
|
52
|
-
// Fonction pour obtenir la localisation par le navigateur
|
53
|
-
const getBrowserLocation = (): Promise<{ lat: number; lng: number }> => {
|
54
|
-
return new Promise((resolve, reject) => {
|
55
|
-
if (!navigator.geolocation) {
|
56
|
-
reject(new Error('Géolocalisation non supportée'));
|
57
|
-
return;
|
58
|
-
}
|
59
|
-
|
60
|
-
navigator.geolocation.getCurrentPosition(
|
61
|
-
(position) => {
|
62
|
-
resolve({
|
63
|
-
lat: position.coords.latitude,
|
64
|
-
lng: position.coords.longitude
|
65
|
-
});
|
66
|
-
},
|
67
|
-
(error) => {
|
68
|
-
reject(error);
|
69
|
-
},
|
70
|
-
{
|
71
|
-
enableHighAccuracy: true,
|
72
|
-
timeout: 10000,
|
73
|
-
maximumAge: 60000
|
74
|
-
}
|
75
|
-
);
|
76
|
-
});
|
77
|
-
};
|
78
|
-
|
79
|
-
// Effet pour la géolocalisation au démarrage
|
80
|
-
useEffect(() => {
|
81
|
-
const initializeLocation = async () => {
|
82
|
-
try {
|
83
|
-
// Essayer d'abord la géolocalisation du navigateur
|
84
|
-
const browserLocation = await getBrowserLocation();
|
85
|
-
setIpLocation(browserLocation);
|
86
|
-
} catch (browserError) {
|
87
|
-
console.log('Géolocalisation navigateur échouée, tentative par IP...', browserError);
|
88
|
-
|
89
|
-
// Fallback sur la géolocalisation par IP
|
90
|
-
const ipLocation = await getLocationByIP();
|
91
|
-
if (ipLocation) {
|
92
|
-
setIpLocation(ipLocation);
|
93
|
-
} else {
|
94
|
-
// Fallback final sur une position par défaut (centre du monde)
|
95
|
-
setIpLocation({ lat: 20, lng: 0 });
|
96
|
-
}
|
97
|
-
}
|
98
|
-
};
|
99
|
-
|
100
|
-
initializeLocation();
|
101
|
-
}, []);
|
102
31
|
|
103
32
|
const parseWKTLineString = (wkt: string): [number, number][] => {
|
104
33
|
try {
|
@@ -123,20 +52,18 @@ const MapView: React.FC<MapViewProps> = ({
|
|
123
52
|
|
124
53
|
useEffect(() => {
|
125
54
|
if (mapContainerRef.current && !mapRef.current) {
|
126
|
-
// Position par défaut centrée sur le monde, sera mise à jour par la géolocalisation
|
127
|
-
const defaultCenter = ipLocation || { lat: 20, lng: 0 };
|
128
|
-
|
129
55
|
mapRef.current = L.map(mapContainerRef.current, {
|
130
|
-
center: [
|
131
|
-
zoom:
|
132
|
-
minZoom:
|
133
|
-
maxZoom:
|
134
|
-
|
56
|
+
center: [7.365, 12.3], // Centre approximatif du Cameroun
|
57
|
+
zoom: 7, // Zoom ajusté pour voir l'ensemble du Cameroun
|
58
|
+
minZoom: 6,
|
59
|
+
maxZoom: 16,
|
60
|
+
maxBounds: [[1.65, 8.4], [13.08, 16.2]], // Limites pour le Cameroun
|
61
|
+
maxBoundsViscosity: 1.0,
|
135
62
|
});
|
136
63
|
|
137
64
|
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
138
65
|
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>',
|
139
|
-
maxZoom:
|
66
|
+
maxZoom: 16,
|
140
67
|
}).addTo(mapRef.current);
|
141
68
|
|
142
69
|
L.Icon.Default.mergeOptions({
|
@@ -164,41 +91,46 @@ const MapView: React.FC<MapViewProps> = ({
|
|
164
91
|
});
|
165
92
|
}
|
166
93
|
|
167
|
-
// Mettre à jour le centre de la carte quand la localisation par IP est disponible
|
168
|
-
if (mapRef.current && ipLocation && !userLocation && !searchedPlace && !routes) {
|
169
|
-
mapRef.current.setView([ipLocation.lat, ipLocation.lng], 12, { animate: true });
|
170
|
-
|
171
|
-
// Ajouter un marqueur pour la position détectée
|
172
|
-
if (!markerRef.current) {
|
173
|
-
markerRef.current = L.marker([ipLocation.lat, ipLocation.lng])
|
174
|
-
.addTo(mapRef.current)
|
175
|
-
.bindPopup(`<b>Votre position approximative</b><br>Détectée par IP<br>Lat: ${ipLocation.lat.toFixed(6)}<br>Lng: ${ipLocation.lng.toFixed(6)}`)
|
176
|
-
.openPopup();
|
177
|
-
}
|
178
|
-
}
|
179
|
-
|
180
94
|
return () => {
|
181
95
|
if (mapRef.current) {
|
182
96
|
mapRef.current.remove();
|
183
97
|
mapRef.current = null;
|
184
98
|
}
|
185
99
|
};
|
186
|
-
}, [apiClient
|
100
|
+
}, [apiClient]);
|
187
101
|
|
188
102
|
useEffect(() => {
|
189
103
|
if (!mapRef.current) return;
|
190
104
|
|
191
|
-
|
192
|
-
if (
|
193
|
-
|
105
|
+
// Nettoyer les couches précédentes
|
106
|
+
if (routeLayerRef.current) {
|
107
|
+
routeLayerRef.current.clearLayers();
|
108
|
+
}
|
109
|
+
if (markerRef.current) {
|
110
|
+
markerRef.current.remove();
|
111
|
+
markerRef.current = null;
|
112
|
+
}
|
113
|
+
if (clickMarkerRef.current) {
|
114
|
+
clickMarkerRef.current.remove();
|
115
|
+
clickMarkerRef.current = null;
|
116
|
+
}
|
117
|
+
|
194
118
|
routePolylinesRef.current = [];
|
195
119
|
|
120
|
+
// Fonction pour centrer la carte sur un point avec un marqueur
|
196
121
|
const centerOnPoint = async (lat: number, lng: number, placeName: string, zoom: number = 16) => {
|
197
122
|
let displayName = placeName;
|
198
123
|
if (placeName === 'Votre position') {
|
199
124
|
const closestPlace = await apiClient.findClosestPlace(lat, lng);
|
200
125
|
displayName = closestPlace?.name || placeName;
|
201
126
|
}
|
127
|
+
|
128
|
+
// Supprimer l'ancien marqueur s'il existe
|
129
|
+
if (markerRef.current) {
|
130
|
+
markerRef.current.remove();
|
131
|
+
markerRef.current = null;
|
132
|
+
}
|
133
|
+
|
202
134
|
mapRef.current!.setView([lat, lng], zoom, { animate: true });
|
203
135
|
markerRef.current = L.marker([lat, lng])
|
204
136
|
.addTo(mapRef.current!)
|
@@ -207,6 +139,7 @@ const MapView: React.FC<MapViewProps> = ({
|
|
207
139
|
};
|
208
140
|
|
209
141
|
if (routes && routes.length > 0) {
|
142
|
+
// Gérer les itinéraires
|
210
143
|
let allCoordinates: [number, number][] = [];
|
211
144
|
routes.forEach((route, index) => {
|
212
145
|
const coordinates: [number, number][] = [];
|
@@ -276,14 +209,10 @@ const MapView: React.FC<MapViewProps> = ({
|
|
276
209
|
centerOnPoint(searchedPlace.coordinates.lat, searchedPlace.coordinates.lng, searchedPlace.name);
|
277
210
|
} else if (userLocation) {
|
278
211
|
centerOnPoint(userLocation.latitude, userLocation.longitude, 'Votre position');
|
279
|
-
} else if (ipLocation) {
|
280
|
-
// Centrer sur la position IP si aucune autre position n'est disponible
|
281
|
-
centerOnPoint(ipLocation.lat, ipLocation.lng, 'Votre position approximative', 12);
|
282
212
|
} else {
|
283
|
-
|
284
|
-
mapRef.current!.setView([20, 0], 2, { animate: true });
|
213
|
+
mapRef.current!.setView([7.365, 12.3], 7, { animate: true });
|
285
214
|
}
|
286
|
-
}, [apiClient, userLocation, searchedPlace, routes, selectedRouteIndex, setSelectedRouteIndex
|
215
|
+
}, [apiClient, userLocation, searchedPlace, routes, selectedRouteIndex, setSelectedRouteIndex]);
|
287
216
|
|
288
217
|
return <div className="w-full h-screen" ref={mapContainerRef} />;
|
289
218
|
};
|