import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:mapbox_maps_flutter/mapbox_maps_flutter.dart'; class IdelHomeMapboxWidget extends StatefulWidget { final MapPosition? currentLocation; final double currentZoomLevel; final String? customMarkerIconPath; // Path to custom marker asset final List? nearestTaxis; // List of taxi positions final void Function(MapboxMap)? onMapCreated; final String? customTaxiIconPath; // Optional custom taxi icon const IdelHomeMapboxWidget({ Key? key, required this.currentLocation, required this.currentZoomLevel, this.customMarkerIconPath, required this.onMapCreated, this.nearestTaxis, this.customTaxiIconPath, }) : super(key: key); @override State createState() => _IdelHomeMapboxWidgetState(); } class _IdelHomeMapboxWidgetState extends State { MapboxMap? mapboxMap; @override Widget build(BuildContext context) { if (widget.currentLocation == null) { return const Center(child: CircularProgressIndicator()); } return MapWidget( key: const ValueKey("mapWidget"), cameraOptions: CameraOptions( center: Point( coordinates: Position( widget.currentLocation!.lng, widget.currentLocation!.lat, ), ), zoom: widget.currentZoomLevel, bearing: 0.0, pitch: 0.0, // equivalent to tilt: 0 ), styleUri: MapboxStyles.MAPBOX_STREETS, // You can change this style onMapCreated: _onMapCreated, ); } void _onMapCreated(MapboxMap mapboxMap) async { this.mapboxMap = mapboxMap; // Disable gestures similar to Google Maps version await _configureMapSettings(); // Call the parent's onMapCreated callback if (widget.onMapCreated != null) { widget.onMapCreated!(mapboxMap); } // Add markers after map is created await _addMarkers(); } Future _configureMapSettings() async { if (mapboxMap == null) return; try { // Disable rotation and pitch gestures await mapboxMap!.gestures.updateSettings( GesturesSettings( rotateEnabled: false, pitchEnabled: false, ), ); } catch (e) { debugPrint('Error configuring map settings: $e'); } } Future _addMarkers() async { if (mapboxMap == null || widget.currentLocation == null) return; // Add user location marker await _addUserMarker(); // Add taxi markers if (widget.nearestTaxis != null && widget.nearestTaxis!.isNotEmpty) { await _addTaxiMarkers(); } } Future _addUserMarker() async { try { // Create point annotation manager final pointAnnotationManager = await mapboxMap!.annotations.createPointAnnotationManager(); // Prepare image data if custom icon is provided Uint8List? imageData; if (widget.customMarkerIconPath != null) { final ByteData bytes = await rootBundle.load(widget.customMarkerIconPath!); imageData = bytes.buffer.asUint8List(); } // Create user marker options final pointAnnotationOptions = PointAnnotationOptions( geometry: Point( coordinates: Position( widget.currentLocation!.lng, widget.currentLocation!.lat, ), ), image: imageData, ); // Add the annotation await pointAnnotationManager.create(pointAnnotationOptions); } catch (e) { debugPrint('Error adding user marker: $e'); } } Future _addTaxiMarkers() async { try { // Create point annotation manager for taxis final taxiAnnotationManager = await mapboxMap!.annotations.createPointAnnotationManager(); final taxiAnnotationOptions = []; // Prepare taxi image data if provided Uint8List? taxiImageData; if (widget.customTaxiIconPath != null) { final ByteData bytes = await rootBundle.load(widget.customTaxiIconPath!); taxiImageData = bytes.buffer.asUint8List(); } // Create taxi markers (limit to 10 as in original) final taxisToShow = widget.nearestTaxis!.take(10); for (final taxi in taxisToShow) { final annotationOptions = PointAnnotationOptions( geometry: Point( coordinates: Position( taxi.lng, taxi.lat, ), ), image: taxiImageData, ); taxiAnnotationOptions.add(annotationOptions); } // Add all taxi annotations await taxiAnnotationManager.createMulti(taxiAnnotationOptions); } catch (e) { debugPrint('Error adding taxi markers: $e'); } } } // Custom Position class to avoid conflicts with Mapbox's Position class MapPosition { final double lat; final double lng; const MapPosition({required this.lat, required this.lng}); // Convert from Google Maps LatLng if needed factory MapPosition.fromLatLng(dynamic latLng) { return MapPosition(lat: latLng.latitude, lng: latLng.longitude); } // Convert to list for Mapbox coordinates [lng, lat] List toCoordinates() => [lng, lat]; }