Getting Started with Flutter Maps (SfMaps)

18 Nov 201820 minutes to read

This section explains the steps required to add the maps widget with shape layer and its elements such as data labels, tooltip, assignable colors based on region, and legends. It also explains about adding tile layer with OpenStreetMap. This section covers only basic features needed to know to get started with Syncfusion® maps.

To get started quickly with our Flutter Maps widget, you can check on this video.

Add Flutter maps to an application

Create a simple project using the instructions given in the Getting Started with your first Flutter app documentation.

Add dependency

Add the Syncfusion® Flutter maps dependency to your pubspec.yaml file.

dependencies:

syncfusion_flutter_maps: ^xx.x.xx

NOTE

Here xx.x.xx denotes the current version of Syncfusion Flutter Maps package. It is recommended to use the latest available version from pub.dev.

Get packages

Run the following command to get the required packages.

$ flutter pub get

Import package

Import the following package in your Dart code.

import 'package:syncfusion_flutter_maps/maps.dart';

Initialize maps

After importing the package, initialize the maps widget as a child of any widget.

import 'package:flutter/material.dart';
import 'package:syncfusion_flutter_maps/maps.dart';

class MapsExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: SfMaps(
          layers: [
            MapShapeLayer(
              source: MapShapeSource.asset(
                'assets/australia.json',
                shapeDataField: 'STATE_NAME',
              ),
            ),
          ],
        ),
      ),
    );
  }
}

Set GeoJSON data for shape layer from various sources

The layers in SfMaps contains collection of either MapShapeLayer or MapTileLayer. The actual geographical rendering is done in each MapShapeLayer. The source property of the MapShapeLayer is of type MapShapeSource. The source can be set as the .json source from an asset bundle, from network or from Uint8List as bytes. Use the respective constructor depending on the source type.

The shapeDataField property of the MapShapeSource is used to refer to the unique field name in the .json source to identify each shape. In Mapping the data source section of this document, this shapeDataField will be used to map with the respective value returned in primaryValueMapper from the data source.

IMPORTANT

The Mercator projection is the default projection in the maps.

From asset bundle

Load .json data from an asset bundle.

NOTE

If you are using the MapShapeSource.asset constructor, you must add the .json file to the assets folder of your root directory and refer the json file path in the pubspec.yaml file as shown in the code snippet below. You can get the australia.json file here.

flutter:
  uses-material-design: true
  assets:
    - australia.json
import 'package:flutter/material.dart';
import 'package:syncfusion_flutter_maps/maps.dart';

class MapsExample extends StatefulWidget {
  @override
  _MapsExampleState createState() => _MapsExampleState();
}

class _MapsExampleState extends State<MapsExample> {
  late MapShapeSource _dataSource;

  @override
  void initState() {
    _dataSource = MapShapeSource.asset(
      'assets/australia.json',
      shapeDataField: 'STATE_NAME',
    );
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Padding(
        padding: EdgeInsets.all(15),
        child: SfMaps(
          layers: [
            MapShapeLayer(source: _dataSource),
          ],
        ),
      ),
    );
  }
}

From network

Load .json data from the network.

import 'package:flutter/material.dart';
import 'package:syncfusion_flutter_maps/maps.dart';

class MapsExample extends StatefulWidget {
  @override
  _MapsExampleState createState() => _MapsExampleState();
}

class _MapsExampleState extends State<MapsExample> {
  late MapShapeSource _dataSource;

  @override
  void initState() {
    _dataSource = MapShapeSource.network(
      'http://www.json-generator.com/api/json/get/bVqXoJvfjC?indent=2',
       shapeDataField: 'name',
    );
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Padding(
        padding: EdgeInsets.all(15),
        child: SfMaps(
          layers: [
            MapShapeLayer(source: _dataSource),
          ],
        ),
      ),
    );
  }
}

From memory

Load .json data as bytes from Uint8List.

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:syncfusion_flutter_maps/maps.dart';
import 'dart:typed_data';

class MapsExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: FutureBuilder(
        future: _fetchJsonData(),
        builder: (BuildContext context, snapshot) {
          if (snapshot.hasData) {
            Uint8List bytesData = snapshot.data as Uint8List;
            return SfMaps(
              layers: [
                MapShapeLayer(
                  source: MapShapeSource.memory(
                    bytesData,
                    shapeDataField: 'STATE_NAME',
                  ),
                ),
              ],
            );
          } else {
            return CircularProgressIndicator();
          }
        },
      ),
    );
  }

  Future<Uint8List> _fetchJsonData() async {
    return (await rootBundle.load('assets/australia.json')).buffer.asUint8List();
  }
}

maps basic view

Mapping the data source for shape layer

By default, the value specified for the shapeDataField in the GeoJSON source will be used in the elements like data labels, tooltip, and legend for their respective shapes. However, it is possible to keep a data source and customize these elements based on the requirement. As mentioned above, shapeDataField will be used to map with the respective value returned in primaryValueMapper from the data source.

