diff --git a/docs/api-reference/google-maps/google-maps-overlay.md b/docs/api-reference/google-maps/google-maps-overlay.md index 585d3aff4c7..b4e7932097f 100644 --- a/docs/api-reference/google-maps/google-maps-overlay.md +++ b/docs/api-reference/google-maps/google-maps-overlay.md @@ -2,40 +2,111 @@ This class implements the [OverlayView](https://developers.google.com/maps/documentation/javascript/reference/overlay-view#OverlayView)/[WebGLOverlayView](https://developers.google.com/maps/documentation/javascript/reference/webgl#WebGLOverlayView) (depending on map rendering type) interface and can be used as any other Google Maps overlay. -## Vector/Raster maps - As detailed in the [overview](./overview.md), the overlay supports both Vector and Raster Google map rendering. Depending on the Google Map configuration, the correct deck.gl overlay rendering method will be chosen at runtime. -## Usage +## Example + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + + + -```js - import {GoogleMapsOverlay as DeckOverlay} from '@deck.gl/google-maps'; - import {GeoJsonLayer} from '@deck.gl/layers'; +```ts +import {Loader} from "@googlemaps/js-api-loader"; +import {GoogleMapsOverlay} from '@deck.gl/google-maps'; +import {ScatterplotLayer} from '@deck.gl/layers'; - // Create map - const map = new google.maps.Map(document.getElementById('map'), { - center: { lat: 40, lng: -100 }, +const loader = new Loader({ + apiKey: '', + version: "quarterly" +}); + +loader.importLibrary('maps').then((googlemaps) => { + const map = new googlemaps.Map(document.getElementById('map'), { + center: {lat: 51.47, lng: 0.45}, zoom: 5, - mapId: GOOGLE_MAP_ID // Only required for Vector maps + mapId: '' }); - // Create overlay instance - const overlay = new DeckOverlay({ + const overlay = new GoogleMapsOverlay({ layers: [ - new GeoJsonLayer({ - ... + new ScatterplotLayer({ + id: 'deckgl-circle', + data: [ + {position: [0.45, 51.47]} + ], + getPosition: d => d.position, + getFillColor: [255, 0, 0, 100], + getRadius: 1000 }) ] }); - // Add overlay to map + overlay.setMap(map); +}); ``` + + + +```tsx +import React, {useMemo, useEffect} from 'react'; +import {APIProvider, Map, useMap} from '@vis.gl/react-google-maps'; +import {DeckProps} from '@deck.gl/core'; +import {ScatterplotLayer} from '@deck.gl/layers'; +import {GoogleMapsOverlay} from '@deck.gl/google-maps'; + +function DeckGLOverlay(props: DeckProps) { + const map = useMap(); + const overlay = useMemo(() => new GoogleMapsOverlay(props)); + + useEffect(() => { + if (map) { + overlay.setMap(map); + return () => overlay.setMap(null); + } + return undefined; + }, [map]) + + overlay.setProps(props); + return null; +} + +function App() { + const layers = [ + new ScatterplotLayer({ + id: 'deckgl-circle', + data: [ + {position: [0.45, 51.47]} + ], + getPosition: d => d.position, + getFillColor: [255, 0, 0, 100], + getRadius: 1000 + }) + ]; + + return + + + + ; +} +``` + + + ## Constructor -```js -const overlay = new GoogleMapsOverlay(props) +```ts +import {GoogleMapsOverlay} from '@deck.gl/google-maps'; +import type {GoogleMapsOverlayProps} from '@deck.gl/google-maps'; + +new GoogleMapsOverlay(props: GoogleMapsOverlayProps); ``` `props` are forwarded to a `Deck` instance. The following [Deck](../core/deck.md) props are supported: @@ -59,7 +130,7 @@ The constructor additionally accepts the following option: #### `setMap` {#setmap} -```js +```ts overlay.setMap(map); ``` @@ -67,7 +138,7 @@ Add/remove the overlay from a map. An overlay can be temporarily hidden from a m #### `setProps` {#setprops} -```js +```ts overlay.setProps(props); ``` @@ -87,12 +158,8 @@ Equivalent of [deck.pickMultipleObjects](../core/deck.md). #### `finalize` {#finalize} -```js -overlay.finalize(); -``` - Remove the overlay and release all underlying resources. ##### getCanvas -See [Deck.getCanvas](../core/deck.md#getcanvas). When using `interleaved: true`, returns the base map's `canvas`. \ No newline at end of file +See [Deck.getCanvas](../core/deck.md#getcanvas). When using `interleaved: true`, returns the base map's `canvas`. diff --git a/docs/api-reference/mapbox/mapbox-overlay.md b/docs/api-reference/mapbox/mapbox-overlay.md index 4230fb197dc..dc61f521691 100644 --- a/docs/api-reference/mapbox/mapbox-overlay.md +++ b/docs/api-reference/mapbox/mapbox-overlay.md @@ -4,130 +4,113 @@ ## Example -### Overlaid +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; -```js -import {MapboxOverlay} from '@deck.gl/mapbox'; -import {ScatterplotLayer} from '@deck.gl/layers'; + + -const map = new mapboxgl.Map({ - center: [-74.5, 40], - zoom: 14, - antialias: true // Improves the rendering quality -}); - -const overlay = new MapboxOverlay({ - interleaved: false, - layers: [ - new ScatterplotLayer({ - id: 'my-scatterplot', - data: [ - {position: [-74.5, 40], size: 100} - ], - getPosition: d => d.position, - getRadius: d => d.size, - getFillColor: [255, 0, 0] - }) - ] -}); - -map.addControl(overlay); -``` - -### Interleaved - -```js +```ts import {MapboxOverlay} from '@deck.gl/mapbox'; import {ScatterplotLayer} from '@deck.gl/layers'; +import mapboxgl from 'mapbox-gl'; +import 'mapbox-gl/dist/mapbox-gl.css'; const map = new mapboxgl.Map({ - center: [-74.5, 40], - zoom: 14, - antialias: true // Improves the rendering quality + container: 'map', + style: 'mapbox://styles/mapbox/light-v9', + accessToken: '', + center: [0.45, 51.47], + zoom: 11 }); -const overlay = new MapboxOverlay({ - interleaved: true, - layers: [ - new ScatterplotLayer({ - id: 'my-scatterplot', - data: [ - {position: [-74.5, 40], size: 100} - ], - getPosition: d => d.position, - getRadius: d => d.size, - getFillColor: [255, 0, 0], +map.once('load', () => { + const deckOverlay = new MapboxOverlay({ + interleaved: true, + layers: [ + new ScatterplotLayer({ + id: 'deckgl-circle', + data: [ + {position: [0.45, 51.47]} + ], + getPosition: d => d.position, + getFillColor: [255, 0, 0, 100], + getRadius: 1000, + beforeId: 'waterway-label' // In interleaved mode render the layer under map labels + }) + ] + }); - beforeId: 'admin_labels' // Insert before this Mapbox layer - }) - ] + map.addControl(deckOverlay); }); - -map.addControl(overlay); ``` -### Using with [react-map-gl](https://visgl.github.io/react-map-gl) - -The following code demonstrates how to create a React component from `MapboxOverlay` with `react-map-gl@7.x` and Typescript: + + ```tsx +import React from 'react'; +import {Map, useControl} from 'react-map-gl'; +import {MapboxOverlay} from '@deck.gl/mapbox'; +import {DeckProps} from '@deck.gl/core'; import {ScatterplotLayer} from '@deck.gl/layers'; -import {MapboxOverlay, MapboxOverlayProps} from '@deck.gl/mapbox'; -import {useControl} from 'react-map-gl'; +import 'mapbox-gl/dist/mapbox-gl.css'; -import Map, {NavigationControl} from 'react-map-gl'; - -function DeckGLOverlay(props: MapboxOverlayProps & { - interleaved?: boolean; -}) { +function DeckGLOverlay(props: DeckProps) { const overlay = useControl(() => new MapboxOverlay(props)); overlay.setProps(props); return null; } -export default function App() { - const scatterplotLayer = new ScatterplotLayer({ - id: 'my-scatterplot', - data: [ - {position: [-74.5, 40], size: 100} - ], - getPosition: d => d.position, - getRadius: d => d.size, - getFillColor: [255, 0, 0] - }); +function App() { + const layers: [ + new ScatterplotLayer({ + id: 'deckgl-circle', + data: [ + {position: [0.45, 51.47]} + ], + getPosition: d => d.position, + getFillColor: [255, 0, 0, 100], + getRadius: 1000, + beforeId: 'waterway-label' // In interleaved mode render the layer under map labels + }) + ]; return ( - - + ); } ``` See react-map-gl's [useControl](https://visgl.github.io/react-map-gl/docs/api-reference/use-control) hook. -See [using deck.gl with Typescript](https://deck.gl/docs/get-started/using-with-typescript). + + + ## Constructor -```js +```ts import {MapboxOverlay} from '@deck.gl/mapbox'; -new MapboxOverlay(props); +import type {MapboxOverlayProps} from '@deck.gl/mapbox'; + +new MapboxOverlay(props: MapboxOverlayProps); ``` `MapboxOverlay` accepts the same props as the [Deck](../core/deck.md) class, with the following exceptions: - `views` - multi-view support is limited. There is only one `MapView` that can synchronize with the base map. See the [using with multi-views](#multi-view-usage) section for details. -- `parent` / `canvas` / `gl` - context creation is managed internally. +- `parent` / `canvas` / `device` - context creation is managed internally. - `viewState` / `initialViewState` - camera state is managed internally. - `controller` - always disabled (to use Mapbox's interaction handlers). @@ -141,7 +124,7 @@ When using `interleaved: true`, you may optionally add a `beforeId` prop to a la ##### setProps -```js +```ts const overlay = new MapboxOverlay({ interleaved: true, layers: [] @@ -188,7 +171,7 @@ With that said, it is still possible to take advantage of deck's multi-view syst - To use multiple views, define a `MapView` with the id `“mapbox”`. This view will receive the state that matches the base map at each render. - If views are provided but the array does not contain this id, then a `MapView({id: 'mapbox'})` will be inserted at the bottom of the stack. -```js +```ts import {MapboxOverlay} from '@deck.gl/mapbox'; import {Deck, MapView, OrthographicView} from '@deck.gl/core'; import {ScatterplotLayer} from '@deck.gl/layers'; diff --git a/docs/developer-guide/base-maps/using-with-google-maps.md b/docs/developer-guide/base-maps/using-with-google-maps.md index f743756a308..76a8fbcd8b7 100644 --- a/docs/developer-guide/base-maps/using-with-google-maps.md +++ b/docs/developer-guide/base-maps/using-with-google-maps.md @@ -6,24 +6,187 @@ ![deck.gl as a Google Maps overlay](https://raw.github.com/visgl/deck.gl-data/master/images/whats-new/google-maps.jpg) -Deck.gl has interleaved and overlaid support for Google Maps with the [@deck.gl/google-maps](../../api-reference/google-maps/overview.md) module. It allows you to construct a Deck instance and apply it to a map using the Maps JavaScript API. +## Integration Modes -See [Google Maps documentation](../../api-reference/google-maps/overview.md) page for a full list of features. +When using deck.gl and Google Maps JavaScript API, there are three options you can choose from: interleaved, overlaid, and reverse-controlled. -## Google Maps Platform API key +### Interleaved -Note that to use deck.gl with the Google's basemap, you must load the Maps JavaScript API using a valid API key. For more information on getting an API key, see the [Google Maps Platform API key documentation](https://developers.google.com/maps/documentation/javascript/get-api-key) for the Maps JavaScript API. +The [interleaved](../../get-started/using-with-map.md#interleaved) mode renders deck.gl layers into the WebGL2 context created by Google's vector map, using the Maps JavaScript API [WebGLOverlayView class](https://developers.google.com/maps/documentation/javascript/webgl/webgl-overlay-view). If you need to mix deck.gl layers with Maps layers, e.g. having deck.gl objects and Maps 3D buildings occluding each other correctly, then you have to use this option. + +Interleaving is supported by using [GoogleMapsOverlay](../../api-reference/google-maps/google-maps-overlay.md) with an instance of Google's [vector map](https://developers.google.com/maps/documentation/javascript/vector-map). Some [limitations](../../api-reference/google-maps/overview.md#supported-features-and-limitations) apply when using this option. + + +### Overlaid + +The [overlaid](../../get-started/using-with-map.md#overlaid) mode renders deck.gl in a separate canvas inside the Maps' controls container, using the Maps JavaScript API [OverlayView class](https://developers.google.com/maps/documentation/javascript/reference/#OverlayView). + +This is supported by using [GoogleMapsOverlay](../../api-reference/google-maps/google-maps-overlay.md) with Google's [raster map](https://developers.google.com/maps/documentation/javascript/vector-map). When a deck.gl overlay instance is added to the map, if a vector map is not detected or the user's device does not support WebGL2, it will automatically fallback to overlaid mode. In this mode, 3D features like tilt, rotation, fraction zoom are not supported. + +### Reverse Controlled + +The reverse-controlled mode renders deck.gl above the Maps container and blocks any interaction to the base map. If your use case does not require interleaving, but you need to implement your own [pointer input handling](../../api-reference/core/controller.md), have multiple maps or a map that does not fill the whole canvas (with Deck's [multi-view feature](../views.md#using-multiple-views)), you need this to allow deck.gl manage the map's size and camera. + +You cannot use Maps' own UI controls such as the zoom buttons or layer selector with this option. Instead, use the components from `@deck.gl/widgets`. + + +## Examples + +### Example: interleaved or overlaid + +Both the interleaved and the overlaid options are supported in by the [@deck.gl/google-maps](../../api-reference/google-maps/overview.md) module. This is recommended approach for developers coming from the Google Maps JavaScript API ecosystem, as it handles fallbacks gracefully, as well as being compatible with other Maps controls and plugins. + + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + + + + +```ts +import {Loader} from "@googlemaps/js-api-loader"; +import {GoogleMapsOverlay} from '@deck.gl/google-maps'; +import {ScatterplotLayer} from '@deck.gl/layers'; + +const loader = new Loader({ + apiKey: '', + version: "quarterly" +}); + +loader.importLibrary('maps').then((googlemaps) => { + const map = new googlemaps.Map(document.getElementById('map'), { + center: {lat: 51.47, lng: 0.45}, + zoom: 5, + mapId: '' + }); + + const overlay = new GoogleMapsOverlay({ + layers: [ + new ScatterplotLayer({ + id: 'deckgl-circle', + data: [ + {position: [0.45, 51.47]} + ], + getPosition: d => d.position, + getFillColor: [255, 0, 0, 100], + getRadius: 1000 + }) + ] + }); -## Using interleaved + overlay.setMap(map); +}); +``` -Starting with v8.6, deck.gl added interleaving support on Google's vector map, using the Maps JavaScript API [WebGLOverlayView class](https://developers.google.com/maps/documentation/javascript/webgl/webgl-overlay-view). + + -When a Deck instance is applied to the map, deck.gl detects whether it is an instance of the vector map, then automatically enables interleaving. For information on how to enable the Google's vector map for the web, see the [Maps JavaScript API documentation](https://developers.google.com/maps/documentation/javascript/vector-map). +```tsx +import React, {useMemo, useEffect} from 'react'; +import {APIProvider, Map, useMap} from '@vis.gl/react-google-maps'; +import {DeckProps} from '@deck.gl/core'; +import {ScatterplotLayer} from '@deck.gl/layers'; +import {GoogleMapsOverlay} from '@deck.gl/google-maps'; -By default, when a Deck instance is added to the map, deck.gl will detect if the map is an instance of the vector map and enable interleaved mode. If the vector map is not detected or the user's device does not support WebGL2, deck.gl will automatically fallback to overlaid mode. +function DeckGLOverlay(props: DeckProps) { + const map = useMap(); + const overlay = useMemo(() => new GoogleMapsOverlay(props)); -## Using overlaid + useEffect(() => { + if (map) { + overlay.setMap(map); + return () => overlay.setMap(null); + } + return undefined; + }, [map]) -Starting with v7.0, deck.gl added support to overlay visualizations on Google's raster map using the Maps JavaScript API [OverlayView class](https://developers.google.com/maps/documentation/javascript/reference/#OverlayView). + overlay.setProps(props); + return null; +} + +function App() { + const layers = [ + new ScatterplotLayer({ + id: 'deckgl-circle', + data: [ + {position: [0.45, 51.47]} + ], + getPosition: d => d.position, + getFillColor: [255, 0, 0, 100], + getRadius: 1000 + }) + ]; + + return + + + + ; +} +``` + + + + +You can find full project setups in the [react get-started example](https://github.com/visgl/deck.gl/tree/master/examples/get-started/react/google-maps/) and [pure js get-started example](https://github.com/visgl/deck.gl/tree/master/examples/get-started/pure-js/google-maps/). + + +### Example: reverse controlled + +The reverse-controlled option is currently only supported in React when used with the `@visgl/react-google-maps` library. + +```tsx +import React from 'react'; +import {APIProvider, Map} from '@vis.gl/react-google-maps'; +import DeckGL from '@deck.gl/react'; +import {ScatterplotLayer} from '@deck.gl/layers'; + +function App() { + const layers = [ + new ScatterplotLayer({ + id: 'deckgl-circle', + data: [ + {position: [0.45, 51.47]} + ], + getPosition: d => d.position, + getFillColor: [255, 0, 0, 100], + getRadius: 1000 + }) + ]; + + return + + + + ; +} +``` + + +## Additional Information + +### react-google-maps + +[@visgl/react-google-maps](https://visgl.github.io/react-google-maps/) is a React wrapper around Google Maps JavaScript API maintained by the vis.gl community. If you'd like to use deck.gl together with Google Maps and React, this library is the recommended companion. + +When you choose the interleaved or overlaid option, the `@visgl/react-google-maps` [Map](https://visgl.github.io/react-google-maps/docs/api-reference/components/map) React component acts as the root component, and [GoogleMapsOverlay](../../api-reference/google-maps/google-maps-overlay.md) is used with a `useMemo` hook. + +When you choose the reverse-controlled option, the `DeckGL` React component cats as the root component, and the `@visgl/react-google-maps` [Map](https://visgl.github.io/react-google-maps/docs/api-reference/components/map) is a child. In this case, `Map` will automatically interpret the deck.gl view state (i.e. latitude, longitude, zoom etc), so that deck.gl layers will render as a synchronized geospatial overlay over the underlying map. + + +### Google Maps Platform API key + +Note that to use deck.gl with the Google's basemap, you must load the Maps JavaScript API using a valid API key. For more information on getting an API key, see the [Google Maps Platform API key documentation](https://developers.google.com/maps/documentation/javascript/get-api-key) for the Maps JavaScript API. -In this mode, the Deck canvas can only be used as a overlay on top of Google Maps, see [pure JS example](https://github.com/visgl/deck.gl/tree/master/examples/get-started/pure-js/google-maps), and 3D features like tilt, rotation, and interleaving are not supported. +If you are using `@visgl/react-google-maps`, supply the API key to the `APIProvider` and wrap it around all components that should have access to the Google Maps API. diff --git a/docs/developer-guide/base-maps/using-with-mapbox.md b/docs/developer-guide/base-maps/using-with-mapbox.md index 0cd412ea5a6..73628328e06 100644 --- a/docs/developer-guide/base-maps/using-with-mapbox.md +++ b/docs/developer-guide/base-maps/using-with-mapbox.md @@ -6,108 +6,237 @@ ![deck.gl interleaved with Mapbox layers](https://raw.github.com/visgl/deck.gl-data/master/images/whats-new/mapbox-layers.jpg) -[Mapbox GL JS](https://github.com/mapbox/mapbox-gl-js) is a powerful open-source map renderer from [Mapbox](https://mapbox.com). deck.gl's `MapView` is designed to sync perfectly with the camera of Mapbox, at every zoom level and rotation angle. +[Mapbox GL JS](https://github.com/mapbox/mapbox-gl-js) is a popular JavaScript library from [Mapbox](https://mapbox.com) for building web map applications. deck.gl's `MapView` can sync perfectly with the camera of Mapbox, at every zoom level and rotation angle. -When using deck.gl and Mapbox, there are three options you can choose from: +## Integration Modes -1. All deck.gl environments support deep integration with Mapbox features using the [@deck.gl/mapbox](../../api-reference/mapbox/overview.md) module. This is recommended approach as it supports interleaved and overlaid rendering, as well as Mapbox controls and plugins. See [Inserting deck.gl into the Mapbox container](#inserting-deckgl-into-the-mapbox-container). -2. The deck.gl React API supports an additional configuration when you just need a map backdrop and prefer to use the Deck API for [interactivity](../../developer-guide/interactivity.md). See [Inserting Mapbox into the deck.gl container](#inserting-mapbox-into-the-deckgl-container). -3. Finally, deck.gl offers out-of-the-box integration with Mapbox when using the [Scripting API](https://deck.gl/docs/get-started/using-standalone#using-the-scripting-api). +When using deck.gl and Mapbox, there are three options you can choose from: interleaved, overlaid, and reverse-controlled. + +### Interleaved + +The [interleaved](../../get-started/using-with-map.md#interleaved) mode renders deck.gl layers into the WebGL2 context created by Mapbox. If you need to mix deck.gl layers with Mapbox layers, e.g. having deck.gl surfaces below text labels, or objects occluding each other correctly in 3D, then you have to use this option. + +Interleaving is supported by using [MapboxOverlay](../../api-reference/mapbox/mapbox-overlay.md) with `interleaved: true`. It requires WebGL2 and therefore only works with `mapbox-gl@>2.13`. See [compatibility](../../api-reference/mapbox/overview#interleaved-renderer-compatibility) and [limitations](../../api-reference/mapbox/overview.md#limitations). + + +### Overlaid + +The [overlaid](../../get-started/using-with-map.md#overlaid) mode renders deck.gl in a separate canvas inside the Mapbox's controls container. If your use case does not require interleaving, but you still want to use certain features of mapbox-gl, such as mapbox-gl controls (e.g. `NavigationControl`, `Popup`) or plugins (e.g. [navigation directions](https://docs.mapbox.com/mapbox-gl-js/example/mapbox-gl-directions/), [mapbox-gl-draw](https://docs.mapbox.com/mapbox-gl-js/example/mapbox-gl-draw/)), then you should use this option. + +This is supported by using [MapboxOverlay](../../api-reference/mapbox/mapbox-overlay.md) with `interleaved: false`. + + +### Reverse Controlled + +The reverse-controlled mode renders deck.gl above the Mapbox container and blocks any interaction to the base map. If your use case does not require interleaving, but you need to implement your own [pointer input handling](../../api-reference/core/controller.md), have multiple maps or a map that does not fill the whole canvas (with Deck's [multi-view feature](../views.md#using-multiple-views)), you need this to allow deck.gl manage the map's size and camera. + +You cannot use mapbox-gl controls and plugins with this option. Instead, use the components from `@deck.gl/widgets`. + + +## Examples + +### Example: interleaved or overlaid + +Both the interleaved and the overlaid options are supported in by the [@deck.gl/mapbox](../../api-reference/mapbox/overview.md) module. This is recommended approach for developers coming from the Mapbox ecosystem, as it can easily switch between interleaved and overlaid rendering, as well as being compatible with other Mapbox controls and plugins. -## Inserting deck.gl into the Mapbox container import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; - + + + +```ts +import {MapboxOverlay} from '@deck.gl/mapbox'; +import {ScatterplotLayer} from '@deck.gl/layers'; +import mapboxgl from 'mapbox-gl'; +import 'mapbox-gl/dist/mapbox-gl.css'; + +const map = new mapboxgl.Map({ + container: 'map', + style: 'mapbox://styles/mapbox/light-v9', + accessToken: '', + center: [0.45, 51.47], + zoom: 11 +}); + +map.once('load', () => { + const deckOverlay = new MapboxOverlay({ + interleaved: true, + layers: [ + new ScatterplotLayer({ + id: 'deckgl-circle', + data: [ + {position: [0.45, 51.47]} + ], + getPosition: d => d.position, + getFillColor: [255, 0, 0, 100], + getRadius: 1000, + beforeId: 'waterway-label' // In interleaved mode render the layer under map labels + }) + ] + }); + + map.addControl(deckOverlay); +}); +``` + + -```jsx -import Map, {useControl} from 'react-map-gl'; -import { MapboxOverlay } from '@deck.gl/mapbox'; +```tsx +import React from 'react'; +import {Map, useControl} from 'react-map-gl'; +import {MapboxOverlay} from '@deck.gl/mapbox'; +import {DeckProps} from '@deck.gl/core'; +import {ScatterplotLayer} from '@deck.gl/layers'; +import 'mapbox-gl/dist/mapbox-gl.css'; -function DeckGLOverlay(props) { - const overlay = useControl(() => new MapboxOverlay(props)); +function DeckGLOverlay(props: DeckProps) { + const overlay = useControl(() => new MapboxOverlay(props)); overlay.setProps(props); return null; } - - - +function App() { + const layers: [ + new ScatterplotLayer({ + id: 'deckgl-circle', + data: [ + {position: [0.45, 51.47]} + ], + getPosition: d => d.position, + getFillColor: [255, 0, 0, 100], + getRadius: 1000, + beforeId: 'waterway-label' // In interleaved mode render the layer under map labels + }) + ]; + + return ( + + + + ); +} ``` - - -```js -import mapboxgl from 'mapbox-gl'; -import { MapboxOverlay as DeckOverlay } from '@deck.gl/mapbox'; + -const map = new mapboxgl.Map({ - center: [-74.5, 40], - zoom: 12 -}) -map.addControl(new DeckOverlay({ interleaved: true, layers: [] })) -``` - - +You can find full project setups in the [react get-started example](https://github.com/visgl/deck.gl/tree/master/examples/get-started/react/mapbox/) and [pure js get-started example](https://github.com/visgl/deck.gl/tree/master/examples/get-started/pure-js/mapbox/). -If you want to use features of mapbox-gl, such as controls like `NavigationControl` or plugins, then need to insert Deck into the Mapbox map container using [MapboxOverlay](../../api-reference/mapbox/mapbox-overlay) from the [@deck.gl/mapbox](../../api-reference/mapbox/overview.md) module, which allows you to construct a Deck instance and apply it to a map using the [IControl](https://docs.mapbox.com/mapbox-gl-js/api/markers/#icontrol) API. In this configuration mapbox-gl handles all user input, holds the source of truth of the camera state, and is the root HTML element of your map. -There are two renderers to pick from, overlaid or interleaved. +### Example: reverse controlled -### Overlaid +The reverse-controlled option is supported by the pre-built scripting bundle, and in React when used with the `react-map-gl` library. There is currently no easy way to do it under Vanilla JS. -If want to use the base map as a backdrop, the recommended approach is to use the Deck canvas as a overlay on top of the Mapbox map using [MapboxOverlay](../../api-reference/mapbox/mapbox-overlay) in its default mode (overlaid, which corresponds to `interleaved: false`). The [react get-started example](https://github.com/visgl/deck.gl/tree/master/examples/get-started/react/mapbox/) and [pure js get-started example](https://github.com/visgl/deck.gl/tree/master/examples/get-started/pure-js/mapbox/) illustrates this pattern. + + -### Interleaved +```js + + + + +``` -If you also need to mix deck.gl layers with base map layers, e.g. having deck.gl surfaces below text labels or objects occluding each other correctly in 3D, then you have to use deck.gl layers interleaved with Mapbox layers in the same WebGL2 context. In addition to using [MapboxOverlay](../../api-reference/mapbox/mapbox-overlay#using-with-react-map-gl) to insert Deck into the map container, you have to use interleaved mode (`interleaved: true`). Be cautious that this feature subjects to bugs and limitations of mapbox-gl's custom layer interface, and is only compatible with WebGL2 (See [interleaved renderer compatibility](../../api-reference/mapbox/overview#interleaved-renderer-compatibility)). The [pure js gallery example](https://github.com/visgl/deck.gl/blob/master/examples/gallery/src/mapbox-overlay.html) illustrates this pattern. + -## Inserting Mapbox into the deck.gl container + -```jsx +```tsx +import React from 'react'; +import {Map} from 'react-map-gl'; import DeckGL from '@deck.gl/react'; -import Map from 'react-map-gl'; - - - - +import {ScatterplotLayer} from '@deck.gl/layers'; +import 'mapbox-gl/dist/mapbox-gl.css'; + +function App() { + const layers: [ + new ScatterplotLayer({ + id: 'deckgl-circle', + data: [ + {position: [0.45, 51.47]} + ], + getPosition: d => d.position, + getFillColor: [255, 0, 0, 100], + getRadius: 1000, + }) + ]; + + return ( + + + + ); +} ``` -If you're using deck.gl in a React environment and just need a map backdrop, then you may use Deck as the root HTML element with its canvas as an overlay on top of the child Mapbox map. The [Minimap example](https://deck.gl/examples/multi-view) illustrates the basic pattern. This is a well tested and robust use case with respect to Deck's functionality, as you can find it in most of the [layer examples on this website](https://deck.gl/examples). You can't use all the features of mapbox-gl like controls (e.g. `NavigationControl`) and plugins, but you can instead use [@deck.gl/widgets](../../api-reference/widgets/overview). + + + -> Note: This usage is not supported in the Pure JS environment. +## Additional Information -## react-map-gl +### react-map-gl -[react-map-gl](https://github.com/visgl/react-map-gl) is a React wrapper around mapbox-gl. If you'd like to use deck.gl with React, this component is the recommended companion. +[react-map-gl](https://github.com/visgl/react-map-gl) is a React wrapper around mapbox-gl maintained by the vis.gl community. If you'd like to use deck.gl together with mapbox-gl and React, this library is the recommended companion. All the [examples on this website](https://github.com/visgl/deck.gl/tree/master/examples/website) are implemented using the React integration. -When you choose the react-map-gl `Map` React component as the root component, using [MapboxOverlay](../../api-reference/mapbox/mapbox-overlay#using-with-react-map-gl) with react-map-gl `useControl` works especially well to insert perfectly synchronized deck.gl layers in the map container. +When you choose the interleaved or overlaid option, the react-map-gl [Map](https://visgl.github.io/react-map-gl/docs/api-reference/map) React component acts as the root component, and [MapboxOverlay](../../api-reference/mapbox/mapbox-overlay#using-with-react-map-gl) is used with react-map-gl's `useControl` hook. -When you choose the `DeckGL` React component as the root component, react-map-gl [Map](https://visgl.github.io/react-map-gl/docs/api-reference/map) as a child automatically interprets the deck.gl view state (i.e. latitude, longitude, zoom etc). In this configuration your deck.gl layers will still render as a synchronized geospatial overlay over the underlying map. +When you choose the reverse-controlled option, the `DeckGL` React component cats as the root component, and the react-map-gl [Map](https://visgl.github.io/react-map-gl/docs/api-reference/map) is a child. In this case, `Map` will automatically interpret the deck.gl view state (i.e. latitude, longitude, zoom etc), so that deck.gl layers will render as a synchronized geospatial overlay over the underlying map. -> Using `DeckGL` as the root component is not compatible with `react-map-gl` controls (`NavigationControl`, `GeolocateControl` etc.) because of `react-map-gl` decisions to prioritize its own maintainability, performance, and compatibility when used standalone. -## Using Mapbox basemap service (with Mapbox token) +### Mapbox Token -The mapbox-gl library is a popular commercial basemap with a free tier. To use Mapbox, you will need to register on their website in order to retrieve an [access token](https://docs.mapbox.com/help/how-mapbox-works/access-tokens/) required by the map component, which will be used to identify you and start serving up map tiles. The service will be free until a [certain level](https://www.mapbox.com/pricing/) of traffic is exceeded. +To use Mapbox, you will need to register on their website in order to retrieve an [access token](https://docs.mapbox.com/help/how-mapbox-works/access-tokens/) required by the map component, which will be used to identify you and start serving up map tiles. The service will be free until a [certain level](https://www.mapbox.com/pricing/) of traffic is exceeded. If you are using mapbox-gl without React, check out [Mapbox GL JS API](https://docs.mapbox.com/mapbox-gl-js/api/#accesstoken) for how to apply the token. @@ -115,35 +244,11 @@ If you are using react-map-gl, there are several ways to provide a token to your * Set the `MapboxAccessToken` environment variable. You may need to add additional set up to the bundler ([example](https://webpack.js.org/plugins/environment-plugin/)) so that `process.env.MapboxAccessToken` is accessible at runtime. * Provide it in the URL, e.g `?access_token=TOKEN` -* Pass it as a prop to the react-map-gl `Map` instance `` - -## Compatibility with Mapbox GL JS forks - -As of v2.0, Mapbox GL JS [went proprietary](https://github.com/mapbox/mapbox-gl-js/blob/main/CHANGELOG.md#200) and requires a Mapbox account to use even if you don't load tiles from the Mapbox data service. Community forks of the v1 code base such as [MapLibre GL JS](https://maplibre.org) can generally be used as a drop-in replacement of mapbox-gl. If you are using react-map-gl, see [their Get Started guide](http://visgl.github.io/react-map-gl/docs/get-started) for more details. - -We provide get-started examples with Maplibre GL JS for [pure js](https://github.com/visgl/deck.gl/tree/master/examples/get-started/pure-js/maplibre/) and [react](https://github.com/visgl/deck.gl/tree/master/examples/get-started/react/maplibre/), and an interleaved rendering example in our [gallery](https://github.com/visgl/deck.gl/blob/master/examples/gallery/src/maplibre-overlay.html). - -If the forked libraries and Mapbox API diverge in the future, compatibility issues may arise. deck.gl intends to support open source efforts wherever reasonable. Please report any issue on GitHub. - -## Using with other basemap services - -It is possible to use the map component without the Mapbox service, you need a URL that conforms to the [Mapbox Style Specification](https://www.mapbox.com/mapbox-gl-js/style-spec) and pass it to the `mapStyle` prop in mapbox-gl `Map` constructor or react-map-gl `Map` component. - -You can use existing free vector tile services: - -- [CARTO free basemaps](https://carto.com/basemaps) for non commercial applications. Checkout [this guide](../../api-reference/carto/basemap.md) to start using it. - -### Hosting your own basemap service - -If you host your own map tiles, you will need a custom Mapbox GL style that points to your own [vector tile source](https://www.mapbox.com/mapbox-gl-js/style-spec/), this custom style must match the schema of your tile source. - -Open source tile schemas include: +* Pass it as a prop to the react-map-gl `Map` component `` -- [TileZen schema](https://tilezen.readthedocs.io/en/latest/layers/) -- [OpenMapTiles schema ](https://openmaptiles.org/schema/) +### Alternatives to Mapbox basemap sevice -Some useful resources for creating your own map service: +As of v2.0, Mapbox GL JS [went proprietary](https://github.com/mapbox/mapbox-gl-js/blob/main/CHANGELOG.md#200) and requires a Mapbox account to use even if you don't load tiles from the Mapbox server. If you do not wish to use the Mapbox service, you may also consider: -- [Mapbox Vector Tile Spec](https://www.mapbox.com/developers/vector-tiles/) -- [Open source tools](https://github.com/mapbox/awesome-vector-tiles) -- [Maputnik Style editor](https://maputnik.github.io) +- mapbox-gl v1.13, the last release before the license change. Interleaving is not supported by this version. +- [MapLibre GL JS](https://maplibre.org), a community-supported WebGL map library. maplibre-gl can generally be used as a drop-in replacement of mapbox-gl, with some of its own features and APIs. More information can be found in [using with Maplibre](./using-with-maplibre.md). diff --git a/docs/developer-guide/base-maps/using-with-maplibre.md b/docs/developer-guide/base-maps/using-with-maplibre.md new file mode 100644 index 00000000000..0f0baa0aeee --- /dev/null +++ b/docs/developer-guide/base-maps/using-with-maplibre.md @@ -0,0 +1,248 @@ +# Using with Maplibre + +| Pure JS | React | Overlaid | Interleaved | +| ----- | ----- | ----- | ----- | +| ✓ | ✓ | [example](https://github.com/visgl/deck.gl/tree/master/examples/get-started/pure-js/maplibre) | [example](https://deck.gl/gallery/maplibre-overlay) | + +[Maplibre GL JS](https://maplibre.org/maplibre-gl-js/docs/) is a powerful open-source library that uses WebGL to render interactive maps from vector tiles in a browser. deck.gl's `MapView` can sync perfectly with the camera of Maplibre, at every zoom level and rotation angle. + +## Integration Modes + +When using deck.gl and Maplibre, there are three options you can choose from: interleaved, overlaid, and reverse-controlled. + +### Interleaved + +The [interleaved](../../get-started/using-with-map.md#interleaved) mode renders deck.gl layers into the WebGL2 context created by Maplibre. If you need to mix deck.gl layers with Maplibre layers, e.g. having deck.gl surfaces below text labels, or objects occluding each other correctly in 3D, then you have to use this option. + +Interleaving is supported by using [MapboxOverlay](../../api-reference/mapbox/mapbox-overlay.md) with `interleaved: true`. It requires WebGL2 and therefore only works with `maplibre-gl@>3`. See [compatibility](../../api-reference/mapbox/overview#interleaved-renderer-compatibility) and [limitations](../../api-reference/mapbox/overview.md#limitations). + + +### Overlaid + +The [overlaid](../../get-started/using-with-map.md#overlaid) mode renders deck.gl in a separate canvas inside the Maplibre's controls container. If your use case does not require interleaving, but you still want to use certain features of maplibre-gl, such as maplibre-gl controls (e.g. `NavigationControl`, `Popup`) or plugins (e.g. [navigation directions](https://github.com/mapbox/mapbox-gl-directions), [mapbox-gl-draw](https://maplibre.org/maplibre-gl-js/docs/examples/mapbox-gl-draw/)), then you should use this option. + +This is supported by using [MapboxOverlay](../../api-reference/mapbox/mapbox-overlay.md) with `interleaved: false`. + + +### Reverse Controlled + +The reverse-controlled mode renders deck.gl above the Maplibre container and blocks any interaction to the base map. If your use case does not require interleaving, but you need to implement your own [pointer input handling](../../api-reference/core/controller.md), have multiple maps or a map that does not fill the whole canvas (with Deck's [multi-view feature](../views.md#using-multiple-views)), you need this to allow deck.gl manage the map's size and camera. + +You cannot use maplibre-gl controls and plugins with this option. Instead, use the components from `@deck.gl/widgets`. + + +## Examples + +### Example: interleaved or overlaid + +Both the interleaved and the overlaid options are supported in by the [@deck.gl/mapbox](../../api-reference/mapbox/overview.md) module. This is recommended approach for developers coming from the Maplibre ecosystem, as it can easily switch between interleaved and overlaid rendering, as well as being compatible with other Maplibre controls and plugins. + + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + + + + +```ts +import {MapboxOverlay} from '@deck.gl/mapbox'; +import {ScatterplotLayer} from '@deck.gl/layers'; +import maplibregl from 'maplibre-gl'; +import 'maplibre-gl/dist/maplibre-gl.css'; + +const map = new maplibregl.Map({ + container: 'map', + style: 'https://basemaps.cartocdn.com/gl/positron-gl-style/style.json', + center: [0.45, 51.47], + zoom: 11 +}); + +map.once('load', () => { + const deckOverlay = new MapboxOverlay({ + interleaved: true, + layers: [ + new ScatterplotLayer({ + id: 'deckgl-circle', + data: [ + {position: [0.45, 51.47]} + ], + getPosition: d => d.position, + getFillColor: [255, 0, 0, 100], + getRadius: 1000, + beforeId: 'watername_ocean' // In interleaved mode render the layer under map labels + }) + ] + }); + + map.addControl(deckOverlay); +}); +``` + + + + +```tsx +import React from 'react'; +import {Map, useControl} from 'react-map-gl/maplibre'; +import {MapboxOverlay} from '@deck.gl/mapbox'; +import {DeckProps} from '@deck.gl/core'; +import {ScatterplotLayer} from '@deck.gl/layers'; +import 'maplibre-gl/dist/maplibre-gl.css'; + +function DeckGLOverlay(props: DeckProps) { + const overlay = useControl(() => new MapboxOverlay(props)); + overlay.setProps(props); + return null; +} + +function App() { + const layers: [ + new ScatterplotLayer({ + id: 'deckgl-circle', + data: [ + {position: [0.45, 51.47]} + ], + getPosition: d => d.position, + getFillColor: [255, 0, 0, 100], + getRadius: 1000, + beforeId: 'watername_ocean' // In interleaved mode render the layer under map labels + }) + ]; + + return ( + + + + ); +} +``` + + + + + +You can find full project setups in the [react get-started example](https://github.com/visgl/deck.gl/tree/master/examples/get-started/react/maplibre/) and [pure js get-started example](https://github.com/visgl/deck.gl/tree/master/examples/get-started/pure-js/maplibre/). + + +### Example: reverse controlled + +The reverse-controlled option is supported by the pre-built scripting bundle, and in React when used with the `react-map-gl` library. There is currently no easy way to do it under Vanilla JS. + + + + +```js + + + + +``` + + + + + +```tsx +import React from 'react'; +import {Map} from 'react-map-gl/maplibre'; +import DeckGL from '@deck.gl/react'; +import {ScatterplotLayer} from '@deck.gl/layers'; +import 'maplibre-gl/dist/maplibre-gl.css'; + +function App() { + const layers: [ + new ScatterplotLayer({ + id: 'deckgl-circle', + data: [ + {position: [0.45, 51.47]} + ], + getPosition: d => d.position, + getFillColor: [255, 0, 0, 100], + getRadius: 1000, + }) + ]; + + return ( + + + + ); +} +``` + + + + + +## Additional Information + +### react-map-gl + +[react-map-gl](https://github.com/visgl/react-map-gl) is a React wrapper around maplibre-gl maintained by the vis.gl community. If you'd like to use deck.gl together with maplibre-gl and React, this library is the recommended companion. + +All the [examples on this website](https://github.com/visgl/deck.gl/tree/master/examples/website) are implemented using the React integration. + +When you choose the interleaved or overlaid option, the react-map-gl [Map](https://visgl.github.io/react-map-gl/docs/api-reference/map) React component acts as the root component, and [MapboxOverlay](../../api-reference/mapbox/mapbox-overlay#using-with-react-map-gl) is used with react-map-gl's `useControl` hook. + +When you choose the reverse-controlled option, the `DeckGL` React component cats as the root component, and the react-map-gl [Map](https://visgl.github.io/react-map-gl/docs/api-reference/map) is a child. In this case, `Map` will automatically interpret the deck.gl view state (i.e. latitude, longitude, zoom etc), so that deck.gl layers will render as a synchronized geospatial overlay over the underlying map. + + +### Choosing a map tile service + +There are paid map tile servers such as [MapTiler](https://www.maptiler.com/) and [AWS Location Service](https://docs.aws.amazon.com/location/latest/developerguide/map-concepts.html). + +deck.gl public demos use [CARTO free basemaps](https://carto.com/basemaps) as a non commercial application. Checkout [this guide](../../api-reference/carto/basemap.md) to start using it. + +If you host your own map tiles, you will need a custom map style JSON that points to your own [vector tile source](https://maplibre.org/maplibre-style-spec/), this custom style must match the schema of your tile source. + +Open source tile schemas include: + +- [TileZen schema](https://tilezen.readthedocs.io/en/latest/layers/) +- [OpenMapTiles schema ](https://openmaptiles.org/schema/) +- [Mapbox Vector Tile Spec](https://www.mapbox.com/developers/vector-tiles/) + +Some useful resources for creating your own map service: + +- [Martin](https://github.com/maplibre/martin), a tile server from the Maplibre organization +- [Open source tools](https://github.com/mapbox/awesome-vector-tiles) +- [Maputnik Style editor](https://maplibre.org/maputnik/) diff --git a/docs/get-started/using-with-map.md b/docs/get-started/using-with-map.md index 7cbdc8c4280..f93adbd81ed 100644 --- a/docs/get-started/using-with-map.md +++ b/docs/get-started/using-with-map.md @@ -8,11 +8,15 @@ deck.gl has been designed to work in tandem with popular JavaScript base map pro There are two types of integration between deck.gl and a base map renderer: -- **Overlaid**: the Deck canvas is rendered over the base map as a separate DOM element. Deck's camera and the camera of the base map are synchronized so they pan/zoom together. This is the more robust option since the two libraries manage their renderings independently from each other. It is usually sufficient if the base map is 2D. +### Overlaid + +The Deck canvas is rendered over the base map as a separate DOM element. Deck's camera and the camera of the base map are synchronized so they pan/zoom together. This is the more robust option since the two libraries manage their renderings independently from each other. It is usually sufficient if the base map is 2D. ![Deck as overlay on top of the base map](https://miro.medium.com/max/1600/0*K3DVssEhnv5VaDCp) -- **Interleaved**: Deck renders into the WebGL2 context of the base map. This allows for occlusion between deck.gl layers and the base map's labels and/or 3D features. The availability of this option depends on whether the base map solution exposes certain developer APIs, and may subject the user to bugs/limitations associated with such APIs. +### Interleaved + +Deck renders into the WebGL2 context of the base map. This allows for occlusion between deck.gl layers and the base map's labels and/or 3D features. The availability of this option depends on whether the base map solution exposes certain developer APIs, and may subject the user to bugs/limitations associated with such APIs. > Note: Deck cannot render into a WebGL1 context. Check your base map solution for WebGL2 compatibility. @@ -26,7 +30,7 @@ There are two types of integration between deck.gl and a base map renderer: | [harp.gl](https://www.harp.gl/) | ✓ | | [example](https://github.com/visgl/deck.gl/tree/master/examples/get-started/pure-js/harp.gl) | | | | [Leaflet](https://leafletjs.com/) | ✓ | | [example](https://github.com/visgl/deck.gl/tree/master/examples/get-started/pure-js/leaflet) | | | | [Mapbox GL JS](https://docs.mapbox.com/mapbox-gl-js/api/) | ✓ | ✓ | [example](https://github.com/visgl/deck.gl/tree/master/examples/get-started/pure-js/mapbox) | [example](https://deck.gl/gallery/mapbox-overlay) | [link](../developer-guide/base-maps/using-with-mapbox.md) | -| [MapLibre GL JS](https://maplibre.org/maplibre-gl-js-docs/api/) | ✓ | ✓ | [example](https://github.com/visgl/deck.gl/tree/master/examples/get-started/pure-js/maplibre) | [example](https://deck.gl/gallery/maplibre-overlay) | [link](../developer-guide/base-maps/using-with-mapbox.md#compatibility-with-mapbox-gl-js-forks) | +| [MapLibre GL JS](https://maplibre.org/maplibre-gl-js-docs/api/) | ✓ | ✓ | [example](https://github.com/visgl/deck.gl/tree/master/examples/get-started/pure-js/maplibre) | [example](https://deck.gl/gallery/maplibre-overlay) | [link](../developer-guide/base-maps/using-with-maplibre.md) | | [OpenLayers](https://openlayers.org/) | ✓ | | [example](https://github.com/visgl/deck.gl/tree/master/examples/get-started/pure-js/openlayers) | | | It is also important to understand the difference between the JS library that renders the map and the map data provider. For example, you can use Mapbox GL JS with the Mapbox service, but also with any other service that hosts Mapbox Vector Tiles. When using a base map, be sure to follow the terms and conditions, as well as the attribution requirements of both the JS library and the data provider. diff --git a/docs/table-of-contents.json b/docs/table-of-contents.json index 5815994e69e..361026abdde 100644 --- a/docs/table-of-contents.json +++ b/docs/table-of-contents.json @@ -16,9 +16,9 @@ "items": [ "get-started/getting-started", "get-started/using-standalone", - "get-started/using-with-map", "get-started/using-with-react", "get-started/using-with-typescript", + "get-started/using-with-map", "get-started/learning-resources" ] }, @@ -50,7 +50,8 @@ "items": [ "developer-guide/base-maps/using-with-arcgis", "developer-guide/base-maps/using-with-google-maps", - "developer-guide/base-maps/using-with-mapbox" + "developer-guide/base-maps/using-with-mapbox", + "developer-guide/base-maps/using-with-maplibre" ] }, { diff --git a/docs/upgrade-guide.md b/docs/upgrade-guide.md index 9784dbf909f..b6684002019 100644 --- a/docs/upgrade-guide.md +++ b/docs/upgrade-guide.md @@ -652,7 +652,7 @@ Breaking Changes: #### Lighting The old experimental prop `lightSettings` in many 3D layers is no longer supported. The new and improved settings are split into two places: a [material](https://github.com/visgl/luma.gl/tree/master/docs/api-reference/core/materials) prop for each 3D layer and a shared set of lights specified by [LightingEffect](./api-reference/core/lighting-effect.md) with the [effects prop of Deck](./api-reference/core/deck.md#effects). -Check [Using Lighting](./developer-guide/using-lighting.md) in developer guide for more details. +Check [Using Lighting](./developer-guide/using-effects.md) in developer guide for more details. #### Views