Getting started with DeckGL

In previous blog posts (post-1, post-2,post-3,post-4)I have covered some topics showing how to add interactivity and visualizations to Mapbox based maps using React-map-gl framework. In this blog post, I will introduce you to another advanced WebGL framework called DeckGL.

According DeckGl website

deck.gl is a great match with React, supporting efficient WebGL rendering under the Reactive programming paradigm. And when used with Mapbox GL it automatically coordinates with the Mapbox camera system to provide compelling 2D and 3D visualizations on top of your Mapbox based maps.

DeckGl is advanced WebGL framework built on the top of react-map-gl framework and can handle large number of datasets.

DeckGL adds visualizations to map using layered approach. You can add visualization and interactivity to the map using multiple layers. The framework has lot of pre defined layers which are easy to use and we can also define our own layers.

In this blog post, I will showcase the working of 2 layers IconLayer and TripsLayer with an example.

Follow the steps below to show the map using the DeckGL

Step 1) First, create a React JS application

npx create-react-app vehicle-trip-pathCode language: Python (python)

Step 2) Next, install the required npm modules

npm install react-map-gl deck-gl react-sliding-side-panelCode language: Python (python)

Step 3) Add a variable to App.js for holding latitude, longitude, zoom, pitch, bearing, width, and height.

const INITIAL_VIEW_STATE = {
  longitude: 174.7078,
  latitude: -36.722,
  zoom: 14.25,
  pitch: 45,
  bearing: 0,
  width: "100vw",
  height: "100vh",
};Code language: JavaScript (javascript)
https://gist.github.com/sureshgadupu/7ef946281b5ca0d68ee371fb5517a325

Step 4) Next, we need add components to show the map in render method of App.js file. Since DeckGl is based on the react-map-gl. We will use react-map-gl components to display the map.

react-map-gl framework has 2 components StaticMap and InteractiveMap

  • StaticMap – The simplest React wrapper around MapboxGL. This is designed to be completely static, and should be used to render a map with no interactivity.
  • InteractiveMap – This component renders MapboxGL and provides full interactivity support. It uses StaticMap underneath to render the final map component. This is the default exported component from react-map-gl.

While using DeckGL framework, we will use the StaticMap component as map interactivity is added by DeckGL components.

<StaticMap
        reuseMaps
        mapboxApiAccessToken={MAPBOX_ACCESS_TOKEN}
        mapStyle={"mapbox://styles/mapbox/dark-v9"}
        preventStyleDiffing={true}
        {...INITIAL_VIEW_STATE}
      />Code language: JavaScript (javascript)
https://gist.github.com/sureshgadupu/b31f5241e3343319fc4ffad51b08391d

Step 5) Let’s wrap the StaticMap with DeckGL component so that we can add interactivity to the map.

<DeckGL
       
        controller={true}
        initialViewState={INITIAL_VIEW_STATE}
        useDevicePixels={false}
      >
        <StaticMap
          reuseMaps
          mapboxApiAccessToken={MAPBOX_ACCESS_TOKEN}
          mapStyle={"mapbox://styles/mapbox/dark-v9"}
          preventStyleDiffing={true}
        />
<DeckGL>Code language: JavaScript (javascript)
https://gist.github.com/sureshgadupu/298387d3bb74f7cf0374df7cec43dd56

Step 6) Now we need to add the layers for interactivity, DeckGL component takes array of layers

<DeckGL
        layers={layers}
        controller={true}
        initialViewState={INITIAL_VIEW_STATE}
        useDevicePixels={false}
      >
      ...
  </DeckGL>Code language: JavaScript (javascript)
https://gist.github.com/sureshgadupu/8d39600f82e9241037e6cfed2f7002cc

Step 7) Now we need to create the Layers and prepare required data for them. First look at the data we have.

I have prepared the data , imagining that the vehicle have travelled between two locations and longitude and latitude are collected at regular interval of times. “co-ordinates” property contains data in [latitude , longitude, timestamp] format

[
    {
        "name" : "Trip-1",
        "co-ordinates"  : [
            [-36.726130270544,174.717837811695,"2021-07-1 13:00:00"],
            [-36.7262315659942,174.717652374079,"2021-07-1 13:00:10"]
            ....
            ]
     },
     {
        
          "name" : "Trip-2",
          "co-ordinates"  : [
              [-36.71731096,174.6909685,"2021-07-11 13:00:00"],
              [-36.71739439,174.6911673,"2021-07-11 13:00:10"]
              ......
     
     }
]Code language: JSON / JSON with Comments (json)
https://gist.github.com/sureshgadupu/b638366483c4f477a7fefda23d16a317

Note

I have used https://www.nmeagen.org/ website to collect the route co-ordinates.

I am showing all the data from the trip names on side panel , when user selects a trip , its origin and destination point is shown on the map with an icon.

DeckGL map

IconLayer is used to display icons at the designated longitude and latitude. First and last co-ordinates of each selected trips are collected and data is passed to IconLayer.

new IconLayer({
      id: "icon-layer",
      data: origDestPoints,
      pickable: true,     
      iconAtlas:
        "https://raw.githubusercontent.com/visgl/deck.gl-data/master/website/icon-atlas.png",
      iconMapping: ICON_MAPPING,
      getIcon: (d) => "marker",
      sizeScale: 5,
      getPosition: (d) => d.coords,
      getSize: (d) => 5,
      getColor: (d) => (d.place === "orig" ? [250, 250, 0] : [0, 0, 255]),
    }Code language: JavaScript (javascript)
https://gist.github.com/sureshgadupu/b1891af3fbc041b0d63b12a1692ec613
  • data: takes the array of data objects
  • getPosition : takes [lng, lat] , where icon is placed.
  • getColor: used to specify the color of icon

You can find the detailed documentation of IconLayer here

When the user selects a ShowTrip icon on the side panel, Application shows the path of vehicle travelled in animated way.

I am using the TripsLayer to show the path of vehicle travelled in an animated way.

new TripsLayer({
          id: "trips",
          data: selectedTrips,
          getPath: (d) => d.path,
          getTimestamps: (d) => d.timestamps,
          getColor: (d) => [255, 255, 0, 255],
          opacity: 0.5,
          widthMinPixels: 12,
          rounded: true,
          trailLength,
          currentTime: time,
          shadowEnabled: false,
        }Code language: JavaScript (javascript)
https://gist.github.com/sureshgadupu/3446c87d773694f0dc61e3276e9e8ccc
  • data: Takes the array of data objects. Each object contains path and timestamps
  • getPath : Called for each data object to retrieve paths. Returns an array of navigation points on a single path. Takes array of [lng, lat] objects
  • getTimestamps : Returns an array of timestamps, one for each navigation point in the geometry returned by getPath, representing the time that the point is visited.
  • currentTime : The current time of the frame, i.e. the playhead of the animation.

To show the trip animation, we need to continuously update the currentTime values. I am using animate() method to update the time. requestAnimationFrame() method is used to repeatedly call the animate method to update time and repaint the window frame.

const animate = useCallback(() => {
    if (maxTimeLengthRef.current > 0 && showTrip) {
      setTime((time) => (time > maxTimeLengthRef.current * 10 ? 1 : time + 2));

      animationRef.current = requestAnimationFrame(animate);
    }
  }, [showTrip]);Code language: JavaScript (javascript)
https://gist.github.com/sureshgadupu/830960e38249d97a375dc26c7525ceea

You can the application is action in below video

You can download the source code for this blog post from GitHub

Similar Posts