zcreativelabs / react-simple-maps

Beautiful React SVG maps with d3-geo and topojson using a declarative api.
https://www.react-simple-maps.io/
MIT License
3.12k stars 427 forks source link

Create Choropleth Map with object data #41

Open James2516 opened 6 years ago

James2516 commented 6 years ago

I have a dynamically generated object with shape: { Hungary: 10, Iceland: 16, Israel: 5, ... } How do I go about converting this data into a choropleth world map?

zimrick commented 6 years ago

Hi @James2516,

You can try the following approach to match your data with the individual country paths and assign a color to the countries. Note that I am using ISO3 values instead of country names, as they are more reliable. To create the colors I am using d3-scale.


import React, { Component } from "react"
import {
  ComposableMap,
  ZoomableGroup,
  Geographies,
  Geography,
} from "react-simple-maps"
import { scaleLinear } from "d3-scale"

const wrapperStyles = {
  width: "100%",
  maxWidth: 980,
  margin: "0 auto",
}

const data = [
  { id: "HUN", name: "Hungary", val: 10 },
  { id: "ISL", name: "Iceland", val: 16 },
  { id: "ISR", name: "Israel", val: 5 },
]

const minValue = 5 // based on the data array above
const maxValue = 16 // based on the data array above

const minColor = "#CFD8DC"
const maxColor = "#37474F"

const customScale = scaleLinear()
  .domain([minValue,maxValue])
  .range([minColor,maxColor])

class ChoroplethMap extends Component {
  render() {
    return (
      <div style={wrapperStyles}>
        <ComposableMap
          width={980}
          height={551}
          style={{
            width: "100%",
            height: "auto",
          }}
          >
          <ZoomableGroup>
            <Geographies geography="/static/world-50m-simplified.json" disableOptimization>
              {(geos, proj) => geos.map((geo, i) => {

                const country = data.find(d => d.id === geo.properties.ISO_A3)

                return (
                  <Geography
                    key={geo.properties.ISO_A3 + i}
                    cacheId={geo.properties.ISO_A3 + i}
                    geography={ geo }
                    projection={ proj }
                    style={{
                      default: {
                        fill: country ? customScale(country.val) : "#ECEFF1",
                        stroke: "#FFF",
                        strokeWidth: 0.75,
                        outline: "none",
                      },
                      hover: {
                        fill: "#263238",
                        stroke: "#FFF",
                        strokeWidth: 0.75,
                        outline: "none",
                      },
                      pressed: {
                        fill: "#263238",
                        stroke: "#FFF",
                        strokeWidth: 0.75,
                        outline: "none",
                      }
                    }}
                  />
                )
              })}
            </Geographies>
          </ZoomableGroup>
        </ComposableMap>
      </div>
    )
  }
}

export default ChoroplethMap

For the country shapes I am using the world-50m-simplified.json file from the topojson-maps folder.

Hope this answers your question.