import 'package:flutter/material.dart';
import 'package:syncfusion_flutter_maps/maps.dart';

class MapsExample extends StatefulWidget {
  @override
  _MapsExampleState createState() => _MapsExampleState();
}

class _MapsExampleState extends State<MapsExample> {
  late List<Model> data;

  @override
  void initState() {
    data = <Model>[
      Model('New South Wales',
       '       New\nSouth Wales'),
      Model('Queensland', 'Queensland'),
      Model('Northern Territory', 'Northern\nTerritory'),
      Model('Victoria', 'Victoria'),
      Model('South Australia', 'South Australia'),
      Model('Western Australia', 'Western Australia'),
      Model('Tasmania', 'Tasmania'),
      Model('Australian Capital Territory', 'ACT')
    ];

    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SfMaps(
         layers: <MapShapeLayer>[
           MapShapeLayer(
             source: MapShapeSource.asset(
               'assets/australia.json',
               shapeDataField: 'STATE_NAME',
               dataCount: data.length,
               primaryValueMapper: (int index) => data[index].state,
             ),
           ),
         ],
       ),
     );
  }
}

class Model {
  Model(this.state, this.stateCode);

  String state;
  String stateCode;
}

NOTE

Add shape layer maps elements

Add the basic maps elements such as data labels, legend, and tooltip as shown in the code snippet below.

import 'package:flutter/material.dart';
import 'package:syncfusion_flutter_maps/maps.dart';

class MapsExample extends StatefulWidget {
  @override
  _MapsExampleState createState() => _MapsExampleState();
}

class _MapsExampleState extends State<MapsExample> {
  late List<Model> data;
  late MapShapeSource dataSource;

  @override
  void initState() {
    data = <Model>[
      Model('New South Wales', Color.fromRGBO(255, 215, 0, 1.0),
          '       New\nSouth Wales'),
      Model('Queensland', Color.fromRGBO(72, 209, 204, 1.0), 'Queensland'),
      Model('Northern Territory', Colors.red.withOpacity(0.85),
          'Northern\nTerritory'),
      Model('Victoria', Color.fromRGBO(171, 56, 224, 0.75), 'Victoria'),
      Model('South Australia', Color.fromRGBO(126, 247, 74, 0.75),
          'South Australia'),
      Model('Western Australia', Color.fromRGBO(79, 60, 201, 0.7),
          'Western Australia'),
      Model('Tasmania', Color.fromRGBO(99, 164, 230, 1), 'Tasmania'),
      Model('Australian Capital Territory', Colors.teal, 'ACT')
    ];

    dataSource = MapShapeSource.asset(
      'assets/australia.json',
      shapeDataField: 'STATE_NAME',
      dataCount: data.length,
      primaryValueMapper: (int index) => data[index].state,
      dataLabelMapper: (int index) => data[index].stateCode,
      shapeColorValueMapper: (int index) => data[index].color,
    );
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    final ThemeData themeData = Theme.of(context);
    return Scaffold(
      body: Center(
        child: SizedBox(
          height: MediaQuery.of(context).size.height * 0.55,
          child: SfMaps(
            layers: <MapShapeLayer>[
              MapShapeLayer(
                source: dataSource,
                showDataLabels: true,
                legend: MapLegend(MapElement.shape),
                shapeTooltipBuilder: (BuildContext context, int index) {
                  return Padding(
                    padding: const EdgeInsets.all(7),
                    child: Text(data[index].stateCode,
                        style: themeData.textTheme.labelSmall!
                            .copyWith(color: themeData.colorScheme.surface)),
                  );
                },
                tooltipSettings: MapTooltipSettings(
                    color: Colors.grey[700],
                    strokeColor: Colors.white,
                    strokeWidth: 2),
                strokeColor: Colors.white,
                strokeWidth: 0.5,
                dataLabelSettings: MapDataLabelSettings(
                    textStyle: TextStyle(
                        color: Colors.black,
                        fontWeight: FontWeight.bold,
                        fontSize: themeData.textTheme.labelSmall!.fontSize)),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

class Model {
  Model(this.state, this.color, this.stateCode);

  String state;
  Color color;
  String stateCode;
}

Maps getting started

Add tile layer

The MapTileLayer needs to be added in the layers collection in SfMaps. The URL of the providers must be set in the MapTileLayer.urlTemplate property.

Refer to the tile layer section for more information.

import 'package:flutter/material.dart';
import 'package:syncfusion_flutter_maps/maps.dart';

class MapsExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return SfMaps(
      layers: [
        MapTileLayer(
          urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
        ),
      ],
    );
  }
}

Maps tile layer getting started

NOTE

You can refer to our Flutter Maps feature tour page for its groundbreaking feature representations. You can also explore our Flutter Maps example that shows how to configure a Maps in Flutter.