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-path
Code language: Python (python)
Step 2) Next, install the required npm modules
npm install react-map-gl deck-gl react-sliding-side-panel
Code 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)
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 simplestReact
wrapper aroundMapboxGL
. This is designed to be completely static, and should be used to render a map with no interactivity.InteractiveMap
– This component rendersMapboxGL
and provides full interactivity support. It usesStaticMap
underneath to render the final map component. This is thedefault
exported component fromreact-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)
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)
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)
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)
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.
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)
- 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)
- 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)
You can the application is action in below video
You can download the source code for this blog post from GitHub