-
Notifications
You must be signed in to change notification settings - Fork 2.1k
/
app.jsx
126 lines (109 loc) · 2.98 KB
/
app.jsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/* global fetch */
import React, {useState, useMemo} from 'react';
import {createRoot} from 'react-dom/client';
import {Map} from 'react-map-gl/maplibre';
import DeckGL from '@deck.gl/react';
import {GeoJsonLayer, ArcLayer} from '@deck.gl/layers';
import {scaleQuantile} from 'd3-scale';
// Source data GeoJSON
const DATA_URL =
'https://raw.githubusercontent.com/visgl/deck.gl-data/master/examples/arc/counties.json'; // eslint-disable-line
export const inFlowColors = [
[255, 255, 204],
[199, 233, 180],
[127, 205, 187],
[65, 182, 196],
[29, 145, 192],
[34, 94, 168],
[12, 44, 132]
];
export const outFlowColors = [
[255, 255, 178],
[254, 217, 118],
[254, 178, 76],
[253, 141, 60],
[252, 78, 42],
[227, 26, 28],
[177, 0, 38]
];
const INITIAL_VIEW_STATE = {
longitude: -100,
latitude: 40.7,
zoom: 3,
maxZoom: 15,
pitch: 30,
bearing: 30
};
const MAP_STYLE = 'https://basemaps.cartocdn.com/gl/positron-nolabels-gl-style/style.json';
function calculateArcs(data, selectedCounty) {
if (!data || !data.length) {
return null;
}
if (!selectedCounty) {
selectedCounty = data.find(f => f.properties.name === 'Los Angeles, CA');
}
const {flows, centroid} = selectedCounty.properties;
const arcs = Object.keys(flows).map(toId => {
const f = data[toId];
return {
source: centroid,
target: f.properties.centroid,
value: flows[toId]
};
});
const scale = scaleQuantile()
.domain(arcs.map(a => Math.abs(a.value)))
.range(inFlowColors.map((c, i) => i));
arcs.forEach(a => {
a.gain = Math.sign(a.value);
a.quantile = scale(Math.abs(a.value));
});
return arcs;
}
function getTooltip({object}) {
return object && object.properties.name;
}
/* eslint-disable react/no-deprecated */
export default function App({data, strokeWidth = 1, mapStyle = MAP_STYLE}) {
const [selectedCounty, selectCounty] = useState(null);
const arcs = useMemo(() => calculateArcs(data, selectedCounty), [data, selectedCounty]);
const layers = [
new GeoJsonLayer({
id: 'geojson',
data,
stroked: false,
filled: true,
getFillColor: [0, 0, 0, 0],
onClick: ({object}) => selectCounty(object),
pickable: true
}),
new ArcLayer({
id: 'arc',
data: arcs,
getSourcePosition: d => d.source,
getTargetPosition: d => d.target,
getSourceColor: d => (d.gain > 0 ? inFlowColors : outFlowColors)[d.quantile],
getTargetColor: d => (d.gain > 0 ? outFlowColors : inFlowColors)[d.quantile],
getWidth: strokeWidth
})
];
return (
<DeckGL
layers={layers}
initialViewState={INITIAL_VIEW_STATE}
controller={true}
getTooltip={getTooltip}
>
<Map reuseMaps mapStyle={mapStyle} />
</DeckGL>
);
}
export function renderToDOM(container) {
const root = createRoot(container);
root.render(<App />);
fetch(DATA_URL)
.then(response => response.json())
.then(({features}) => {
root.render(<App data={features} />);
});
}