What is deck.gl?
deck.gl is a powerful WebGL-powered framework for visual exploratory data analysis of large datasets. It provides a suite of highly performant, customizable layers for rendering complex data visualizations on top of maps.
What are deck.gl's main functionalities?
ScatterplotLayer
The ScatterplotLayer is used to render scatter plot points on a map. Each point can be customized with different sizes and colors.
const {DeckGL, ScatterplotLayer} = require('deck.gl');
const scatterplotLayer = new ScatterplotLayer({
id: 'scatterplot-layer',
data: [
{position: [-122.45, 37.78], size: 100},
{position: [-122.46, 37.79], size: 200}
],
getPosition: d => d.position,
getRadius: d => d.size,
getColor: [255, 0, 0]
});
const deckgl = new DeckGL({
initialViewState: {
longitude: -122.45,
latitude: 37.78,
zoom: 12
},
controller: true,
layers: [scatterplotLayer]
});
GeoJsonLayer
The GeoJsonLayer is used to render GeoJSON data. It supports features like picking, extruding, and coloring of GeoJSON polygons.
const {DeckGL, GeoJsonLayer} = require('deck.gl');
const geoJsonLayer = new GeoJsonLayer({
id: 'geojson-layer',
data: 'https://raw.githubusercontent.com/uber-common/deck.gl-data/master/examples/geojson/vancouver-blocks.json',
pickable: true,
stroked: false,
filled: true,
extruded: true,
getFillColor: [160, 160, 180, 200],
getLineColor: [255, 255, 255],
getRadius: 100,
getLineWidth: 1
});
const deckgl = new DeckGL({
initialViewState: {
longitude: -123.1,
latitude: 49.28,
zoom: 11
},
controller: true,
layers: [geoJsonLayer]
});
ArcLayer
The ArcLayer is used to render arcs between pairs of coordinates. It is useful for visualizing connections or flows between locations.
const {DeckGL, ArcLayer} = require('deck.gl');
const arcLayer = new ArcLayer({
id: 'arc-layer',
data: [
{source: [-122.45, 37.78], target: [-122.46, 37.79]},
{source: [-122.46, 37.79], target: [-122.47, 37.80]}
],
getSourcePosition: d => d.source,
getTargetPosition: d => d.target,
getSourceColor: [0, 128, 200],
getTargetColor: [255, 0, 0],
getWidth: 2
});
const deckgl = new DeckGL({
initialViewState: {
longitude: -122.45,
latitude: 37.78,
zoom: 12
},
controller: true,
layers: [arcLayer]
});
Other packages similar to deck.gl
leaflet
Leaflet is a popular open-source JavaScript library for mobile-friendly interactive maps. It is lightweight and easy to use, but it does not offer the same level of performance and customization for large datasets as deck.gl.
mapbox-gl
Mapbox GL JS is a powerful library for interactive, customizable vector maps. It offers high performance and a wide range of features, but it is more focused on map rendering and less on data visualization compared to deck.gl.
three
Three.js is a JavaScript library for creating 3D graphics in the browser. While it is highly versatile and powerful for 3D rendering, it requires more effort to set up and use for data visualization compared to deck.gl.
deck.gl
A WebGL overlay suite for React providing a set of highly performant
data visualization overlays.
Design goals:
- Provide overlays that plug directly into react-map-gl's overlay model,
enabling overlays to work on maps.
- Provide highly performant data visualization overlays in 2 and 3 dimensions.
- Provide tested, highly performant layers for basic data visualization
use cases, scatterplots, choropleths etc.
- Allows easy creation of custom WebGL layers by subclassing
Layer
. - Support efficient WebGL rendering in "data flow architecture" applications
(i.e. React).
- Special focus on buffer management, allowing both automatic buffer updates
but also full application control of buffer allocation and management
Features:
- Web Mercator projections are handled in shader on GPU. No projections are
done in JavaScript (unless needed for a uniform calculation or reverse
projection of e.g. picked coordinate etc). Specify your lat,lon once and
never touch it again.
- Can accept data stored in any ES6 container
(supporting [Symbol.iterator] iteration).
- Automatic and manual WebGL buffer management to support.
Installation
npm install --save deck.gl
Usage
import {
WebGLOverlay,
/* import layers here */
} from 'deck.gl';
const mapState = {
latitude: 37.55,
longitude: -122.2,
zoom: 9,
...
}
<WebGLOverlay
width={1920}
height={1080}
mapState={mapState}, // optional
layers={[/* put layer instances here */]}
/>
WebGLOverlay:
-
webgl-overlay
A react component that takes in viewport parameters, layer instances and
generates an overlay consists of single/multiple layers sharing the same
rendering context. Internally, the webgl-overlay initializes a WebGL context
attached to a canvas element, sets up the animation loop and calls provided
callbacks on initial load and for each rendering frames. The webgl-overlay
also handles events propagation across layers, and prevents unnecessary
calculation taking advantage of the react lifecycle functions.
Parameters
width
(number, required) width of the canvasheight
(number, required) height of the canvaslongitude
(number, required) longitude of the map centerlatitude
(number, required) latitude of the map centerzoom
(number, required) zoom level of the map
Callbacks
onAfterRender
[function, optional] callback after rendering is finished
for the current frame
Supported Layers:
The Choropleth Layer takes in GeoJson formatted data and
renders it as interactive choropleths.
Common Parameters
id
(string, required): layer IDwidth
(number, required) width of the layerheight
(number, required) height of the layerlongitude
(number, required) longitude of the map centerlatitude
(number, required) latitude of the map centerzoom
(number, required) zoom level of the mapopacity
(number, required) opacity of the layerisPickable
[bool, optional, default=false] whether layer responses to
mouse events
Layer-specific Parameters
data
(object, required) input data in GeoJson formatdrawContour
[bool, optional, default=false] draw choropleth contour if
true, else fill choropleth area
Callbacks
-
onChoroplethHovered
[function, optional] bubbles choropleth properties
when mouse hovering
-
onChoroplethClicked
[function, optional] bubbles choropleth properties
when mouse clicking
-
Hexagon Layer
The Hexagon Layer takes in a list of hexagon objects and renders them as
interactive hexagons.
Common Parameters
id
(string, required): layer IDwidth
(number, required) width of the layerheight
(number, required) height of the layeropacity
(number, required) opacity of the layerisPickable
[bool, optional, default=false] whether layer responses to
mouse events
Layer-specific Parameters
data
(array, required) array of hexagon objects: [{ centroid, vertices,
color }, ...]dotRadius
[number, optional, default=10] radius of each hexagonelevation
[number, optional, default=0.02] height scale of hexagonslightingEnabled
[bool, optional, default=false] whether lighting is
enabled
Callbacks
onHexagonHovered
[function, optional] bubbles selection index when mouse
hoveringonHexagonClicked
[function, optional] bubbles selection index when mouse
clicking
-
Scatterplot Layer
The Scatterplot Layer takes in and renders an array of latitude and longitude
coordinated points.
Common Parameters
id
(string, required): layer IDwidth
(number, required) width of the layerheight
(number, required) height of the layeropacity
(number, required) opacity of the layerisPickable
[bool, optional, default=false] whether layer responses to
mouse events
Layer-specific Parameters
data
(array, required) array of objects: [{ position, color }, ...]radius
[number, optional, default=10] radius of each marker
-
Arc Layer
The Arc Layer takes in paired latitude and longitude coordinated points and
render them as arcs that links the starting and ending points.
Common Parameters
id
(string, required): layer IDwidth
(number, required) width of the layerheight
(number, required) height of the layeropacity
(number, required) opacity of the layerisPickable
[bool, optional, default=false] whether layer responses to
mouse events
Layer-specific Parameters
data
(array, required) array of objects: [{ position: {x0, y0, x1, y1},
color }, ...]
-
Grid Layer
The Grid Layer takes in an array of latitude and longitude coordinated points,
aggregates them into histogram bins and renders as a grid.
Common Parameters
id
(string, required): layer IDwidth
(number, required) width of the layerheight
(number, required) height of the layeropacity
(number, required) opacity of the layerisPickable
[bool, optional, default=false] whether layer responses to
mouse events
Layer-specific Parameters
data
(array, required) array of objects: [{ position, color }, ...]unitWidth
[number, optional, default=100] unit width of the binsunitHeight
[number, optional, default=100] unit height of the bins
Notes on data property
The data
property will accept any containers that can be iterated over using
ES6 for-of iteration, this includes e.g. native Arrays, ES6 Sets and Maps,
all Immutable.js containers etc. The notable exception are native JavaScript
object maps. It is recommended to use ES6 Maps instead.
It is recommended, but not required, to use immutable data (containers AND
objects) as it ensures that changes to data
property trigger a rerender.
(See the notes on rerenderCount
and updateCount
properties.)
Notes on picking
Note: Because DeckGL layers are designed to take any type of iterable
collection as data (which may not support "random access" array style
references of its elements), the picking calculates and index but the
actual object.
FEATURE IDEA: The base layer could take an optional getObject(index) accessor
and call it if supplied.
Notes on WebGL buffer management
deck.gl Layers were designed with data flow architectures like React in mind.
The challenge is of course that in the react model, every change to application
state causes a full rerender. The rendering callbacks are then supposed to
detect what changes were made a limit rerendering as appropriate. When you
have a couple of 100K element WebGL buffers to update, this can become quite
expensive unless change detection is well managed.
Data Management using automatic Buffer updates
The layer will expect each object to provide a number of "attributes" that it
can use to set the GL buffers. By default, the layer will look for these
attributes to be available as fields directly on the objects during iteration
over the supplied data set. To gain more control of attribute access and/or
to do on-the-fly calculation of attributes.
Manual Buffer Management
For ultimate performance and control of updates, the application can do its
own management of the glbuffers. Each Layer can accept buffers directly as
props.
Note: The application can provide some buffers and let others be managed
by the layer. As an example management of the instancePickingColors
buffer is
normally left to the layer.
Note: A layer only renders when a property change is detected. For
performance reasons, property change detection uses shallow compare,
which means that mutating an element inside a buffer or a mutable data array
does not register as a property change, and thus does not trigger a rerender.
To force trigger a render after mutating buffers, simply increment the
renderCount
property. To force trigger a buffer update after mutating data,
increment the updateCount
property.
Notes on Blending Modes
To get a handle on blending modes, it helps to consider that deck.gl
renders in a separate transparent div on top of the map div,
so it is actually the browser that blends the deck.gl output into the map,
not WebGL, and the default blending in the browser typically does not give
ideal effects.
There is a CSS property mix-blend-mode
in modern browsers
that allows control over blending:
.overlays canvas {
mix-blend-mode: multiply;
}
multiply
blend mode is usually the right choice, as it only darkens.
This will keep your overlay colors, but let map legends underneath
remain black and legible.
Note: that there is a caveat with setting mix-blend-mode
:
it can affect other peer HTML elements, especially other map children (perhaps
controls or legends that are being rendered on top of the map).
If this is an issue, set isolation CSS prop on the map (DeckGLOverlay parent)
element.
isolation: 'isolate'
Example
npm run start
Data source
https://data.sfgov.org/