Skip to content

Commit ee65ba9

Browse files
aleksprogergithub-actions[bot]
authored andcommitted
Add back buildings toggle to indoor control (internal-10233)
GitOrigin-RevId: 4bb5f09daa7fd34071945b6fcbd9dff51cf55913
1 parent de053a3 commit ee65ba9

6 files changed

Lines changed: 323 additions & 66 deletions

File tree

debug/indoor/indoor_style.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ const indoorLayers = [{
1414
"source": "indoor-source",
1515
"source-layer": "indoor_structure",
1616
"minzoom": 15.0,
17-
"filter": isSelectedFloorBase(),
17+
"filter": ["is-active-floor"],
1818
"layout": {
1919
"clip-layer-types": ["model", "symbol"]
2020
}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@
196196
]
197197
},
198198
{
199-
"limit": "5.41 kb",
199+
"limit": "5.54 kb",
200200
"gzip": true,
201201
"path": "dist/mapbox-gl.css"
202202
}

src/css/mapbox-gl.css

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,23 @@
258258
background-size: 18px 18px;
259259
}
260260

261+
.mapboxgl-ctrl button.mapboxgl-ctrl-indoor-toggle .mapboxgl-ctrl-icon {
262+
background-image: svg-load("svg/mapboxgl-ctrl-buidling.svg", fill: #333);
263+
background-size: 18px 18px;
264+
}
265+
266+
@media (-ms-high-contrast: active) {
267+
.mapboxgl-ctrl button.mapboxgl-ctrl-indoor-toggle .mapboxgl-ctrl-icon {
268+
background-image: svg-load("svg/mapboxgl-ctrl-buidling.svg", fill: #fff);
269+
}
270+
}
271+
272+
@media (-ms-high-contrast: black-on-white) {
273+
.mapboxgl-ctrl button.mapboxgl-ctrl-indoor-toggle .mapboxgl-ctrl-icon {
274+
background-image: svg-load("svg/mapboxgl-ctrl-buidling.svg", fill: #000);
275+
}
276+
}
277+
261278

262279
@svg-load ctrl-geolocate url("svg/mapboxgl-ctrl-geolocate.svg") {
263280
fill: #333;
Lines changed: 3 additions & 0 deletions
Loading

src/ui/control/indoor_control.ts

Lines changed: 137 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,12 @@ class IndoorControl implements IControl {
2020
_container: HTMLElement | null;
2121
_model: IndoorControlModel | null;
2222
_visibleFloorStart: number;
23+
_lastSelectedFloorId: string | null;
2324

2425
constructor() {
25-
bindAll(['_onIndoorUpdate', '_onStyleData', '_scrollUp', '_scrollDown'], this);
26+
bindAll(['_onIndoorUpdate', '_onStyleData', '_scrollUp', '_scrollDown', '_toggleIndoor'], this);
2627
this._visibleFloorStart = 0;
28+
this._lastSelectedFloorId = null;
2729
}
2830
onAdd(map: Map): HTMLElement {
2931
this._map = map;
@@ -70,7 +72,7 @@ class IndoorControl implements IControl {
7072
return 'top-right';
7173
}
7274
_onIndoorUpdate(model: IndoorControlModel | null) {
73-
if (!model || !model.floors) {
75+
if (!model || !model.floors || model.floors.length === 0) {
7476
this._model = model;
7577
this._container.style.display = 'none';
7678
return;
@@ -83,17 +85,45 @@ class IndoorControl implements IControl {
8385

8486
if (floorsChanged) {
8587
this._visibleFloorStart = 0;
88+
this._lastSelectedFloorId = null;
8689
}
8790

8891
if (model.selectedFloorId) {
89-
const selectedIndex = model.floors.findIndex(f => f.id === model.selectedFloorId);
90-
if (selectedIndex !== -1) {
91-
if (selectedIndex < this._visibleFloorStart) {
92-
this._visibleFloorStart = selectedIndex;
93-
} else if (selectedIndex >= this._visibleFloorStart + VISIBLE_FLOORS) {
94-
this._visibleFloorStart = selectedIndex - (VISIBLE_FLOORS - 1);
92+
const selectionChanged = model.selectedFloorId !== this._lastSelectedFloorId;
93+
94+
if (selectionChanged || floorsChanged) {
95+
const selectedIndex = model.floors.findIndex(f => f.id === model.selectedFloorId);
96+
if (selectedIndex !== -1) {
97+
const totalFloors = model.floors.length;
98+
let minVisible, maxVisible;
99+
100+
if (totalFloors <= VISIBLE_FLOORS + 2) {
101+
minVisible = 0;
102+
maxVisible = totalFloors - 1;
103+
} else {
104+
const isAtTop = this._visibleFloorStart === 0;
105+
const isAtBottom = this._visibleFloorStart >= totalFloors - VISIBLE_FLOORS;
106+
107+
if (isAtTop) {
108+
minVisible = 0;
109+
maxVisible = VISIBLE_FLOORS;
110+
} else if (isAtBottom) {
111+
minVisible = totalFloors - VISIBLE_FLOORS - 1;
112+
maxVisible = totalFloors - 1;
113+
} else {
114+
minVisible = this._visibleFloorStart;
115+
maxVisible = this._visibleFloorStart + VISIBLE_FLOORS - 1;
116+
}
117+
}
118+
119+
if (selectedIndex < minVisible) {
120+
this._visibleFloorStart = selectedIndex;
121+
} else if (selectedIndex > maxVisible) {
122+
this._visibleFloorStart = selectedIndex - (VISIBLE_FLOORS - 1);
123+
}
95124
}
96125
}
126+
this._lastSelectedFloorId = model.selectedFloorId;
97127
}
98128

99129
this._render();
@@ -103,58 +133,129 @@ class IndoorControl implements IControl {
103133
if (!this._container || !this._model || !this._model.floors) return;
104134

105135
this._container.innerHTML = '';
136+
137+
// Add Toggle Button
138+
const toggleButton = this._createButton('mapboxgl-ctrl-indoor-toggle', this._toggleIndoor);
139+
const toggleIcon = DOM.create('span', 'mapboxgl-ctrl-icon', toggleButton);
140+
toggleIcon.setAttribute('aria-hidden', 'true');
141+
142+
if (!this._model.activeFloorsVisible) {
143+
toggleButton.classList.add('mapboxgl-ctrl-level-button-selected');
144+
}
145+
this._container.appendChild(toggleButton);
146+
106147
const floors = this._model.floors;
107148
const totalFloors = floors.length;
108149

109-
if (totalFloors > VISIBLE_FLOORS) {
150+
// If we can fit all floors in the space of (Arrow + 3 Floors + Arrow = 5 slots), do it.
151+
if (totalFloors <= VISIBLE_FLOORS + 2) {
152+
floors.forEach(floor => this._createFloorButton(floor));
153+
return;
154+
}
155+
156+
const isAtTop = this._visibleFloorStart === 0;
157+
const isAtBottom = this._visibleFloorStart >= totalFloors - VISIBLE_FLOORS;
158+
159+
// Top Button
160+
if (isAtTop) {
161+
this._createFloorButton(floors[0]);
162+
} else {
110163
const upButton = this._createButton('mapboxgl-ctrl-arrow-up', this._scrollUp);
111-
if (this._visibleFloorStart === 0) {
112-
upButton.disabled = true;
113-
}
114164
DOM.create('span', 'mapboxgl-ctrl-icon', upButton).setAttribute('aria-hidden', 'true');
115165
this._container.appendChild(upButton);
116166
}
117167

118-
const visibleFloors = floors.slice(this._visibleFloorStart, this._visibleFloorStart + VISIBLE_FLOORS);
119-
visibleFloors.forEach(floor => {
120-
const levelButton = this._createButton('mapboxgl-ctrl-level-button', () => {
121-
if (this._model && this._model.selectedFloorId === floor.id) return;
122-
if (this._map) {
123-
this._map._selectIndoorFloor(floor.id);
168+
// Middle Floors
169+
let middleFloors: {id: string; name: string; zIndex: number}[] = [];
170+
if (isAtTop) {
171+
middleFloors = floors.slice(1, 1 + VISIBLE_FLOORS);
172+
} else if (isAtBottom) {
173+
middleFloors = floors.slice(this._visibleFloorStart - 1, this._visibleFloorStart + VISIBLE_FLOORS - 1);
174+
} else {
175+
middleFloors = floors.slice(this._visibleFloorStart, this._visibleFloorStart + VISIBLE_FLOORS);
176+
}
177+
178+
middleFloors.forEach(floor => this._createFloorButton(floor));
179+
180+
// Bottom Button
181+
if (isAtBottom) {
182+
this._createFloorButton(floors[totalFloors - 1]);
183+
} else {
184+
const downButton = this._createButton('mapboxgl-ctrl-arrow-down', this._scrollDown);
185+
DOM.create('span', 'mapboxgl-ctrl-icon', downButton).setAttribute('aria-hidden', 'true');
186+
this._container.appendChild(downButton);
187+
}
188+
}
189+
190+
_createFloorButton(floor: {id: string; name: string; zIndex: number}) {
191+
const levelButton = this._createButton('mapboxgl-ctrl-level-button', () => {
192+
const floorId = floor.id;
193+
// If the floor is already selected, do nothing.
194+
if (this._model && this._model.selectedFloorId === floorId && this._model.activeFloorsVisible) return;
195+
196+
if (this._map) {
197+
if (this._model && !this._model.activeFloorsVisible && this._map.style && this._map.style.indoorManager) {
198+
this._map.style.indoorManager.setActiveFloorsVisibility(true);
124199
}
125-
});
126-
const floorName = (floor.name || '').trim();
127-
const zIndexText = floor.zIndex.toString();
128-
const buttonTitle = floorName ? Array.from(floorName).slice(0, 3).join('') : zIndexText;
129-
this._setButtonTitle(levelButton, buttonTitle);
130-
131-
if (this._model && floor.id === this._model.selectedFloorId) {
132-
levelButton.classList.add('mapboxgl-ctrl-level-button-selected');
200+
this._map._selectIndoorFloor(floorId);
133201
}
134-
this._container.appendChild(levelButton);
135202
});
203+
const floorName = (floor.name || '').trim();
204+
const zIndexText = floor.zIndex.toString();
205+
const buttonTitle = floorName ? Array.from(floorName).slice(0, 3).join('') : zIndexText;
206+
this._setButtonTitle(levelButton, buttonTitle);
136207

137-
if (totalFloors > VISIBLE_FLOORS) {
138-
const downButton = this._createButton('mapboxgl-ctrl-arrow-down', this._scrollDown);
139-
if (this._visibleFloorStart + VISIBLE_FLOORS >= totalFloors) {
140-
downButton.disabled = true;
208+
if (this._model && this._model.activeFloorsVisible && floor.id === this._model.selectedFloorId) {
209+
levelButton.classList.add('mapboxgl-ctrl-level-button-selected');
210+
}
211+
if (this._container) {
212+
this._container.appendChild(levelButton);
213+
}
214+
}
215+
216+
_toggleIndoor() {
217+
if (this._map && this._map.style && this._map.style.indoorManager && this._model) {
218+
if (this._model.activeFloorsVisible) {
219+
this._map.style.indoorManager.setActiveFloorsVisibility(false);
141220
}
142-
DOM.create('span', 'mapboxgl-ctrl-icon', downButton).setAttribute('aria-hidden', 'true');
143-
this._container.appendChild(downButton);
144221
}
145222
}
146223

147224
_scrollUp() {
148225
if (this._visibleFloorStart > 0) {
149226
this._visibleFloorStart--;
227+
if (this._visibleFloorStart === 1) {
228+
this._visibleFloorStart = 0;
229+
}
230+
const floors = (this._model && this._model.floors) || [];
231+
if (floors.length > VISIBLE_FLOORS) {
232+
const maxStart = floors.length - VISIBLE_FLOORS;
233+
if (this._visibleFloorStart === maxStart - 1) {
234+
this._visibleFloorStart = maxStart - 2;
235+
}
236+
}
150237
this._render();
151238
}
152239
}
153240

154241
_scrollDown() {
155-
if (this._model && this._model.floors && this._visibleFloorStart + VISIBLE_FLOORS < this._model.floors.length) {
156-
this._visibleFloorStart++;
157-
this._render();
242+
if (this._model && this._model.floors) {
243+
const maxStart = this._model.floors.length - VISIBLE_FLOORS;
244+
if (this._visibleFloorStart < maxStart) {
245+
this._visibleFloorStart++;
246+
if (this._visibleFloorStart === 1) {
247+
this._visibleFloorStart = 2;
248+
}
249+
if (this._visibleFloorStart === maxStart - 1) {
250+
this._visibleFloorStart = maxStart;
251+
}
252+
253+
if (this._visibleFloorStart > maxStart) {
254+
this._visibleFloorStart = maxStart;
255+
}
256+
257+
this._render();
258+
}
158259
}
159260
}
160261
}

0 commit comments

Comments
 (0)