import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:syncfusion_flutter_core/theme.dart'; import 'package:syncfusion_flutter_maps/maps.dart'; import '../consts.dart'; import '../data_classes.dart'; /// ChoroplethMap is a stateful widget that contains a choropleth map. /// The map is created using the Syncfusion Flutter Maps library and /// coordinates fetched from the server. class ChoroplethMap extends StatefulWidget { const ChoroplethMap({ Key? key, required this.relation, required this.measurements, required this.subdivisions, required this.onSelectionChanged, }) : super(key: key); final Uint8List relation; final List<Measurement> measurements; final List<SubDiv> subdivisions; final void Function(int selectedIndex) onSelectionChanged; @override ChoroplethMapState createState() => ChoroplethMapState(); } class ChoroplethMapState extends State<ChoroplethMap> { int selectedIndex = -1; // Subdivision/map tile index late MapShapeSource dataSource; late final MapZoomPanBehavior _zoomPanBehavior = MapZoomPanBehavior(); void updateDataSource() { _initDataSource(); } @override void initState() { super.initState(); _initDataSource(); } void _initDataSource() { dataSource = MapShapeSource.memory( widget.relation, shapeDataField: 'sub_div_id', dataCount: widget.subdivisions.length, primaryValueMapper: (int index) => widget.subdivisions[index].sub_div_id, shapeColorValueMapper: (int index) => widget.subdivisions[index].avgThickness, // NB will later be minThickness shapeColorMappers: const [ MapColorMapper( from: 0, to: 4, color: Color(0xffff0000), text: '{0},{1}'), MapColorMapper( from: 4, to: 8, color: Color(0xffff6a00), text: '2'), MapColorMapper( from: 8, to: 12, color: Color(0xFFb1ff00), text: '3'), MapColorMapper( from: 12, to: 400, color: Color(0xFF00d6ff), text: '4'), ], ); } @override Widget build(BuildContext context) { updateDataSource(); return Stack( children: [ SfMapsTheme( data: SfMapsThemeData( // Coloring of selected shape selectionStrokeWidth: 3.5, selectionStrokeColor: Colors.blue[600], ), child: SfMaps( layers: [ MapShapeLayer( source: dataSource, legend: MapLegend.bar( MapElement.shape, position: MapLegendPosition.bottom, segmentSize: const Size(70.0, 7.0), textStyle: smallTextStyle, ), zoomPanBehavior: _zoomPanBehavior, strokeColor: Colors.blue.shade50, strokeWidth: 1, // Shape selection selectedIndex: selectedIndex, onSelectionChanged: (int index) { setState(() { selectedIndex = index; }); widget.onSelectionChanged(selectedIndex); }, ), ], ), ), ], ); } }