Skip to content
Snippets Groups Projects
choropleth_map.dart 3.23 KiB
Newer Older
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:syncfusion_flutter_core/theme.dart';
import 'package:syncfusion_flutter_maps/maps.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.onSelectionChanged,
  }) : super(key: key);

  final Uint8List relation;
  final List<Measurement> measurements;
  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();
  final List<SubDiv> _subdivisions = <SubDiv>[];

  @override
  void initState() {
    super.initState();
    // Extract all _subdivisions from list of measurements
    for (Measurement measurement in widget.measurements) {
      for (SubDiv subdivision in measurement.subDivs) {
        _subdivisions.add(subdivision);

    // Initialise data source
    _dataSource = MapShapeSource.memory(
      widget.relation,
      shapeDataField: 'sub_div_id',
      dataCount: _subdivisions.length,
      primaryValueMapper: (int index) => _subdivisions[index].sub_div_id,
      shapeColorValueMapper: (int index) => _subdivisions[index].avgThickness, // NB will later be minThickness
      shapeColorMappers: const [
        MapColorMapper(
            from: -2,
            to: -1,
            color: Color(0xFF8C8C8C),
            text: '>8'),
      MapColorMapper(
          from: 0,
          to: 4,
          color: Color(0xFFff0000),
          text: '{0},{4}'),
      MapColorMapper(
          from: 4,
          color: Color(0xffff6a00),
      MapColorMapper(
          color: Color(0xFFb1ff00),
      MapColorMapper(
          color: Color(0xFF00d6ff),
          text: '>8'),

  @override
  Widget build(BuildContext context) {
    print("Map built!");
    return Stack(
      children: [
          data: SfMapsThemeData( // Coloring of selected shape
            selectionStrokeWidth: 3.5,
            selectionStrokeColor: Colors.blue[600],
          ),
          child: SfMaps(
            layers: [
              MapShapeLayer(
                zoomPanBehavior: _zoomPanBehavior,
                strokeColor: Colors.blue.shade50,
                // Shape selection
                selectedIndex: _selectedIndex,
                onSelectionChanged: (int index) {
                    _selectedIndex = index;
                  widget.onSelectionChanged(_selectedIndex);