vis.gl
Published in

vis.gl

Using deck.gl with Google Maps

deck.gl ScatterplotLayer and ArcLayer over Google Maps (data source: Natural Earth)

Live demo

deck.gl was originally created to work with Mapbox GL JS. All of the examples on its website still use Mapbox as the base map. Yet, since we first open-sourced the framework, we’ve been asked on GitHub: how do you use it with Google Maps?

Both map solutions use Web Mercator Projection, so the same camera settings should (for the most part) yield pixel-matching views. In practice, we found there was more to it than that, so we worked with the Google Maps Platform engineering team to make it happen.

So what was the issue?

The largest issue that delayed adding Google Maps support to deck.gl was camera synchronization. For example, when a user zooms in and out of a Google map with the scroll wheel, Google Maps always settles on an integer zoom level, and applies a smooth transition between the current and new zoom levels. For deck.gl’s visualization layers to look as a seamless part of the Google map, deck.gl must redraw its canvas on every transition frame to match itself with the base map.

To achieve this, we had two options:

  • Match the deck.gl camera with that of the base map. This requires us to listen to a camera event of the map component and update the deck.gl view state on every change. But there’s a big problem with this approach: in Google Maps, the zoom_changed event is fired only once when zoom happens, and the map.getZoom method only ever returns the target (integer) zoom level. This means there’s no way for deck.gl to stay synchronized with Google’s transition animation between zoom levels.
  • Match the base map’s camera with that of deck.gl. This approach would require disabling the default interaction of Google Maps, and use deck.gl’s map controller to drive all camera changes. Bad news: we can’t do that either because the map.setZoom function of the Google Maps JS API doesn’t accept fractional values, meaning there is no way for external code to plug in a smooth transition logic.

So neither of these options was viable. From the API perspective, Google Maps JS API doesn’t offer the fine-grain callbacks, getters and/or setters that deck.gl normally uses for camera synchronization. Additionally, we had no visibility into the animation curve used to control the camera in Google Map, so we couldn’t hack our end to produce the same look. It started to look like Google Maps support wouldn’t be possible.

The solution

While working on deck.gl v7.0, we partnered with developers from Google to restart the investigation into how deck.gl can work seamlessly with Google Maps. Their familiarity with the Maps API gave us the eventual breakthrough. The solution involved extending the OverlayView API and reverse-engineering the projection matrix as well as some CSS. If you are curious, here is how we did it.

We figured you probably don’t need to know the details, so we packaged it up and offered it as a new npm module @deck.gl/google-maps. To use this module, you construct a GoogleMapsOverlay instance:

import {GoogleMapsOverlay} from '@deck.gl/google-maps';const overlay = new GoogleMapsOverlay({
// Deck props
});

And then simply use it as any other Maps overlay:

overlay.setMap(map);

Here is what the code would look like:

Mapping 203K trees in Paris using Google Maps and deck.gl’s ScatterplotLayer. Data source: https://opendata.paris.fr/

Live demo

All deck.gl layers and picking functionalities (e.g. onHover and onClick) work with the Google Maps integration.

The Google Maps JavaScript library does not support free rotation of the camera, so sadly the 3D layers of deck.gl may not work very well. deck.gl does not currently support zoom levels below zero, so it will hide itself when the user zooms all the way out.

What’s next

Because we don’t use Google Maps for internal apps at Uber, this new module might not be as battle-tested as the rest of the framework. We ask external developers to kindly provide us feedback if anything can be improved.

This is not the end of our work with Google Maps. The Google Maps API team plan on offering more of their WebGL infrastructure through the JS API and are committed to work closely with us as they bring their 3D rendering to their external developers. We love the richness of Google’s map data and its beautiful visuals. I would personally die to put my data in the same 3D space as its building models and street view.

Big thanks to everyone who worked on this feature: Pascal Gula, Ib Green, Don McCurdy, and Travis McPhail.

--

--

--

Open-source, WebGL-powered visualization frameworks

Recommended from Medium

Routing in Blazor

The proper way of passing an event handler (such as onClick) to a component

Javascript WTFs demystified

How to Build an advanced Modal in React (Part Two)

Build Youtube in React 07: Home Feed and video previews

Packaging Your React App With NodeJS Backend For Production

Custom OTP Verification System that Works with Firebase

Timestamps in Javascript

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Xiaoji Chen | 消极

Xiaoji Chen | 消极

Designer. Geek. Data queen. Beer lover.

More from Medium

Host a BI Report Using ReactJs+Firebase with Auth — Part2 Data + Context API + Interactions

Create a data visualization app for the K-pop TV show ‘Queendom2’ with…

What Are Svelte Stores and How to Use Them

April Releases: customizable webhook payloads, custom prices in checkout, and more!