React+Datamaps => Choropleth region map

This post will walk through on how to create a Datamap React component using the Datamap npm module and then use that component to have a region based world map choropleth.

Here we go:

Create a JSX component which encapsulates a Datamaps instance ( var map = new Datamaps() ) and we will use that map instance to update/clear/create the maps behaviour based on the data being passed to the React component.

First install datamaps


npm install datamaps --save-dev

Lets write the function which will create the map in a given dom target:


	drawMap = () =&rt; {
        var map = new Datamaps(Object.assign({}, { // create the instance here
            ...this.props
        }, {
            element: this.refs.container,
            projection: 'mercator',
            responsive: true
        }));

        this.map = map; assign this instance to the react class.
    }

The lets write a React component around this, and we will invoke this function in the componentDidMount and the ComponentDidUpdate life cycle events.


	import React, {PropTypes} from 'react';
	import Datamaps from 'datamaps/dist/datamaps.world.hires.min.js';

	export default class Datamap extends React.Component {

		//defining our expected props which will be directly passed on to the datamaps instance
		static propTypes = {
			arc: React.PropTypes.array,
			arcOptions: React.PropTypes.object,
			bubbleOptions: React.PropTypes.object,
			bubbles: React.PropTypes.array,
			graticule: React.PropTypes.bool,
			labels: React.PropTypes.bool
		};

		constructor(props) {
			super(props);
			window.addEventListener('resize', this.resize);
		}

		resize = () =&rt; {
			if (this.map) {
				this.map.resize();
			}
		}
	
		//this will create the map when the component mounts
		componentDidMount() {
			this.drawMap();
		}

		//this will remove the map from the dom when the react component is unmounted
		componentWillReceiveProps() {
			this.clear();
		}

		//this will update the map with the latest props
		componentDidUpdate() {
			this.drawMap();
		}

		componentWillUnmount() {
			this.clear();
			window.removeEventListener('resize', this.resize);
		}

		clear = () =&rt; {
			const container = this.refs.container;

			for (const child of Array.from(container.childNodes)) {
				container.removeChild(child);
			}
		}

		drawMap = () =&rt; {
			var map = new Datamaps(Object.assign({}, {
				...this.props
			}, {
				element: this.refs.container, // this is the place where the react dom and the Datamaps dom will be wired
				projection: 'mercator', // this is hardcoded here as we want the projection to be constant
				responsive: true
			}));

			this.map = map;
		}

		render() {
			const style = {
				position: 'relative',
				width: '80%',
				height: '60%'
			};

			return <div ref="container" style={style}&rt;</div&rt;;
		}

	}

Now that our Datamaps React component is ready, ets write a container JSX file (MapView.jsx):

This will call invoke our Datamaps react component and will also pass the props into this.
We will add some filters as well to this component which will change the state of the Datamaps by changing the props values.

Here is the render function:


	render() {
        return (
            <div className="App"&rt;
                <div className="App-options"&rt;
                    <RadioGroup name="fruit" selectedValue={this.state.selectedRegion} onChange={this.update}&rt;
                        {Radio =&rt; (
                            <div&rt;
                                <Radio value="AMR"/&rt;AMR
                                <Radio value="APAC"/&rt;APAC
                                <Radio value="EMEA"/&rt;EMEA
                                <Radio value="ALL"/&rt;ALL

                            </div&rt;
                        )}
                    </RadioGroup&rt;

                </div&rt;
                <div className="App-map"&rt;
                    <Datamap {...this.state}/&rt;
                </div&rt;
            </div&rt;
        );
    }

Here is the function which changes the props(in this case state which is passed as the props to Datamaps) based on the filter selection:

	
	update = (region) =&rt; {
		//some data manipulation object to filter the data based on region param
        this.setState(Object.assign({}, {
            data: regionData,
            selectedRegion:region
        }, window.example));
    }

And finally lets add the constructor to this class which will add some initial data to the state so that on page load, the map loads with a unfiltered data set.


	constructor(props) {
        super(props);
        var dataset = {};
        /* 
        logic to populate the dataset, please note that this should be in the following format:
        dataset[iso] = {
                numberOfThings: <numeric value&rt;,
                fillColor: <some rgb color&rt;,
                region: <region&rt;
        };
        
        Please check the final code in the github account to get the full picture.
        */
        this.state = {
            scope: 'world',
            selectedRegion:'ALL',
            allData: dataset,
            data: dataset,
            fills: {
                defaultFill: '#ddd'
            },
            geographyConfig: {  // this one is the xact same config which is you will see in the Datamaps config, you can add any confi option required for the Datamaps instance depending on your requirement.
                borderColor: '#888',
                borderWidth: .5,
                highlightBorderWidth: .5,
                highlightBorderColor: 'black',
                highlightFillColor: function(geo) {
                    return geo['fillColor'] || '#ddd';
                },
                popupTemplate: function(geo, data) {
                    //some custom popup html fragment
                }
            }
        };

    }

The final result here:

Screen Shot 2016-05-10 at 4.19.37 PM Screen Shot 2016-05-10 at 4.19.33 PM Screen Shot 2016-05-10 at 4.19.30 PM Screen Shot 2016-05-10 at 4.19.26 PM

Full code:

https://github.com/nishantnisonko/react-datamaps

 

References:

http://datamaps.github.io

https://github.com/btmills/react-datamaps

 

 

Posted in Generic

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

Recent Posts


Hit Counter provided by technology news