Skip to content

Commit b5b2c83

Browse files
committed
feat: Add menu to select basemap
1 parent ea68978 commit b5b2c83

File tree

5 files changed

+60
-42
lines changed

5 files changed

+60
-42
lines changed

web/src/components/ControlsBar.vue

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,25 @@ function takeScreenshot(save: boolean) {
6464
</script>
6565

6666
<template>
67-
<div id="controls-bar" :class="appStore.openSidebars.includes('left') ? 'controls-bar shifted' : 'controls-bar'
68-
">
69-
<v-btn color="primary" class="control-btn" @click="mapStore.toggleBaseLayer" variant="flat">
70-
<v-icon icon="mdi-layers" v-tooltip="'Toggle Base Layer'"></v-icon>
67+
<div id="controls-bar" :class="appStore.openSidebars.includes('left') ? 'controls-bar shifted' : 'controls-bar'">
68+
<v-btn color="primary" class="control-btn" variant="flat">
69+
<v-icon>mdi-map-outline</v-icon>
70+
<v-menu activator="parent" :close-on-content-click="false" open-on-hover>
71+
<v-card style="max-height: 400px; overflow-y: auto;">
72+
<v-list :selected="[mapStore.currentBasemap]"
73+
@update:selected="(selected) => mapStore.currentBasemap = selected[0]" class="basemap-list"
74+
density="compact" mandatory>
75+
<v-list-subheader>Base Map Options</v-list-subheader>
76+
<v-list-item v-for="basemap in mapStore.availableBasemaps" :key="basemap.id" :value="basemap" class="px-2">
77+
{{ basemap.name }}
78+
<template v-slot:prepend>
79+
<v-icon :icon="basemap.id === mapStore.currentBasemap?.id ? 'mdi-check' : 'none'" color="success"
80+
class="pa-0"></v-icon>
81+
</template>
82+
</v-list-item>
83+
</v-list>
84+
</v-card>
85+
</v-menu>
7186
</v-btn>
7287
<v-btn class="control-btn" @click="fitMap" variant="flat">
7388
<v-progress-circular v-if="loadingBounds" indeterminate />
@@ -161,4 +176,8 @@ function takeScreenshot(save: boolean) {
161176
justify-content: space-between;
162177
margin-bottom: 5px;
163178
}
179+
180+
.basemap-list .v-list-item__prepend>.v-icon~.v-list-item__spacer {
181+
width: 5px;
182+
}
164183
</style>

web/src/components/map/Map.vue

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,11 @@ function createMap() {
6060
preserveDrawingBuffer: true, // allows screenshots
6161
// transformRequest adds auth headers to tile requests
6262
transformRequest: (url) => {
63-
return {
64-
url,
65-
headers: oauthClient?.authHeaders,
66-
};
63+
let headers = {}
64+
if (url.includes(import.meta.env.VITE_APP_API_ROOT)) {
65+
headers = oauthClient?.authHeaders
66+
}
67+
return { url, headers };
6768
},
6869
style: THEMES[appStore.theme].mapStyle,
6970
center: [0, 0],
@@ -127,19 +128,21 @@ onMounted(() => {
127128
128129
watch(() => mapStore.currentBasemap, () => {
129130
if (mapStore.map && mapStore.currentBasemap) {
130-
const map = mapStore.getMap();
131-
map.setStyle(mapStore.currentBasemap.style);
131+
const visible = mapStore.currentBasemap.id !== undefined
132+
mapStore.setBasemapVisibility(visible);
133+
if (visible) {
134+
const map = mapStore.getMap();
135+
map.setStyle(mapStore.currentBasemap.style);
136+
map.once('idle', () => {
137+
layerStore.updateLayersShown();
138+
});
139+
}
132140
}
133141
})
134142
135143
watch(() => appStore.theme, () => {
136-
const map = mapStore.getMap();
137-
map.once('idle', () => {
138-
layerStore.updateLayersShown();
139-
});
140144
mapStore.setBasemapToDefault();
141145
setAttributionControlStyle();
142-
layerStore.updateLayersShown();
143146
});
144147
145148
watch(() => appStore.openSidebars, () => {

web/src/store/map.ts

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,6 @@ export const useMapStore = defineStore('map', () => {
128128
const map = shallowRef<Map>();
129129
const availableBasemaps = ref<Basemap[]>([]);
130130
const currentBasemap = ref<Basemap>();
131-
const showMapBaseLayer = ref(true);
132131
const tooltipOverlay = ref<Popup>();
133132
const clickedFeature = ref<ClickedFeatureData>();
134133
const rasterTooltipDataCache = ref<Record<number, RasterDataValues | undefined>>({});
@@ -139,7 +138,10 @@ export const useMapStore = defineStore('map', () => {
139138
const appStore = useAppStore();
140139

141140
async function fetchAvailableBasemaps() {
142-
availableBasemaps.value = await getBasemaps();
141+
availableBasemaps.value = [
142+
{name: 'None'},
143+
...await getBasemaps()
144+
];
143145
setBasemapToDefault();
144146
}
145147

@@ -151,6 +153,21 @@ export const useMapStore = defineStore('map', () => {
151153
}
152154
}
153155

156+
function setBasemapVisibility(visible: boolean) {
157+
const map = getMap();
158+
const baseLayerSourceIds = getBaseLayerSourceIds();
159+
map.getLayersOrder().forEach((id) => {
160+
const layer = map.getLayer(id);
161+
if (layer && baseLayerSourceIds.includes(layer.source)) {
162+
map.setLayoutProperty(
163+
id,
164+
"visibility",
165+
visible ? "visible" : "none"
166+
);
167+
}
168+
});
169+
}
170+
154171
function handleLayerClick(e: MapLayerMouseEvent) {
155172
const map = getMap();
156173
const clickedFeatures = map.queryRenderedFeatures(e.point).filter(
@@ -182,26 +199,6 @@ export const useMapStore = defineStore('map', () => {
182199
}
183200
}
184201

185-
// Update the base layer visibility
186-
watch(showMapBaseLayer, () => {
187-
const map = getMap();
188-
const baseLayerSourceIds = getBaseLayerSourceIds();
189-
map.getLayersOrder().forEach((id) => {
190-
const layer = map.getLayer(id);
191-
if (layer && baseLayerSourceIds.includes(layer.source)) {
192-
map.setLayoutProperty(
193-
id,
194-
"visibility",
195-
showMapBaseLayer.value ? "visible" : "none"
196-
);
197-
}
198-
});
199-
});
200-
201-
function toggleBaseLayer() {
202-
showMapBaseLayer.value = !showMapBaseLayer.value;
203-
}
204-
205202
function getMap() {
206203
if (map.value === undefined) {
207204
throw new Error("Map not yet initialized!");
@@ -509,16 +506,15 @@ export const useMapStore = defineStore('map', () => {
509506
map,
510507
availableBasemaps,
511508
currentBasemap,
512-
showMapBaseLayer,
513509
tooltipOverlay,
514510
clickedFeature,
515511
rasterTooltipDataCache,
516512
rasterSourceTileURLs,
517513
// Functions
518514
fetchAvailableBasemaps,
519515
setBasemapToDefault,
516+
setBasemapVisibility,
520517
handleLayerClick,
521-
toggleBaseLayer,
522518
getMap,
523519
getMapSources,
524520
getCurrentMapPosition,

web/src/store/project.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ export const useProjectStore = defineStore('project', () => {
6666

6767
function clearState() {
6868
clearProjectState();
69-
mapStore.showMapBaseLayer = true;
69+
mapStore.setBasemapToDefault();
7070
appStore.currentError = undefined;
7171

7272
panelStore.resetPanels();

web/src/types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ export interface User {
1010
}
1111

1212
export interface Basemap {
13-
id: number;
13+
id?: number;
1414
name: string;
15-
style: any;
15+
style?: any;
1616
}
1717

1818
export interface Dataset {

0 commit comments

Comments
 (0)