forked from peterqliu/threebox
-
Notifications
You must be signed in to change notification settings - Fork 150
/
08-3dbuildings.html
179 lines (150 loc) · 4.83 KB
/
08-3dbuildings.html
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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
<!doctype html>
<html>
<head>
<title>Threebox display buildings in 3D with auto tooltips</title>
<link href="https://api.mapbox.com/mapbox-gl-js/v2.2.0/mapbox-gl.css" rel="stylesheet">
<script src="https://api.mapbox.com/mapbox-gl-js/v2.2.0/mapbox-gl.js"></script>
<script src="../dist/threebox.js" type="text/javascript"></script>
<link href="../dist/threebox.css" rel="stylesheet" />
<script src="config.js"></script>
</head>
<body>
<div id='map' class='map'>
</div>
<script type="module">
if (!config) console.error("Config not set! Make a copy of 'config_template.js', add in your access token, and save the file as 'config.js'.");
mapboxgl.accessToken = config.accessToken;
//starting location for map
let popup;
let minZoom = 12;
let mapConfig = {
ALL: { center: [-73.985699, 40.750042, 0], zoom: 16.25, pitch: 45, bearing: 0 },
names: {
compositeSource: "composite",
compositeSourceLayer: "building",
compositeLayer: "3d-buildings"
}
}
var map = new mapboxgl.Map({
style: 'mapbox://styles/mapbox/outdoors-v11',
center: mapConfig.ALL.center,
zoom: mapConfig.ALL.zoom,
pitch: mapConfig.ALL.pitch,
bearing: mapConfig.ALL.bearing,
container: 'map',
antialias: true,
hash: true
});
// we can add Threebox to mapbox to add built-in mouseover/mouseout and click behaviors
window.tb = new Threebox(
map,
map.getCanvas().getContext('webgl'),
{
defaultLights: true,
enableSelectingFeatures: true, //change this to false to disable fill-extrusion features selection
enableTooltips: true // change this to false to disable default tooltips on fill-extrusion and 3D models
}
);
import { GUI } from 'https://threejs.org/examples/jsm/libs/dat.gui.module.js';
import Stats from 'https://threejs.org/examples/jsm/libs/stats.module.js';
let stats, gui;
function animate() {
requestAnimationFrame(animate);
stats.update();
}
let api = {
fov: Math.atan(3 / 4) * 180 / Math.PI
};
function init() {
// stats
stats = new Stats();
map.getContainer().appendChild(stats.dom);
animate();
// gui
gui = new GUI();
// going below 2.5 degrees will start to generate serious issues with polygons in fill-extrusions and 3D meshes
// going above 45 degrees will also produce clipping and performance issues
gui.add(api, 'fov', 2.5, 45.0).step(0.1).onChange(changeFOV);
}
function changeFOV() {
tb.fov = api.fov;
}
// The 'building' layer in the mapbox-streets vector source contains building-height
// data from OpenStreetMap.
map.on('style.load', function () {
init();
map.addLayer(createCompositeLayer());
//[jscastro] there is no need to add a layer if we are not adding 3D objects or models, we can subscribe to render to invoke update
map.on('render', function () {
tb.update();
})
//[jscastro] subscribe to selected/unselect extrusion feature event
map.on('SelectedFeatureChange', onSelectedFeatureChange);
});
function createCompositeLayer() {
let layer = {
'id': mapConfig.names.compositeLayer,
'source': mapConfig.names.compositeSource,
'source-layer': mapConfig.names.compositeSourceLayer,
'filter': ['==', 'extrude', 'true'],
'type': 'fill-extrusion',
'minzoom': minZoom,
'paint': {
'fill-extrusion-color':
[
'case',
['boolean', ['feature-state', 'select'], false],
"lightgreen",
['boolean', ['feature-state', 'hover'], false],
"lightblue",
'#aaa'
],
// use an 'interpolate' expression to add a smooth transition effect to the
// buildings as the user zooms in
'fill-extrusion-height': [
'interpolate',
['linear'],
['zoom'],
minZoom,
0,
minZoom + 0.05,
['get', 'height']
],
'fill-extrusion-base': [
'interpolate',
['linear'],
['zoom'],
minZoom,
0,
minZoom + 0.05,
['get', 'min_height']
],
'fill-extrusion-opacity': 0.9
}
};
return layer;
}
//[jscastro] handler for the feature selected UI... we will create a Mapbox popup to compare with Threebox popup
function onSelectedFeatureChange(e) {
let feature = e.detail;
if (feature && feature.state && feature.state.select) {
if (popup) popup.remove();
let center = [];
let coords = tb.getFeatureCenter(feature, null, 0);
center.push([coords[0], coords[1]]);
//TODO: this creates a Mapbox popup in the same coords the Threebox popup to see the difference
popup = new mapboxgl.Popup({ offset: 0 })
.setLngLat(center[0].slice())
.setHTML('<strong>' + (feature.id || feature.type) + '</strong >')
.addTo(map);
let geoJson = {
"geometry": feature.geometry,
"type": "Feature",
"properties": feature.properties
}
console.log(JSON.stringify(geoJson, null, 2))
}
}
</script>
</body>
</html>