Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(examples) add mapbox and maplibre get-started examples #8562

Merged
merged 13 commits into from Mar 6, 2024
Merged
6 changes: 3 additions & 3 deletions docs/developer-guide/base-maps/using-with-mapbox.md
Expand Up @@ -2,14 +2,14 @@

| 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/mapbox-layer) |
| ✓ | ✓ | [example](https://github.com/visgl/deck.gl/tree/master/examples/get-started/pure-js/mapbox) | [example](https://deck.gl/gallery/mapbox-layer) |

[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.

When using deck.gl and Mapbox, there are three options you can choose from:

- Using the Deck canvas as a overlay on top of the Mapbox map, and Deck as the root element. In this option, deck.gl handles all user input, and holds the source of truth of the camera state. The [React get-started example](https://github.com/visgl/deck.gl/tree/master/examples/get-started/react/mapbox/) illustrates the basic pattern. This is the most tested and robust use case, as you can find in all the [examples on this website](https://deck.gl/examples/website). It supports all the features of Deck.
- Using the Deck canvas as a overlay on top of the Mapbox map, and Mapbox as the root element. In this option, mapbox-gl handles all user input, and holds the source of truth of the camera state. The [vanilla JS get-started example](https://github.com/visgl/deck.gl/tree/master/examples/get-started/pure-js/maplibre/) illustrates this pattern. The `MapboxOverlay` class in [@deck.gl/mapbox](../../api-reference/mapbox/overview.md) implements the mapbox-gl control interface to insert deck into the map container. This is favorable if you need to use other mapbox-gl controls and plugins in addition to deck.gl.
- Using the Deck canvas as a overlay on top of the Mapbox map, and Mapbox as the root element. In this option, mapbox-gl handles all user input, and holds the source of truth of the camera state. The [vanilla JS get-started example](https://github.com/visgl/deck.gl/tree/master/examples/get-started/pure-js/mapbox/) illustrates this pattern. The `MapboxOverlay` class in [@deck.gl/mapbox](../../api-reference/mapbox/overview.md) implements the mapbox-gl control interface to insert deck into the map container. This is favorable if you need to use other mapbox-gl controls and plugins in addition to deck.gl.
- Using deck.gl layers interleaved with Mapbox layers in the same WebGL2 context, using either the `MapboxOverlay` or `MapboxLayer` from the [@deck.gl/mapbox](../../api-reference/mapbox/overview.md) module. This allows you to mix deck.gl layers with base map layers, e.g. below text labels or occlude each other correctly in 3D. Be cautious that this feature subjects to bugs and limitations of mapbox-gl's custom layer interface.

![deck.gl interleaved with Mapbox layers](https://raw.github.com/visgl/deck.gl-data/master/images/whats-new/mapbox-layers.jpg)
Expand All @@ -32,7 +32,7 @@ If you are using mapbox-gl without React, check out [Mapbox GL JS API](https://d

If you are using react-map-gl, there are several ways to provide a token to your app:

* 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.MapboxAccessToekn` is accessible at runtime.
* 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 ReactMapGL instance `<ReactMapGL mapboxAccessToken={TOKEN} />`

Expand Down
27 changes: 27 additions & 0 deletions examples/get-started/pure-js/mapbox/README.md
@@ -0,0 +1,27 @@
## Example: Use deck.gl with Mapbox

Uses [Vite](https://vitejs.dev/) to bundle and serve files.

## Usage

To run this example, you need a [Mapbox access token](https://docs.mapbox.com/help/how-mapbox-works/access-tokens/). You can either set an environment variable:

```bash
export MapboxAccessToken=<mapbox_access_token>
```

Or set `MAPBOX_TOKEN` directly in `app.js`.

Other options can be found at [using with Mapbox GL](../../../../docs/developer-guide/base-maps/using-with-mapbox.md).

To install dependencies:

```bash
npm install
# or
yarn
```

Commands:
* `npm start` is the development target, to serve the app and hot reload.
* `npm run build` is the production target, to create the final bundle and write to disk.
58 changes: 58 additions & 0 deletions examples/get-started/pure-js/mapbox/app.js
@@ -0,0 +1,58 @@
import {MapboxOverlay as DeckOverlay} from '@deck.gl/mapbox';
import {GeoJsonLayer, ArcLayer} from '@deck.gl/layers';
import mapboxgl from 'mapbox-gl';
import 'mapbox-gl/dist/mapbox-gl.css';

// source: Natural Earth http://www.naturalearthdata.com/ via geojson.xyz
const AIR_PORTS =
'https://d2ad6b4ur7yvpq.cloudfront.net/naturalearth-3.3.0/ne_10m_airports.geojson';

// Set your Mapbox token here or via environment variable
const MAPBOX_TOKEN = process.env.MapboxAccessToken; // eslint-disable-line

const map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/light-v9',
accessToken: MAPBOX_TOKEN,
center: [0.45, 51.47],
zoom: 4,
bearing: 0,
pitch: 30
});

const deckOverlay = new DeckOverlay({
// interleaved: true,
layers: [
new GeoJsonLayer({
id: 'airports',
data: AIR_PORTS,
// Styles
filled: true,
pointRadiusMinPixels: 2,
pointRadiusScale: 2000,
getPointRadius: f => 11 - f.properties.scalerank,
getFillColor: [200, 0, 80, 180],
// Interactive props
pickable: true,
autoHighlight: true,
onClick: info =>
// eslint-disable-next-line
info.object && alert(`${info.object.properties.name} (${info.object.properties.abbrev})`),
// beforeId: 'waterway-label' // In interleaved mode render the layer under map labels
}),
new ArcLayer({
id: 'arcs',
data: AIR_PORTS,
dataTransform: d => d.features.filter(f => f.properties.scalerank < 4),
// Styles
getSourcePosition: f => [-0.4531566, 51.4709959], // London
getTargetPosition: f => f.geometry.coordinates,
getSourceColor: [0, 128, 200],
getTargetColor: [200, 0, 80],
getWidth: 1
})
]
});

map.addControl(deckOverlay);
map.addControl(new mapboxgl.NavigationControl());
20 changes: 20 additions & 0 deletions examples/get-started/pure-js/mapbox/index.html
@@ -0,0 +1,20 @@
<!doctype html>
<html>
<head>
<meta charset='UTF-8' />
<title>deck.gl example</title>
<style>
#map {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
</style>
</head>
<body>
<div id="map"></div>
<script type="module" src='app.js'></script>
</body>
</html>
20 changes: 20 additions & 0 deletions examples/get-started/pure-js/mapbox/package.json
@@ -0,0 +1,20 @@
{
"name": "deckgl-example-pure-js-mapbox",
"version": "0.0.0",
"private": true,
"license": "MIT",
"scripts": {
"start": "vite --open",
"start-local": "vite --config ../../../vite.config.local.mjs",
"build": "vite build"
},
"dependencies": {
"@deck.gl/core": "^9.0.0-beta",
"@deck.gl/layers": "^9.0.0-beta",
"@deck.gl/mapbox": "^9.0.0-beta",
"mapbox-gl": "^3.0.0"
},
"devDependencies": {
"vite": "^4.0.0"
}
}
5 changes: 5 additions & 0 deletions examples/get-started/pure-js/mapbox/vite.config.js
@@ -0,0 +1,5 @@
export default {
define: {
'process.env.MapboxAccessToken': JSON.stringify(process.env.MapboxAccessToken),
}
};
6 changes: 4 additions & 2 deletions examples/get-started/pure-js/maplibre/app.js
Expand Up @@ -9,14 +9,15 @@ const AIR_PORTS =

const map = new maplibregl.Map({
container: 'map',
style: 'https://basemaps.cartocdn.com/gl/positron-nolabels-gl-style/style.json',
style: 'https://basemaps.cartocdn.com/gl/positron-gl-style/style.json',
center: [0.45, 51.47],
zoom: 4,
bearing: 0,
pitch: 30
});

const deckOverlay = new DeckOverlay({
// interleaved: true,
layers: [
new GeoJsonLayer({
id: 'airports',
Expand All @@ -32,7 +33,8 @@ const deckOverlay = new DeckOverlay({
autoHighlight: true,
onClick: info =>
// eslint-disable-next-line
info.object && alert(`${info.object.properties.name} (${info.object.properties.abbrev})`)
info.object && alert(`${info.object.properties.name} (${info.object.properties.abbrev})`),
// beforeId: 'watername_ocean' // In interleaved mode, render the layer under map labels
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Pessimistress, FYI added interleaved option

}),
new ArcLayer({
id: 'arcs',
Expand Down
1 change: 0 additions & 1 deletion examples/get-started/pure-js/maplibre/index.html
Expand Up @@ -12,7 +12,6 @@
bottom: 0;
}
</style>
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v1.13.0/mapbox-gl.css' rel='stylesheet' />
</head>
<body>
<div id="map"></div>
Expand Down
16 changes: 11 additions & 5 deletions examples/get-started/react/mapbox/README.md
@@ -1,9 +1,19 @@
## Example: Use deck.gl with react-map-gl and Webpack
## Example: Use deck.gl with react-map-gl and Mapbox

Uses [Vite](https://vitejs.dev/) to bundle and serve files.

## Usage

To run this example, you need a [Mapbox access token](https://docs.mapbox.com/help/how-mapbox-works/access-tokens/). You can either set an environment variable:

```bash
export MapboxAccessToken=<mapbox_access_token>
```

Or set `MAPBOX_TOKEN` directly in `app.jsx`.

Other options can be found at [using with Mapbox GL](../../../../docs/developer-guide/base-maps/using-with-mapbox.md).

To install dependencies:

```bash
Expand All @@ -15,7 +25,3 @@ yarn
Commands:
* `npm start` is the development target, to serve the app and hot reload.
* `npm run build` is the production target, to create the final bundle and write to disk.

### Basemap

The basemap in this example is provided by [CARTO free basemap service](https://carto.com/basemaps). To use an alternative base map solution, visit [this guide](https://deck.gl/docs/get-started/using-with-map#using-other-basemap-services)
17 changes: 11 additions & 6 deletions examples/get-started/react/mapbox/app.jsx
@@ -1,14 +1,17 @@
import React from 'react';
import {createRoot} from 'react-dom/client';
import {Map, NavigationControl, useControl} from 'react-map-gl/maplibre';
import DeckGL, {GeoJsonLayer, ArcLayer} from 'deck.gl';
import {Map, NavigationControl, useControl} from 'react-map-gl';
import {GeoJsonLayer, ArcLayer} from 'deck.gl';
import {MapboxOverlay as DeckOverlay} from '@deck.gl/mapbox';
import 'maplibre-gl/dist/maplibre-gl.css';
import 'mapbox-gl/dist/mapbox-gl.css';

// source: Natural Earth http://www.naturalearthdata.com/ via geojson.xyz
const AIR_PORTS =
'https://d2ad6b4ur7yvpq.cloudfront.net/naturalearth-3.3.0/ne_10m_airports.geojson';

// Set your Mapbox token here or via environment variable
const MAPBOX_TOKEN = process.env.MapboxAccessToken; // eslint-disable-line

const INITIAL_VIEW_STATE = {
latitude: 51.47,
longitude: 0.45,
Expand All @@ -17,7 +20,7 @@ const INITIAL_VIEW_STATE = {
pitch: 30
};

const MAP_STYLE = 'https://basemaps.cartocdn.com/gl/positron-nolabels-gl-style/style.json';
const MAP_STYLE = 'mapbox://styles/mapbox/light-v9';
function DeckGLOverlay(props) {
const overlay = useControl(() => new DeckOverlay(props));
overlay.setProps(props);
Expand Down Expand Up @@ -45,7 +48,8 @@ function Root() {
// Interactive props
pickable: true,
autoHighlight: true,
onClick
onClick,
// beforeId: 'waterway-label' // In interleaved mode render the layer under map labels
}),
new ArcLayer({
id: 'arcs',
Expand All @@ -64,8 +68,9 @@ function Root() {
<Map
initialViewState={INITIAL_VIEW_STATE}
mapStyle={MAP_STYLE}
mapboxAccessToken={MAPBOX_TOKEN}
>
<DeckGLOverlay layers={layers} />
<DeckGLOverlay layers={layers} /*interleaved*/ />
<NavigationControl position='top-left' />
</Map>
);
Expand Down
6 changes: 3 additions & 3 deletions examples/get-started/react/mapbox/package.json
@@ -1,5 +1,5 @@
{
"name": "deckgl-example-react-map-gl",
"name": "deckgl-example-react-map-gl-mapbox",
"version": "0.0.0",
"private": true,
"license": "MIT",
Expand All @@ -9,8 +9,8 @@
"build": "vite build"
},
"dependencies": {
"deck.gl": "^9.0.0-beta.2",
"maplibre-gl": "^2.4.0",
"deck.gl": "^9.0.0-beta",
"mapbox-gl": "^3.0.0",
"react": "^18.0.0",
"react-dom": "^18.0.0",
"react-map-gl": "^7.0.0"
Expand Down
5 changes: 5 additions & 0 deletions examples/get-started/react/mapbox/vite.config.js
@@ -0,0 +1,5 @@
export default {
define: {
'process.env.MapboxAccessToken': JSON.stringify(process.env.MapboxAccessToken),
}
};
21 changes: 21 additions & 0 deletions examples/get-started/react/maplibre/README.md
@@ -0,0 +1,21 @@
## Example: Use deck.gl with react-map-gl and Maplibre

Uses [Vite](https://vitejs.dev/) to bundle and serve files.

## Usage

To install dependencies:

```bash
npm install
# or
yarn
```

Commands:
* `npm start` is the development target, to serve the app and hot reload.
* `npm run build` is the production target, to create the final bundle and write to disk.

### Basemap

The basemap in this example is provided by [CARTO free basemap service](https://carto.com/basemaps). To use an alternative base map solution, visit [this guide](https://deck.gl/docs/get-started/using-with-map#using-other-basemap-services)
77 changes: 77 additions & 0 deletions examples/get-started/react/maplibre/app.jsx
@@ -0,0 +1,77 @@
import React from 'react';
import {createRoot} from 'react-dom/client';
import {Map, NavigationControl, useControl} from 'react-map-gl/maplibre';
import {GeoJsonLayer, ArcLayer} from 'deck.gl';
import {MapboxOverlay as DeckOverlay} from '@deck.gl/mapbox';
import 'maplibre-gl/dist/maplibre-gl.css';

// source: Natural Earth http://www.naturalearthdata.com/ via geojson.xyz
const AIR_PORTS =
'https://d2ad6b4ur7yvpq.cloudfront.net/naturalearth-3.3.0/ne_10m_airports.geojson';

const INITIAL_VIEW_STATE = {
latitude: 51.47,
longitude: 0.45,
zoom: 4,
bearing: 0,
pitch: 30
};

const MAP_STYLE = 'https://basemaps.cartocdn.com/gl/positron-gl-style/style.json';
function DeckGLOverlay(props) {
const overlay = useControl(() => new DeckOverlay(props));
overlay.setProps(props);
return null;
}

function Root() {
const onClick = info => {
if (info.object) {
// eslint-disable-next-line
alert(`${info.object.properties.name} (${info.object.properties.abbrev})`);
}
};

const layers = [
new GeoJsonLayer({
id: 'airports',
data: AIR_PORTS,
// Styles
filled: true,
pointRadiusMinPixels: 2,
pointRadiusScale: 2000,
getPointRadius: f => 11 - f.properties.scalerank,
getFillColor: [200, 0, 80, 180],
// Interactive props
pickable: true,
autoHighlight: true,
onClick,
// beforeId: 'watername_ocean' // In interleaved mode, render the layer under map labels
}),
new ArcLayer({
id: 'arcs',
data: AIR_PORTS,
dataTransform: d => d.features.filter(f => f.properties.scalerank < 4),
// Styles
getSourcePosition: f => [-0.4531566, 51.4709959], // London
getTargetPosition: f => f.geometry.coordinates,
getSourceColor: [0, 128, 200],
getTargetColor: [200, 0, 80],
getWidth: 1
})
];

return (
<Map
initialViewState={INITIAL_VIEW_STATE}
mapStyle={MAP_STYLE}
>
<DeckGLOverlay layers={layers} /*interleaved*/ />
<NavigationControl position='top-left' />
</Map>
);
}

/* global document */
const container = document.body.appendChild(document.createElement('div'));
createRoot(container).render(<Root />);