Search for content

Vector Map React App

You will learn how a basic Vector Map with React is implemented. We will display a beautiful vector map with minimal configuration effort. Tutorial illustrates the use of the PTV Developer Vector Maps API

Try it! Download from GitHub

Prerequisites

Getting started

Setting up a React App with CRA

We'll use the official create-react-app (CRA) template as a starting point. Open a terminal at the target location of your project and run the command

npx create-react-app ptv-vector-map-react-app

If this does not work, e.g. because your npm version is older than 5.2.0, you can alternatively run

npm i -g create-react-app
create-react-app ptv-vector-map-react-app

This will create the basic structure of a runnable React App with the name ptv-vector-map-react-app. You can switch into the project folder and run the npm start script to run the app. For now, it will show a rotating React icon.

Writing a Vector Map Component

In this tutorial, we'll use React Map GL and MapLibre GL JS to render the vector map. Install the npm package with this command:

npm i react-map-gl
npm i maplibre-gl

In the /src folder, create a JavaScript file called VectorMap.js. Our vector map component may look like this:

//VectorMap.js
import { useCallback } from "react";
import { Map, NavigationControl } from "react-map-gl/maplibre";

// Use the standard map style provided by PTV.
const MAP_STYLE_URL = "https://vectormaps-resources.myptv.com/styles/latest/standard.json";

// The initial view is Karlsruhe, Germany.
const INITIAL_VIEW_PORT = {
  longitude: 8.4055677,
  latitude: 49.0070036,
  zoom: 12,
  pitch: 0,
  bearing: 0,
};

export const VectorMap = (props) => {
  const getTransformRequest = useCallback(
    (url, resourceType) => {
      if (resourceType === "Tile") {
        return { url: url, headers: { ApiKey: " " + props.apiKey } };
      }
      return { url: url, headers: {} };
    }
  );

  return (
    <Map
      height="100%"
      width="100%"
      mapStyle={MAP_STYLE_URL}
      initialViewState={INITIAL_VIEW_PORT}
      transformRequest={(url, resourceType) => getTransformRequest(url, resourceType)}
    />
  );
};

The VectorMap component wraps the ReactMapGL component and sets the MAP_STYLE_URL provided by PTV (Read more on styling the map in the concept). Also, it appends the API key passed to VectorMap to the tile requests via transformRequest. We initialize the initial view of our map to Karlsruhe, where PTV Headquarters are located.

Let's see what this looks like! Replace the contents of the App.js file with this to use the component:

// App.js
import "maplibre-gl/dist/maplibre-gl.css";

import { VectorMap } from "./VectorMap";

const API_KEY = "YOUR_API_KEY";

const WRAPPER_STYLE = {
  position: "absolute",
  gridArea: "map",
  height: "100%",
  width: "100%",
  zIndex: 0
};

const App = () => (
  <div style={WRAPPER_STYLE}>
    <VectorMap apiKey={API_KEY}/>
  </div>
);

export default App;

Paste your API key in the designated variable. In a productive app, never hard-code or check-in your API key! You should now see the PTV Vector Map.

Adding controls

Now you can go and extend the map component to match your needs. For instance, let's add a NavigationControl from Maplibre to the top-right corner of our map:

 

import { Map, NavigationControl } from "react-map-gl/maplibre";

...

export const VectorMap = (props) => {

   ...   
   
   return (
    <Map
      ...
    >
      <NavigationControl position="bottom-right" />
    </Map>
  );
};