How to Create a Choropleth Map in a Flutter Application

How to Create a Choropleth Map in a Flutter Application

Rajeshwari Pandinagarajan
Apr 8 · 7 min read

A choropleth map is a specialized type of geographic map in which regions are highlighted by color based on the data of those regions. They are appropriate for visualizing regional patterns in the data. The higher the value is, the darker the color will be in that region. This will be helpful to understand trends in the data with a quick look. In this blog post, I will explain you about how to create a choropleth map easily using the Syncfusion Flutter Maps widget.

Choropleth map works perfectly for showing data that depends on a single parameter. It is used to showcase the data of a region relative to the data of the nearby regions, like for population density, COVID-19 cases, GDP growth, and weather.

Add Choropleth maps to the Flutter Maps shape layer

We are going to create a choropleth map to show the world’s population density. For that, we need to render the basic world map first.

We are not going to focus on the initial rendering of the maps in this blog post. You can check out our existing dedicated blog, Introducing Flutter Maps Widget, for this. You can also check our Getting Started with Flutter Maps documentation.

Refer to the following code example to render the basic world map.

class _ChoroplethMapState extends State {List<_CountryDensityModel> _worldPopulationDensityDetails;MapShapeSource _mapShapeSource;@overridevoid initState() {super.initState();_mapShapeSource = MapShapeSource.asset('assets/world_map.json',shapeDataField: 'name',dataCount: _worldPopulationDensityDetails.length,primaryValueMapper: (int index) =>_worldPopulationDensityDetails[index].countryName,);}@overrideWidget build(BuildContext context) {return SfMaps(layers: [MapShapeLayer(source: _mapShapeSource,strokeColor: Colors.white30),],);}}
Render a basic map using a Flutter application

Then, we need the world population density data to be mapped. Let’s define a model and data for it as shown in the following.

List<_CountryDensityModel> _worldPopulationDensityDetails;@overridevoid initState() {super.initState();_worldPopulationDensityDetails = <_CountryDensityModel>[_CountryDensityModel('Monaco', 26337),_CountryDensityModel('Macao', 21717),_CountryDensityModel('Singapore', 8358),_CountryDensityModel('Hong kong', 7140),_CountryDensityModel('Gibraltar', 3369),_CountryDensityModel('Bahrain', 2239),_CountryDensityModel('Holy See', 1820),_CountryDensityModel('Maldives', 1802),_CountryDensityModel('Malta', 1380),_CountryDensityModel('Bangladesh', 1265),_CountryDensityModel('Sint Maarten', 1261),_CountryDensityModel('Bermuda', 1246),_CountryDensityModel('Channel Islands', 915),_CountryDensityModel('State of Palestine', 847),_CountryDensityModel('Saint-Martin', 729),_CountryDensityModel('Mayotte', 727),_CountryDensityModel('Taiwan', 672),_CountryDensityModel('Barbados', 668),_CountryDensityModel('Lebanon', 667),_CountryDensityModel('Mauritius', 626),_CountryDensityModel('Aruba', 593),_CountryDensityModel('San Marino', 565),_CountryDensityModel('Nauru', 541),_CountryDensityModel('Korea', 527),_CountryDensityModel('Rwanda', 525),_CountryDensityModel('Netherlands', 508),_CountryDensityModel('Comoros', 467),_CountryDensityModel('India', 464),_CountryDensityModel('Burundi', 463),_CountryDensityModel('Saint-Barthélemy', 449),_CountryDensityModel('Haiti', 413),_CountryDensityModel('Israel', 400),_CountryDensityModel('Tuvalu', 393),_CountryDensityModel('Belgium', 382),_CountryDensityModel('Curacao', 369),_CountryDensityModel('Philippines', 367),_CountryDensityModel('Reunion', 358),_CountryDensityModel('Martinique', 354),_CountryDensityModel('Japan', 346),_CountryDensityModel('Sri Lanka', 341),_CountryDensityModel('Grenada', 331),_CountryDensityModel('Marshall Islands', 328),_CountryDensityModel('Puerto Rico', 322),_CountryDensityModel('Vietnam', 313),_CountryDensityModel('El Salvador', 313),_CountryDensityModel('Guam', 312),_CountryDensityModel('Saint Lucia', 301),_CountryDensityModel('United States Virgin Islands', 298),_CountryDensityModel('Pakistan', 286),_CountryDensityModel('Saint Vincent and the Grenadines', 284),_CountryDensityModel('United Kingdom', 280),_CountryDensityModel('American Samoa', 276),_CountryDensityModel('Cayman Islands', 273),_CountryDensityModel('Jamaica', 273),_CountryDensityModel('Trinidad and Tobago', 272),_CountryDensityModel('Qatar', 248),_CountryDensityModel('Guadeloupe', 245),_CountryDensityModel('Luxembourg', 241),_CountryDensityModel('Germany', 240),_CountryDensityModel('Kuwait', 239),_CountryDensityModel('Gambia', 238),_CountryDensityModel('Liechtenstein', 238),_CountryDensityModel('Uganda', 228),_CountryDensityModel('Sao Tome and Principe', 228),_CountryDensityModel('Nigeria', 226),_CountryDensityModel('Dominican Rep.', 224),_CountryDensityModel('Antigua and Barbuda', 222),_CountryDensityModel('Switzerland', 219),_CountryDensityModel('Dem. Rep. Korea', 214),_CountryDensityModel('Seychelles', 213),_CountryDensityModel('Italy', 205),_CountryDensityModel('Saint Kitts and Nevis', 204),_CountryDensityModel('Nepal', 203),_CountryDensityModel('Malawi', 202),_CountryDensityModel('British Virgin Islands', 201),_CountryDensityModel('Guatemala', 167),_CountryDensityModel('Anguilla', 166),_CountryDensityModel('Andorra', 164),_CountryDensityModel('Micronesia', 164),_CountryDensityModel('China', 153),_CountryDensityModel('Togo', 152),_CountryDensityModel('Indonesia', 151),_CountryDensityModel('Isle of Man', 149),_CountryDensityModel('Kiribati', 147),_CountryDensityModel('Tonga', 146),_CountryDensityModel('Czech Rep.', 138),_CountryDensityModel('Cabo Verde', 138),_CountryDensityModel('Thailand', 136),_CountryDensityModel('Ghana', 136),_CountryDensityModel('Denmark', 136),_CountryDensityModel('Tokelau', 135),_CountryDensityModel('Cyprus', 130),_CountryDensityModel('Northern Mariana Islands', 125),_CountryDensityModel('Poland', 123),_CountryDensityModel('Moldova', 122),_CountryDensityModel('Azerbaijan', 122),_CountryDensityModel('France', 119),_CountryDensityModel('United Arab Emirates', 118),_CountryDensityModel('Ethiopia', 115),_CountryDensityModel('Jordan', 114),_CountryDensityModel('Slovakia', 113),_CountryDensityModel('Portugal', 111),_CountryDensityModel('Sierra Leone', 110),_CountryDensityModel('Turkey', 109),_CountryDensityModel('Austria', 109),_CountryDensityModel('Benin', 107),_CountryDensityModel('Hungary', 106),_CountryDensityModel('Cuba', 106),_CountryDensityModel('Albania', 105),_CountryDensityModel('Armenia', 104),_CountryDensityModel('Slovenia', 103),_CountryDensityModel('Egypt', 102),_CountryDensityModel('Serbia', 99),_CountryDensityModel('Costa Rica', 99),_CountryDensityModel('Malaysia', 98),_CountryDensityModel('Dominica', 95),_CountryDensityModel('Syria', 95),_CountryDensityModel('Cambodia', 94),_CountryDensityModel('Kenya', 94),_CountryDensityModel('Spain', 93),_CountryDensityModel('Iraq', 92),_CountryDensityModel('Timor-Leste', 88),_CountryDensityModel('Honduras', 88),_CountryDensityModel('Senegal', 86),_CountryDensityModel('Romania', 83),_CountryDensityModel('Myanmar', 83),_CountryDensityModel('Brunei Darussalam', 83),_CountryDensityModel("Côte d'Ivoire", 82),_CountryDensityModel('Morocco', 82),_CountryDensityModel('Macedonia', 82),_CountryDensityModel('Greece', 80),_CountryDensityModel('Wallis and Futuna Islands', 80),_CountryDensityModel('Bonaire, Sint Eustatius and Saba', 79),_CountryDensityModel('Uzbekistan', 78),_CountryDensityModel('French Polynesia', 76),_CountryDensityModel('Burkina Faso', 76),_CountryDensityModel('Tunisia', 76),_CountryDensityModel('Ukraine', 75),_CountryDensityModel('Croatia', 73),_CountryDensityModel('Cook Islands', 73),_CountryDensityModel('Ireland', 71),_CountryDensityModel('Ecuador', 71),_CountryDensityModel('Lesotho', 70),_CountryDensityModel('Samoa', 70),_CountryDensityModel('Guinea-Bissau', 69),_CountryDensityModel('Tajikistan', 68),_CountryDensityModel('Eswatini', 67),_CountryDensityModel('Tanzania', 67),_CountryDensityModel('Mexico', 66),_CountryDensityModel('Bosnia and Herz.', 64),_CountryDensityModel('Bulgaria', 64),_CountryDensityModel('Afghanistan', 59),_CountryDensityModel('Panama', 58),_CountryDensityModel('Georgia', 57),_CountryDensityModel('Yemen', 56),_CountryDensityModel('Cameroon', 56),_CountryDensityModel('Nicaragua', 55),_CountryDensityModel('Guinea', 53),_CountryDensityModel('Liberia', 52),_CountryDensityModel('Iran', 51),_CountryDensityModel('Eq. Guinea', 50),_CountryDensityModel('Montserrat', 49),_CountryDensityModel('Fiji', 49),_CountryDensityModel('South Africa', 48),_CountryDensityModel('Madagascar', 47),_CountryDensityModel('Montenegro', 46),_CountryDensityModel('Belarus', 46),_CountryDensityModel('Colombia', 45),_CountryDensityModel('Lithuania', 43),_CountryDensityModel('Djibouti', 42),_CountryDensityModel('Turks and Caicos Islands', 40),_CountryDensityModel('Mozambique', 39),_CountryDensityModel('Dem. Rep. Congo', 39),_CountryDensityModel('Palau', 39),_CountryDensityModel('Bahamas', 39),_CountryDensityModel('Zimbabwe', 38),_CountryDensityModel('United States of America', 36),_CountryDensityModel('Eritrea', 35),_CountryDensityModel('Faroe Islands', 35),_CountryDensityModel('Kyrgyzstan', 34),_CountryDensityModel('Venezuela', 32),_CountryDensityModel('Lao PDR', 31),_CountryDensityModel('Estonia', 31),_CountryDensityModel('Latvia', 30),_CountryDensityModel('Angola', 26),_CountryDensityModel('Peru', 25),_CountryDensityModel('Chile', 25),_CountryDensityModel('Brazil', 25),_CountryDensityModel('Somalia', 25),_CountryDensityModel('Vanuatu', 25),_CountryDensityModel('Saint Pierre and Miquelon', 25),_CountryDensityModel('Sudan', 24),_CountryDensityModel('Zambia', 24),_CountryDensityModel('Sweden', 24),_CountryDensityModel('Solomon Islands', 24),_CountryDensityModel('Bhutan', 20),_CountryDensityModel('Uruguay', 19),_CountryDensityModel('Papua New Guinea', 19),_CountryDensityModel('Niger', 19),_CountryDensityModel('Algeria', 18),_CountryDensityModel('S. Sudan', 18),_CountryDensityModel('New Zealand', 18),_CountryDensityModel('Finland', 18),_CountryDensityModel('Paraguay', 17),_CountryDensityModel('Belize', 17),_CountryDensityModel('Mali', 16),_CountryDensityModel('Argentina', 16),_CountryDensityModel('Oman', 16),_CountryDensityModel('Saudi Arabia', 16),_CountryDensityModel('Congo', 16),_CountryDensityModel('New Caledonia', 15),_CountryDensityModel('Saint Helena', 15),_CountryDensityModel('Norway', 14),_CountryDensityModel('Chad', 13),_CountryDensityModel('Turkmenistan', 12),_CountryDensityModel('Bolivia', 10),_CountryDensityModel('Russia', 8),_CountryDensityModel('Gabon', 8),_CountryDensityModel('Central African Rep.', 7),_CountryDensityModel('Kazakhstan', 6),_CountryDensityModel('Niue', 6),_CountryDensityModel('Mauritania', 4),_CountryDensityModel('Canada', 4),_CountryDensityModel('Botswana', 4),_CountryDensityModel('Guyana', 3),_CountryDensityModel('Libya', 3),_CountryDensityModel('Suriname', 3),_CountryDensityModel('French Guiana', 3),_CountryDensityModel('Iceland', 3),_CountryDensityModel('Australia', 3),_CountryDensityModel('Namibia', 3),_CountryDensityModel('W. Sahara', 2),_CountryDensityModel('Mongolia', 2),_CountryDensityModel('Falkland Is.', 0.2),_CountryDensityModel('Greenland', 0.1),];}@overridevoid dispose() {_worldPopulationDensityDetails?.clear();super.dispose();}}class _CountryDensityModel {_CountryDensityModel(this.countryName, this.density);final String countryName;final double density;}

Now, we have the basic requirements for creating the choropleth map using Syncfusion Flutter Maps widget. As I mentioned earlier, we need a single parameter, based on which the color of the region will be applied. In our case, density is the required parameter. We need to return the density of each country using the shapeColorValueMapper callback.

Refer to the following code.

@overridevoid initState() {super.initState();_mapShapeSource = MapShapeSource.asset('assets/world_map.json',shapeDataField: 'name',dataCount: _worldPopulationDensityDetails.length,primaryValueMapper: (int index) =>_worldPopulationDensityDetails[index].countryName,shapeColorValueMapper: (int index) =>_worldPopulationDensityDetails[index].density,);}}

Now, apply colors to the regions based on the value of their density which falls within a particular range. For example, if the density falls between 100 to 200, the region will be shown in a light color, and if it is between 201 to 300, then it will be a dark color. We will set these instructions using the collection MapColorMapper in the shapeColorMappers property.

_mapShapeSource = MapShapeSource.asset('assets/world_map.json',shapeDataField: 'name',dataCount: _worldPopulationDensityDetails.length,primaryValueMapper: (int index) =>_worldPopulationDensityDetails[index].countryName,shapeColorValueMapper: (int index) =>_worldPopulationDensityDetails[index].density,shapeColorMappers: const [MapColorMapper(from: 0,to: 25,color: Color.fromRGBO(223,169,254, 1),text: '{0},{25}'),MapColorMapper(from: 25,to: 75,color: Color.fromRGBO(190,78,253, 1),text: '75'),MapColorMapper(from: 75,to: 150,color: Color.fromRGBO(167,17,252, 1),text: '150'),MapColorMapper(from: 150,to: 400,color: Color.fromRGBO(152,3,236, 1),text: '400'),MapColorMapper(from: 400,to: 50000,color: Color.fromRGBO(113,2,176, 1),text: '>500'),],);
Applying colors to the choropleth map in a Flutter application

You can also apply colors based on the exact values. For example, red for 100, yellow for 200, etc. This is another way of color mapping in Flutter Maps.

Note: For more details, you can refer to the user guide documentation.

Add a legend

Legends provide a clear picture of the data plotted in maps using colors and brief text. One will further improve the data visualization and helps us to easily understand the trend in the data in the choropleth maps.

Refer to the following code to show bar legend in your choropleth map.

@overrideWidget build(BuildContext context) {return SfMaps(layers: [MapShapeLayer(source: _mapShapeSource,strokeColor: Colors.white30,legend: MapLegend.bar(MapElement.shape,position: MapLegendPosition.bottom,segmentSize: Size(55.0, 9.0))),],);}
Rendering a bar legend in a choropleth Flutter map
Rendering a bar legend in a choropleth Flutter map
Rendering a bar legend in a choropleth Flutter map

Support in the tile layer

Some features, like bubbles, data labels, shape selection, and setting colors based on a region’s data, are not directly possible in the tile layer. In that case, we can use a shape sublayer on top of the tile layer to enable these features in our Flutter Maps.

In the tile layer, it is possible to render the choropleth map using a shape layer as a sublayer. The process of applying the colors to the shape sublayer is exactly the same as described previously.

To learn about this in more detail, please refer to Shape Layer in Flutter Maps.

GitHub Reference

You can get the complete sample to Display Choropleth Maps using Syncfusion Flutter Maps demo.

Conclusion

In this blog post, we have gone through how to create a choropleth map using the Syncfusion Flutter Maps widget. With this, you can show data of a region relating to election results, average rain fall, literacy rates, and more. So, try out these steps and share your feedback in the comments section below.

You can go through our Flutter Map’s complete user guide and samples available at this GitHub location. Additionally, you can download our demo apps from Google Play, App Store, and on our live website.

If you need a new widget for the Flutter framework or new features in our existing widgets, you can contact us through our support forums, Direct-Trac, or feedback portal. As always, we are happy to assist you!

If you liked this blog post, we think you’ll also like the following articles too:

Originally published at https://www.syncfusion.com on April 8, 2021.

Syncfusion

Syncfusion provides third-party UI components for React…

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store