Files
floodwatch/lib/pages/map_page.dart

114 lines
3.3 KiB
Dart

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';
import '../model/flood_station.dart';
import '../services/flood_station_provider.dart';
import '../widgets/custom_marker.dart';
class MapPage extends StatefulWidget {
const MapPage({super.key});
static const routeName = '/map';
@override
State<MapPage> createState() => _MapPageState();
}
class _MapPageState extends State<MapPage> {
final mapController = MapController();
@override
Widget build(BuildContext context) {
final floodStationProvider = context.watch<FloodStationProvider>();
if (floodStationProvider.allStations.isEmpty) {
return Center(
child: ElevatedButton(
onPressed: floodStationProvider.loadAllStations,
child: Text('Load Map'),
),
);
}
return FlutterMap(
mapController: mapController,
options: MapOptions(
cameraConstraint: CameraConstraint.containCenter(
bounds: LatLngBounds.fromPoints(floodStationProvider.allStations
.map<LatLng>(
(e) => LatLng(e.lat, e.long),
)
.toList())),
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: _stationsAsMarkers(floodStationProvider.allStations),
builder: _markerBuilder),
)
],
);
}
Widget _markerBuilder(BuildContext context, List<Marker> 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),
),
),
);
}
List<Marker> _stationsAsMarkers(List<FloodStation> stations) {
return stations
.map<Marker>(
(station) => Marker(
alignment: Alignment.center,
point: LatLng(station.lat, station.long),
child: CustomMarker(
onTap: () => _markerTapped(station),
),
),
)
.toList();
}
_markerTapped(FloodStation station) {
showDialog(
context: context,
builder: (context) {
return Center(
child: Card(
child: SizedBox(
width: 300,
height: 300,
child: Text(station.label),
),
),
);
},
);
}
}
TileLayer get openStreetMapTileLayer => TileLayer(
urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
userAgentPackageName: 'dev.fleaflet.flutter_map.example',
tileProvider: CancellableNetworkTileProvider(),
);