-
Notifications
You must be signed in to change notification settings - Fork 2.1k
/
Copy pathapp.tsx
143 lines (128 loc) · 3.49 KB
/
app.tsx
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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
// deck.gl
// SPDX-License-Identifier: MIT
// Copyright (c) vis.gl contributors
import React, {useState} from 'react';
import {createRoot} from 'react-dom/client';
import {Map} from 'react-map-gl/maplibre';
import DeckGL from '@deck.gl/react';
import {GeoJsonLayer, PolygonLayer} from '@deck.gl/layers';
import {LightingEffect, AmbientLight, _SunLight as SunLight} from '@deck.gl/core';
import {scaleThreshold} from 'd3-scale';
import type {Color, Position, PickingInfo, MapViewState} from '@deck.gl/core';
import type {Feature, Geometry} from 'geojson';
// Source data GeoJSON
const DATA_URL =
'https://raw.githubusercontent.com/visgl/deck.gl-data/master/examples/geojson/vancouver-blocks.json'; // eslint-disable-line
export const COLOR_SCALE = scaleThreshold<number, Color>()
.domain([-0.6, -0.45, -0.3, -0.15, 0, 0.15, 0.3, 0.45, 0.6, 0.75, 0.9, 1.05, 1.2])
.range([
[65, 182, 196],
[127, 205, 187],
[199, 233, 180],
[237, 248, 177],
// zero
[255, 255, 204],
[255, 237, 160],
[254, 217, 118],
[254, 178, 76],
[253, 141, 60],
[252, 78, 42],
[227, 26, 28],
[189, 0, 38],
[128, 0, 38]
]);
const INITIAL_VIEW_STATE: MapViewState = {
latitude: 49.254,
longitude: -123.13,
zoom: 11,
maxZoom: 16,
pitch: 45,
bearing: 0
};
const MAP_STYLE = 'https://basemaps.cartocdn.com/gl/positron-nolabels-gl-style/style.json';
const ambientLight = new AmbientLight({
color: [255, 255, 255],
intensity: 1.0
});
const dirLight = new SunLight({
timestamp: Date.UTC(2019, 7, 1, 22),
color: [255, 255, 255],
intensity: 1.0,
_shadow: true
});
const landCover: Position[][] = [
[
[-123.0, 49.196],
[-123.0, 49.324],
[-123.306, 49.324],
[-123.306, 49.196]
]
];
type BlockProperties = {
valuePerParcel: number;
valuePerSqm: number;
growth: number;
};
function getTooltip({object}: PickingInfo<Feature<Geometry, BlockProperties>>) {
return (
object && {
html: `\
<div><b>Average Property Value</b></div>
<div>${object.properties.valuePerParcel} / parcel</div>
<div>${object.properties.valuePerSqm} / m<sup>2</sup></div>
<div><b>Growth</b></div>
<div>${Math.round(object.properties.growth * 100)}%</div>
`
}
);
}
export default function App({
data = DATA_URL,
mapStyle = MAP_STYLE
}: {
data?: string | Feature<Geometry, BlockProperties>[];
mapStyle?: string;
}) {
const [effects] = useState(() => {
const lightingEffect = new LightingEffect({ambientLight, dirLight});
lightingEffect.shadowColor = [0, 0, 0, 0.5];
return [lightingEffect];
});
const layers = [
// only needed when using shadows - a plane for shadows to drop on
new PolygonLayer<Position[]>({
id: 'ground',
data: landCover,
stroked: false,
getPolygon: f => f,
getFillColor: [0, 0, 0, 0]
}),
new GeoJsonLayer<BlockProperties>({
id: 'geojson',
data,
opacity: 0.8,
stroked: false,
filled: true,
extruded: true,
wireframe: true,
getElevation: f => Math.sqrt(f.properties.valuePerSqm) * 10,
getFillColor: f => COLOR_SCALE(f.properties.growth),
getLineColor: [255, 255, 255],
pickable: true
})
];
return (
<DeckGL
layers={layers}
effects={effects}
initialViewState={INITIAL_VIEW_STATE}
controller={true}
getTooltip={getTooltip}
>
<Map reuseMaps mapStyle={mapStyle} />
</DeckGL>
);
}
export function renderToDOM(container: HTMLDivElement) {
createRoot(container).render(<App />);
}