Restructuration majeure du projet: migration de flutt vers app, ajout de l'API et mise à jour du site web
This commit is contained in:
204
app/lib/presentation/widgets/mapbox_map.dart
Normal file
204
app/lib/presentation/widgets/mapbox_map.dart
Normal file
@@ -0,0 +1,204 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_map/flutter_map.dart';
|
||||
import 'package:latlong2/latlong.dart';
|
||||
import 'package:geosector_app/core/constants/app_keys.dart';
|
||||
import 'package:geosector_app/app.dart'; // Pour accéder à l'instance globale de ApiService
|
||||
|
||||
/// Widget de carte réutilisable utilisant Mapbox
|
||||
///
|
||||
/// Ce widget encapsule un FlutterMap avec des tuiles Mapbox et fournit
|
||||
/// des fonctionnalités pour afficher des marqueurs, des polygones et des contrôles.
|
||||
class MapboxMap extends StatefulWidget {
|
||||
/// Position initiale de la carte
|
||||
final LatLng initialPosition;
|
||||
|
||||
/// Niveau de zoom initial
|
||||
final double initialZoom;
|
||||
|
||||
/// Liste des marqueurs à afficher
|
||||
final List<Marker>? markers;
|
||||
|
||||
/// Liste des polygones à afficher
|
||||
final List<Polygon>? polygons;
|
||||
|
||||
/// Contrôleur de carte externe (optionnel)
|
||||
final MapController? mapController;
|
||||
|
||||
/// Callback appelé lorsque la carte est déplacée
|
||||
final void Function(MapEvent)? onMapEvent;
|
||||
|
||||
/// Afficher les boutons de contrôle (zoom, localisation)
|
||||
final bool showControls;
|
||||
|
||||
/// Style de la carte Mapbox (optionnel)
|
||||
/// Si non spécifié, utilise le style par défaut 'mapbox/streets-v12'
|
||||
final String? mapStyle;
|
||||
|
||||
const MapboxMap({
|
||||
super.key,
|
||||
this.initialPosition = const LatLng(48.1173, -1.6778), // Rennes par défaut
|
||||
this.initialZoom = 13.0,
|
||||
this.markers,
|
||||
this.polygons,
|
||||
this.mapController,
|
||||
this.onMapEvent,
|
||||
this.showControls = true,
|
||||
this.mapStyle,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MapboxMap> createState() => _MapboxMapState();
|
||||
}
|
||||
|
||||
class _MapboxMapState extends State<MapboxMap> {
|
||||
/// Contrôleur de carte interne
|
||||
late final MapController _mapController;
|
||||
|
||||
/// Niveau de zoom actuel
|
||||
double _currentZoom = 13.0;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_mapController = widget.mapController ?? MapController();
|
||||
_currentZoom = widget.initialZoom;
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
// Ne pas disposer le contrôleur s'il a été fourni de l'extérieur
|
||||
if (widget.mapController == null) {
|
||||
_mapController.dispose();
|
||||
}
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
/// Construit un bouton de contrôle de carte
|
||||
Widget _buildMapButton({
|
||||
required IconData icon,
|
||||
required VoidCallback onPressed,
|
||||
}) {
|
||||
return Container(
|
||||
width: 40,
|
||||
height: 40,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
shape: BoxShape.circle,
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.2),
|
||||
blurRadius: 6,
|
||||
offset: const Offset(0, 3),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: IconButton(
|
||||
icon: Icon(icon, size: 20),
|
||||
onPressed: onPressed,
|
||||
padding: EdgeInsets.zero,
|
||||
constraints: const BoxConstraints(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// Déterminer l'URL du template de tuiles Mapbox
|
||||
// Utiliser l'environnement actuel pour obtenir la bonne clé API
|
||||
final String environment = apiService.getCurrentEnvironment();
|
||||
final String mapboxToken = AppKeys.getMapboxApiKey(environment);
|
||||
final String mapStyle = widget.mapStyle ?? 'mapbox/streets-v11';
|
||||
final String urlTemplate =
|
||||
'https://api.mapbox.com/styles/v1/$mapStyle/tiles/256/{z}/{x}/{y}@2x?access_token=$mapboxToken';
|
||||
|
||||
return Stack(
|
||||
children: [
|
||||
// Carte principale
|
||||
FlutterMap(
|
||||
mapController: _mapController,
|
||||
options: MapOptions(
|
||||
initialCenter: widget.initialPosition,
|
||||
initialZoom: widget.initialZoom,
|
||||
onMapEvent: (event) {
|
||||
if (event is MapEventMove) {
|
||||
setState(() {
|
||||
// Dans flutter_map 8.1.1, nous devons utiliser le contrôleur pour obtenir le zoom actuel
|
||||
_currentZoom = _mapController.camera.zoom;
|
||||
});
|
||||
}
|
||||
|
||||
// Appeler le callback externe si fourni
|
||||
if (widget.onMapEvent != null) {
|
||||
widget.onMapEvent!(event);
|
||||
}
|
||||
},
|
||||
),
|
||||
children: [
|
||||
// Tuiles de la carte (Mapbox)
|
||||
TileLayer(
|
||||
urlTemplate: urlTemplate,
|
||||
userAgentPackageName: 'app.geosector.fr',
|
||||
maxNativeZoom: 19,
|
||||
additionalOptions: {
|
||||
'accessToken': mapboxToken,
|
||||
},
|
||||
),
|
||||
|
||||
// Polygones
|
||||
if (widget.polygons != null && widget.polygons!.isNotEmpty)
|
||||
PolygonLayer(polygons: widget.polygons!),
|
||||
|
||||
// Marqueurs
|
||||
if (widget.markers != null && widget.markers!.isNotEmpty)
|
||||
MarkerLayer(markers: widget.markers!),
|
||||
],
|
||||
),
|
||||
|
||||
// Boutons de contrôle
|
||||
if (widget.showControls)
|
||||
Positioned(
|
||||
bottom: 16,
|
||||
right: 16,
|
||||
child: Column(
|
||||
children: [
|
||||
// Bouton de zoom +
|
||||
_buildMapButton(
|
||||
icon: Icons.add,
|
||||
onPressed: () {
|
||||
_mapController.move(
|
||||
_mapController.camera.center,
|
||||
_mapController.camera.zoom + 1,
|
||||
);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
|
||||
// Bouton de zoom -
|
||||
_buildMapButton(
|
||||
icon: Icons.remove,
|
||||
onPressed: () {
|
||||
_mapController.move(
|
||||
_mapController.camera.center,
|
||||
_mapController.camera.zoom - 1,
|
||||
);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
|
||||
// Bouton de localisation
|
||||
_buildMapButton(
|
||||
icon: Icons.my_location,
|
||||
onPressed: () {
|
||||
_mapController.move(
|
||||
widget.initialPosition,
|
||||
15,
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user