Skip to content

Commit d60482d

Browse files
authored
Merge pull request #931 from mapbox/as/add-3d-buildings-toggle
Add 3d buildings toggle
2 parents 29963d3 + b7edffc commit d60482d

File tree

7 files changed

+128
-17
lines changed

7 files changed

+128
-17
lines changed

src/constants.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@ module.exports = {
33
DEFAULT_STYLE: 'Standard',
44
DEFAULT_DARK_FEATURE_COLOR: '#555',
55
DEFAULT_LIGHT_FEATURE_COLOR: '#e8e8e8',
6-
DEFAULT_SATELLITE_FEATURE_COLOR: '#00f900'
6+
DEFAULT_SATELLITE_FEATURE_COLOR: '#00f900',
7+
DEFAULT_3D_BUILDINGS: true
78
};

src/css/site.css

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,11 +105,17 @@ button {
105105

106106
.top button.active,
107107
.layer-switch button.active,
108-
.projection-switch button.active {
108+
.projection-switch button.active,
109+
.toggle-3D button.active {
109110
background: #34495e;
110111
color: #fff;
111112
}
112113

114+
.toggle-3D.hidden {
115+
opacity: 0;
116+
pointer-events: none;
117+
}
118+
113119
button.major {
114120
padding: 5px;
115121
border-radius: 3px;

src/ui.js

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ const buttons = require('./ui/mode_buttons'),
33
dnd = require('./ui/dnd'),
44
// userUi = require('./ui/user'),
55
layer_switch = require('./ui/layer_switch'),
6-
projection_switch = require('./ui/projection_switch');
6+
projection_switch = require('./ui/projection_switch'),
7+
toggle_3d = require('./ui/3d-buildings-toggle');
78

89
module.exports = ui;
910

@@ -24,7 +25,18 @@ function ui(context) {
2425
'map grow shrink-0 top-0 bottom-0 left-0 basis-0 transition-all duration-300'
2526
)
2627
.call(layer_switch(context))
27-
.call(projection_switch(context));
28+
.call(projection_switch(context))
29+
.call(toggle_3d(context));
30+
31+
// After context.map() is created and available, add the 3D toggle UI
32+
// setTimeout(() => {
33+
// const mapInstance = typeof context.map === 'function' ? context.map() : context.map;
34+
// if (mapInstance && typeof mapInstance.on === 'function') {
35+
// mapInstance.on('load', () => {
36+
// d3.select('#map').call(toggle_3d(context));
37+
// });
38+
// }
39+
// }, 0);
2840

2941
// sidebar handle
3042
map

src/ui/3d-buildings-toggle.js

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
module.exports = function (context) {
2+
return function (selection) {
3+
const Buildings3D = [
4+
{
5+
label: 'Show',
6+
value: true
7+
},
8+
{
9+
label: 'Hide',
10+
value: false
11+
}
12+
];
13+
14+
const container3D = selection
15+
.append('div')
16+
.attr(
17+
'class',
18+
'toggle-3D absolute left-0 bottom-0 mb-16 text-xs transition-all duration-200 z-10'
19+
);
20+
21+
container3D
22+
.append('span')
23+
.attr('class', 'bg-white p-[4px]')
24+
.text('3D Buildings');
25+
26+
const buttons3D = container3D.selectAll('button').data(Buildings3D);
27+
28+
const set3DBuildings = function () {
29+
const clicked = this instanceof d3.selection ? this.node() : this;
30+
31+
buttons3D.classed('active', function () {
32+
return clicked === this;
33+
});
34+
35+
if (context.map._loaded) {
36+
const { value } = d3.select(clicked).datum();
37+
context.map.setConfigProperty('basemap', 'show3dObjects', value);
38+
context.storage.set('3DBuildings', value);
39+
}
40+
};
41+
42+
buttons3D
43+
.enter()
44+
.append('button')
45+
.attr('class', 'pad0x')
46+
.on('click', set3DBuildings)
47+
.text((d) => {
48+
return d.label;
49+
});
50+
};
51+
};

src/ui/layer_switch.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,16 @@ module.exports = function (context) {
3232
context.data.set({
3333
mapStyleLoaded: true
3434
});
35+
36+
// Update toggle visibility based on new style
37+
setTimeout(() => {
38+
const toggle3D = d3.select('.toggle-3D');
39+
const shouldHide3DForStyle =
40+
title === 'OSM' ||
41+
title === 'Outdoors' ||
42+
title === 'Standard Satellite';
43+
toggle3D.classed('hidden', shouldHide3DForStyle);
44+
}, 100);
3545
}
3646
};
3747

src/ui/map/index.js

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ const {
1818
DEFAULT_PROJECTION,
1919
DEFAULT_DARK_FEATURE_COLOR,
2020
DEFAULT_LIGHT_FEATURE_COLOR,
21-
DEFAULT_SATELLITE_FEATURE_COLOR
21+
DEFAULT_SATELLITE_FEATURE_COLOR,
22+
DEFAULT_3D_BUILDINGS
2223
} = require('../../constants');
2324
const drawStyles = require('../draw/styles');
2425

@@ -362,21 +363,58 @@ module.exports = function (context, readonly) {
362363

363364
geojsonToLayer(context, writable);
364365

366+
// Initialize 3D buildings state from localStorage after style is loaded
367+
// This can't live in `ui/3d-buildings-toggle.js because we have to wait for the map style to be loaded
368+
const hasKey = context.storage.get('3DBuildings') !== undefined;
369+
const active3DBuildings = hasKey
370+
? context.storage.get('3DBuildings')
371+
: DEFAULT_3D_BUILDINGS;
372+
if (context.map.getConfigProperty) {
373+
context.map.setConfigProperty(
374+
'basemap',
375+
'show3dObjects',
376+
active3DBuildings
377+
);
378+
}
379+
// Update the UI to reflect the active state
380+
d3.selectAll('.toggle-3D button').classed('active', function () {
381+
const { value } = d3.select(this).datum();
382+
return value === active3DBuildings;
383+
});
384+
365385
context.data.set({
366386
mapStyleLoaded: false
367387
});
368388
}
369389
});
370390

371391
// only show projection toggle on zoom < 6
372-
context.map.on('zoomend', () => {
392+
// only show 3d Buildings toggle on Zoom > 14
393+
function updateTogglesByZoom() {
373394
const zoom = context.map.getZoom();
395+
const projectionSwitch = d3.select('.projection-switch');
396+
const toggle3D = d3.select('.toggle-3D');
397+
398+
// Get current style to check if 3D buildings should be hidden
399+
const currentStyle = context.storage.get('style') || DEFAULT_STYLE;
400+
const shouldHide3DForStyle =
401+
currentStyle === 'OSM' ||
402+
currentStyle === 'Outdoors' ||
403+
currentStyle === 'Standard Satellite';
404+
374405
if (zoom < 6) {
375-
d3.select('.projection-switch').style('opacity', 1);
406+
projectionSwitch.style('opacity', 1);
407+
toggle3D.classed('hidden', true);
408+
} else if (zoom > 6 && zoom < 14) {
409+
projectionSwitch.style('opacity', 0);
410+
toggle3D.classed('hidden', true);
376411
} else {
377-
d3.select('.projection-switch').style('opacity', 0);
412+
// Hide 3D toggle for OSM and Outdoors styles, regardless of zoom
413+
toggle3D.classed('hidden', shouldHide3DForStyle);
378414
}
379-
});
415+
}
416+
context.map.on('load', () => updateTogglesByZoom());
417+
context.map.on('zoomend', () => updateTogglesByZoom());
380418

381419
const maybeSetCursorToPointer = () => {
382420
if (context.Draw.getMode() === 'simple_select') {

src/ui/map/styles.js

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,7 @@
11
module.exports = [
22
{
33
title: 'Standard',
4-
style: 'mapbox://styles/mapbox/standard',
5-
config: {
6-
basemap: {
7-
show3dObjects: false
8-
}
9-
}
4+
style: 'mapbox://styles/mapbox/standard'
105
},
116
{
127
title: 'Standard Satellite',
@@ -17,7 +12,6 @@ module.exports = [
1712
style: 'mapbox://styles/mapbox/standard',
1813
config: {
1914
basemap: {
20-
show3dObjects: false,
2115
theme: 'monochrome'
2216
}
2317
}
@@ -27,7 +21,6 @@ module.exports = [
2721
style: 'mapbox://styles/mapbox/standard',
2822
config: {
2923
basemap: {
30-
show3dObjects: false,
3124
theme: 'monochrome',
3225
lightPreset: 'night'
3326
}

0 commit comments

Comments
 (0)