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) Use MapboxOverlay in mapbox (formerly safegraph) website example #8558

Merged
merged 8 commits into from
Mar 6, 2024
Merged
File renamed without changes.
150 changes: 150 additions & 0 deletions examples/website/mapbox/app.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
import React, {useCallback, useState, useRef, useMemo} from 'react';
import {createRoot} from 'react-dom/client';
import {MapboxOverlay} from '@deck.gl/mapbox';
import {ArcLayer} from '@deck.gl/layers';
import {H3HexagonLayer} from '@deck.gl/geo-layers';
import {scaleLog} from 'd3-scale';
import {cellToLatLng} from 'h3-js';
import {load} from '@loaders.gl/core';
import {CSVLoader} from '@loaders.gl/csv';
import {Map, NavigationControl, useControl, Layer} from 'react-map-gl';
import 'mapbox-gl/dist/mapbox-gl.css';

const DATA_URL =
'https://raw.githubusercontent.com/visgl/deck.gl-data/master/examples/safegraph/sf-pois.csv';

// Set your mapbox token here
const MAPBOX_TOKEN = process.env.MapboxAccessToken; // eslint-disable-line

const colorScale = scaleLog()
.domain([10, 100, 1000, 10000])
.range([
[255, 255, 178],
[254, 204, 92],
[253, 141, 60],
[227, 26, 28]
]);

const buildings3DLayer = {
id: '3d-buildings',
source: 'composite',
'source-layer': 'building',
filter: ['==', 'extrude', 'true'],
type: 'fill-extrusion',
minzoom: 14,
paint: {
'fill-extrusion-color': '#ccc',
'fill-extrusion-height': ['get', 'height']
}
};

function DeckGLOverlay(props) {
const overlay = useControl(() => new MapboxOverlay(props));
overlay.setProps(props);
return null;
}

export default function App({data}) {
const [selectedPOI, setSelectedPOI] = useState('8a283082aa17fff');
const [firstLabelLayerId, setFirstLabelLayerId] = useState();
const mapRef = useRef();

const onMapLoad = useCallback(() => {
setFirstLabelLayerId(getFirstLabelLayerId(mapRef.current.getStyle()));
}, []);

const selectedPOICentroid = useMemo(() => {
const [lat, lng] = cellToLatLng(selectedPOI);
return [lng, lat];
}, [selectedPOI]);

const arcs = useMemo(() => filterArcs(data, selectedPOI), [data, selectedPOI]);

const hexes = useMemo(() => aggregateHexes(data), [data]);

const arcLayer = new ArcLayer({
id: 'deckgl-connections',
data: arcs,
getSourcePosition: d => selectedPOICentroid,
getTargetPosition: d => [d.home_lng, d.home_lat],
getSourceColor: [255, 0, 128],
getTargetColor: [0, 200, 255],
getWidth: d => Math.max(2, d.count / 15)
});

const poiLayer = new H3HexagonLayer({
id: 'deckgl-pois',
data: hexes,
opacity: 0.4,
pickable: true,
autoHighlight: true,
onClick: ({object}) => object && setSelectedPOI(object.hex),
getHexagon: d => d.hex,
getFillColor: d => colorScale(d.count),
extruded: false,
stroked: false,
beforeId: firstLabelLayerId
});

return (
<Map
ref={mapRef}
mapboxAccessToken={MAPBOX_TOKEN}
mapStyle="mapbox://styles/mapbox/light-v9"
antialias={true}
initialViewState={{
longitude: -122.4034,
latitude: 37.7845,
zoom: 15.5,
bearing: 20,
pitch: 60
}}
onLoad={onMapLoad}
>
<DeckGLOverlay interleaved={true} layers={[poiLayer, arcLayer]} />
<NavigationControl />
<Layer {...buildings3DLayer} />
</Map>
);
}

function filterArcs(data, selectedPOI) {
if (!data) {
return null;
}
return data.filter(d => d.hex === selectedPOI);
}

function aggregateHexes(data) {
if (!data) {
return null;
}
const result = {};
for (const object of data) {
if (!result[object.hex]) {
result[object.hex] = {hex: object.hex, count: 0};
}
result[object.hex].count += object.count;
}
return Object.values(result);
}

function getFirstLabelLayerId(style) {
const layers = style.layers;
// Find the index of the first symbol (i.e. label) layer in the map style
for (let i = 0; i < layers.length; i++) {
if (layers[i].type === 'symbol') {
return layers[i].id;
}
}
return undefined;
}

export function renderToDOM(container) {
const root = createRoot(container);
root.render(<App />);

load(DATA_URL, CSVLoader).then(data => {
root.render(<App data={data.data} />);
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
<head>
<meta charset='UTF-8' />
<title>mapbox-custom-layer-example</title>
<link href="https://api.mapbox.com/mapbox-gl-js/v1.13.0/mapbox-gl.css" rel="stylesheet" />
<style>
body {
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
Expand All @@ -23,7 +22,7 @@
<div id="app"></div>
</body>
<script type="module">
import {loadAndRender} from './app.js';
loadAndRender(document.getElementById('app'));
import {renderToDOM} from './app.jsx';
renderToDOM(document.getElementById('app'));
</script>
</html>
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,11 @@
"dependencies": {
"@loaders.gl/csv": "^4.1.0",
"d3-scale": "^2.0.0",
"deck.gl": "^9.0.0-alpha",
"mapbox-gl": "^2.0.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"
},
"devDependencies": {
"typescript": "^4.6.0",
Expand Down
135 changes: 0 additions & 135 deletions examples/website/safegraph/app.js

This file was deleted.

4 changes: 2 additions & 2 deletions website/src/examples/mapbox.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import React, {Component, createRef} from 'react';
import {DATA_URI, GITHUB_TREE} from '../constants/defaults';
import {renderToDOM} from 'website-examples/safegraph/app';
import {renderToDOM} from 'website-examples/mapbox/app';

import {makeExample} from '../components';

class MapboxDemo extends Component {
static title = 'Who Is Visiting San Francisco?';

static code = `${GITHUB_TREE}/examples/website/safegraph`;
static code = `${GITHUB_TREE}/examples/website/mapbox`;

static data = {
url: `${DATA_URI}/safegraph.txt`,
Expand Down