From 562c85079dca62886d73720015da03313dc6ba6f Mon Sep 17 00:00:00 2001 From: marco Date: Tue, 28 Jan 2025 16:34:25 +0100 Subject: [PATCH] implemented map view with markers for every floodstation --- lib/pages/map_page.dart | 67 +++++++++++++++++++++++- lib/services/flood_station_provider.dart | 14 +++++ lib/widgets/custom_marker.dart | 15 ++++++ pubspec.yaml | 5 +- 4 files changed, 98 insertions(+), 3 deletions(-) create mode 100644 lib/widgets/custom_marker.dart diff --git a/lib/pages/map_page.dart b/lib/pages/map_page.dart index 3f4ac10..c5b1d57 100644 --- a/lib/pages/map_page.dart +++ b/lib/pages/map_page.dart @@ -1,11 +1,74 @@ import 'package:flutter/material.dart'; +import 'package:flutter_map/flutter_map.dart'; +import 'package:flutter_map_cancellable_tile_provider/flutter_map_cancellable_tile_provider.dart'; +import 'package:flutter_map_marker_cluster/flutter_map_marker_cluster.dart'; +import 'package:latlong2/latlong.dart'; +import 'package:provider/provider.dart'; -class MapPage extends StatelessWidget { +import '../services/flood_station_provider.dart'; + +class MapPage extends StatefulWidget { const MapPage({super.key}); static const routeName = '/map'; + @override + State createState() => _MapPageState(); +} + +class _MapPageState extends State { + final mapController = MapController(); + @override Widget build(BuildContext context) { - return const Placeholder(); + final floodStationProvider = context.watch(); + if (floodStationProvider.allStations.isEmpty) { + return Center( + child: ElevatedButton( + onPressed: floodStationProvider.loadAllStations, + child: Text('Load Map'), + ), + ); + } + return FlutterMap( + mapController: mapController, + options: MapOptions( + initialCenter: LatLng(54.81, -4.42), + initialZoom: 6, + ), + children: [ + openStreetMapTileLayer, + MarkerClusterLayerWidget( + options: MarkerClusterLayerOptions( + maxClusterRadius: 45, + size: Size(30, 30), + alignment: Alignment.center, + padding: EdgeInsets.all(50), + maxZoom: 15, + markers: floodStationProvider.stationsAsMarkers, + builder: _markerBuilder), + ) + ], + ); + } + + Widget _markerBuilder(BuildContext context, List markers) { + return Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(20), + color: Theme.of(context).colorScheme.tertiary, + ), + child: Center( + child: Text( + markers.length.toString(), + style: const TextStyle(color: Colors.white), + ), + ), + ); } } + +TileLayer get openStreetMapTileLayer => TileLayer( + urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png', + userAgentPackageName: 'dev.fleaflet.flutter_map.example', + tileProvider: CancellableNetworkTileProvider(), + ); diff --git a/lib/services/flood_station_provider.dart b/lib/services/flood_station_provider.dart index 972c71c..2674adb 100644 --- a/lib/services/flood_station_provider.dart +++ b/lib/services/flood_station_provider.dart @@ -1,7 +1,10 @@ import 'package:flutter/material.dart'; import 'package:async/async.dart'; +import 'package:flutter_map/flutter_map.dart'; +import 'package:latlong2/latlong.dart'; import '../model/flood_station.dart'; +import '../widgets/custom_marker.dart'; import 'api.dart'; class FloodStationProvider extends ChangeNotifier { @@ -13,6 +16,17 @@ class FloodStationProvider extends ChangeNotifier { List get allStations => _allStations; List get filteredStations => _filteredStations; + List get stationsAsMarkers { + return allStations + .map( + (e) => Marker( + alignment: Alignment.center, + point: LatLng(e.lat, e.long), + child: CustomMarker(), + ), + ) + .toList(); + } CancelableOperation? _filteredStationsFuture; diff --git a/lib/widgets/custom_marker.dart b/lib/widgets/custom_marker.dart new file mode 100644 index 0000000..a7a6c4c --- /dev/null +++ b/lib/widgets/custom_marker.dart @@ -0,0 +1,15 @@ +import 'package:flutter/material.dart'; + +class CustomMarker extends StatelessWidget { + const CustomMarker({super.key, this.label}); + final String? label; + + @override + Widget build(BuildContext context) { + return Icon( + Icons.location_on_sharp, + color: Theme.of(context).colorScheme.primary, + size: 30, + ); + } +} diff --git a/pubspec.yaml b/pubspec.yaml index b722710..b6b2154 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,10 @@ dependencies: provider: ^6.1.2 timezone: ^0.10.0 async: ^2.11.0 - flutter_osm_plugin: ^1.3.6 + flutter_map: ^7.0.2 + flutter_map_cancellable_tile_provider: ^3.0.2 + latlong2: ^0.9.1 + flutter_map_marker_cluster: ^1.4.0 dev_dependencies: flutter_test: