Richard Zimerman

@zimrick

Mapping Tutorial: Combining Victory Charts and React-Simple-Maps

Creating a beautiful map of Switzerland’s language distribution by canton using donut charts on a map.

This is the end result of this tutorial.

React-simple-maps is a react component library to help make SVG mapping with d3-geo, TopoJSON, and React easier. One of the strengths of using react-simple-maps is that it gives React full control over the DOM and does not treat the SVG map as a black box. This means that react-simple-maps can easily take advantage of the entire React ecosystem and all the good things that come with it.

React-simple-maps was partially inspired by the declarative api of Victory charts. If you haven’t heard about Victory, take a look on github, or see the examples and guides on their website.

The great thing about Victory charts is that it does not have to be used standalone, but that it can be embedded in already existing SVG containers. This makes it possible to combine Victory charts with any SVG visual, e.g. a map ;)

This tutorial will go over how to combine the two libraries and create the map shown on the cover of this article. If you are just interested in the final code, head on over to the github repo.

Here’s what this tutorial will cover:

  1. About the visualisation
  2. The repo and the app structure
  3. Setting up a basic map (TopoJSON, projection, style)
  4. The data
  5. Rendering <VictoryPie /> inside <Marker /> components

Let’s get started.

About the Visualisation

The visualisation for this tutorial shows the language distribution in Switzerland by canton. Even though Switzerland has a population of slightly more than 8 million, it has four official languages: German, French, Italian, and Romansh. This results in Switzerland being divided into three distinct linguistic regions, each with its own culture. Romansh constitutes a special case, as it is only spoken by 0.5% of the Swiss population, mostly in the canton of Graubünden.

While most cantons will identify predominantly with one language, there are some (Fribourg, Valais, Bern, and Graubünden) that have quite a diverse linguistic environment.

The Repo and App Structure

In order to simplify the setup for this tutorial, I will be using next.js to create an app scaffold. To get started, install these dependencies:

$ npm install react react-dom react-simple-maps victory next --save

In terms of scaffolding, here’s what the app structure will look like:

┬ app
├─┬ data
│ └── index.js
├─┬ pages
│ └── index.js
├─┬ static
│ └── cantons.json
├── node_modules
└── package.json

Don’t forget to add the next dev script in package.json.

// ./package.json
...
scripts: {
"dev": "next",
...
}
...

Setting up a Basic Map

Every mapping visualisation starts with a good base map, and a solid TopoJSON file. If you are new to TopoJSON, check out the docs here. If you are new to creating your own TopoJSON files, you can check out my article on How to convert and prepare TopoJSON files for interactive mapping with d3.

The original shapefile used to create the TopoJSON file came from gadm.org.

The projection for the map of Switzerland was derived from this block, made by Mike Bostock. In order to use the Albers projection with react-simple-maps, we need to load in d3-geo. Since react-simple-maps uses d3-geo internally, it should already be installed. Using geoAlbers from d3-geo, you can easily create a custom projection, and pass it into the projection prop of <ComposableMap />.

You can now run the app. Just type $ npm run dev in the terminal, and go to http://localhost:3000.

The Data

The dataset for this tutorial comes from the Swiss Federal Statistics Office. In order to not mess with asynchronous data loading, this small dataset can be easily converted into a javascript object, and loaded in as a normal script. Here’s an excerpt:

// ./data/index.js
export const cantons = [
{
id: 25,
canton: "Zurich",
coordinates: [ 8.6356, 47.3595 ],
languages: [
{ name: "German", value: 83.1 },
{ name: "French", value: 3 },
{ name: "Italian", value: 5.9 },
{ name: "Romansh", value: 0.4 },
]
},
...

The data can now be easily imported into the app:

// ./pages/index.js
import { cantons } from "../data"
...

Rendering Victory Charts As Markers

The final step is now to use the data to render out react-simple-maps <Marker /> components and render <VictoryPie /> charts into those markers.

Note: The two <circle /> elements added on lines 67-68, are just for decorative purposes.

Conclusion

This tutorial covered how to use react-simple-maps together with Victory charts to create a nice little map of Switzerland’s language distribution by canton. The two libraries play well together, so give it a try. Thanks for reading, and happy mapping! ;)

Resources

For the complete code example, see this github repo.

For more information on declarative mapping, check out How to create pure react SVG maps with topojson and d3-geo.

For information on how to convert shapefiles into TopoJSON to use with react-simple-maps, or d3, check out How to convert and prepare TopoJSON files for interactive mapping with d3.

More information about react-simple-maps

More information about Victory.

Mentions

Thanks to the folks at Formidable, for creating the awesomeness that is Victory and of course Mike Bostock, and Jason Davies for their work on d3 and for being a continuous source of inspiration.

More by Richard Zimerman

Topics of interest

More Related Stories