Categories
Visx

Add a Mercator Map into Our React App with the Visx Library

Spread the love

Visx is a library that lets us add graphics to our React app easily.

In this article, we’ll look at how to use it to add a map view into our React app

Install Required Packages

We have to install a few modules to create the map.

To get started, we run:

npm i @visx/geo @visx/responsive @visx/scale

to install the packages.

Add the Map

We can add the map with the Mercator projection by writing:

import React from "react";
import { scaleQuantize } from "@visx/scale";
import { Mercator, Graticule } from "@visx/geo";
import * as topojson from "topojson-client";
import topology from "./world-topo.json";

const background = "#f9f7e8";
const world = topojson.feature(topology, topology.objects.units);

const color = scaleQuantize({
  domain: [
    Math.min(...world.features.map((f) => f.geometry.coordinates.length)),
    Math.max(...world.features.map((f) => f.geometry.coordinates.length))
  ],
  range: [
    "#ffb01d",
    "#ffa020",
    "#ff9221",
    "#ff8424",
    "#ff7425",
    "#fc5e2f",
    "#f94b3a",
    "#f63a48"
  ]
});

const Example = ({ width, height, events = false }) => {
  const centerX = width / 2;
  const centerY = height / 2;
  const scale = (width / 630) * 100;

  return width < 10 ? null : (
    <svg width={width} height={height}>
      <rect
        x={0}
        y={0}
        width={width}
        height={height}
        fill={background}
        rx={14}
      />
      <Mercator
        data={world.features}
        scale={scale}
        translate={[centerX, centerY + 50]}
      >
        {(mercator) => (
          <g>
            <Graticule
              graticule={(g) => mercator.path(g) || ""}
              stroke="rgba(33,33,33,0.05)"
            />
            {mercator.features.map(({ feature, path }, i) => (
              <path
                key={`map-feature-${i}`}
                d={path || ""}
                fill={color(feature.geometry.coordinates.length)}
                stroke={background}
                strokeWidth={0.5}
                onClick={() => {
                  if (events)
                    alert(
                      `Clicked: ${feature.properties.name} (${feature.id})`
                    );
                }}
              />
            ))}
          </g>
        )}
      </Mercator>
    </svg>
  );
};

export default function App() {
  return (
    <div className="App">
      <Example width={500} height={300} />
    </div>
  );
}

world-topo.json can be found at https://codesandbox.io/s/github/airbnb/visx/tree/master/packages/visx-demo/src/sandboxes/visx-geo-custom?file=/world-topo.json

We add the color variable to add the colors of the countries on the map.

Then in the Example component, we add the centerX and centerY variables to set the center of the map.

scale has the initial zoom level.

Then to add a 2D map that uses the Mercator projection, we add the Mercator component.

The data prop is set to the world variable, which created from the topojson.feature method with th topology JSON as the argument.

Then in its render prop, we add the Graticule component to add the map grid lines.

And the path element draws the countries.

Conclusion

We can add a simple 2D map easily into our React app with the Visx library.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

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