Skip to content

Commit 12301ea

Browse files
authored
Add opacity slider (#259)
1 parent 820937a commit 12301ea

5 files changed

Lines changed: 35 additions & 54 deletions

File tree

src/components/GlobalDataPanel.vue

Lines changed: 10 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
<script setup lang="ts">
2-
import { computed, onUnmounted, ref, watch } from 'vue'
3-
import useSettings, { GLOBAL_DATA_MAP_FIELD_START_ZOOM_LEVEL } from '../composables/useSettings'
2+
import useSettings from '../composables/useSettings'
43
import useMap from '../composables/useMap'
54
import useAreaOfInterest from '../composables/useAreaOfInterest'
65
import type { PlaceResult } from '../composables/useAreaOfInterest'
@@ -14,34 +13,6 @@ const { map } = useMap()
1413
const { fitToExtent } = useAreaOfInterest()
1514
const { showError } = useNotifier()
1615
17-
const zoom = ref(0)
18-
const onZoomChange = () => {
19-
zoom.value = map.value?.getView()?.getZoom() ?? 0
20-
}
21-
22-
// Watch map and attach zoom listener when map becomes available
23-
watch(
24-
map,
25-
(newMap, oldMap) => {
26-
// Clean up previous listener
27-
if (oldMap) {
28-
oldMap.getView()?.un('change:resolution', onZoomChange)
29-
}
30-
31-
// Attach new listener if map is available
32-
if (newMap) {
33-
onZoomChange()
34-
newMap.getView().on('change:resolution', onZoomChange)
35-
}
36-
},
37-
{ immediate: true },
38-
)
39-
40-
onUnmounted(() => {
41-
map.value?.getView()?.un('change:resolution', onZoomChange)
42-
})
43-
const fieldBoundariesDisabled = computed(() => zoom.value < GLOBAL_DATA_MAP_FIELD_START_ZOOM_LEVEL)
44-
4516
const handleLocationSelected = (place: PlaceResult) => {
4617
if (!map.value) return
4718
if (!place.boundingbox) {
@@ -81,14 +52,16 @@ const handleLocationSelected = (place: PlaceResult) => {
8152
thumb-color="teal"
8253
hide-details
8354
/>
84-
<v-checkbox
85-
v-model="settings.showFieldBoundaries"
86-
label="Show field boundaries"
87-
density="compact"
88-
hide-details
55+
<h3 class="group">Opacity: {{ settings.fieldBoundariesOpacity }}%</h3>
56+
<v-slider
57+
v-model.number="settings.fieldBoundariesOpacity"
58+
:min="0"
59+
:max="100"
60+
:step="1"
8961
color="teal"
90-
class="mt-2"
91-
:disabled="fieldBoundariesDisabled"
62+
track-color="grey-darken-2"
63+
thumb-color="teal"
64+
hide-details
9265
/>
9366
<h3 class="group legend">Legend</h3>
9467
<MapLegend />

src/composables/useMap.ts

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -93,16 +93,20 @@ watch(
9393
}
9494

9595
globalPredictionsController.value = createGlobalPredictionsLayer(settings.value)
96-
globalPredictionsController.value.layer.setVisible(settings.value.showFieldBoundaries)
96+
globalPredictionsController.value.layer.setOpacity(
97+
settings.value.fieldBoundariesOpacity / 100,
98+
)
9799
map.value.addLayer(globalPredictionsController.value.layer)
98100
}
99101
},
100102
)
101103

102104
watch(
103-
() => settings.value.showFieldBoundaries,
104-
(visible) => {
105-
globalPredictionsController.value?.layer.setVisible(visible)
105+
() => settings.value.fieldBoundariesOpacity,
106+
(opacity) => {
107+
const olOpacity = opacity / 100
108+
globalPredictionsController.value?.layer.setOpacity(olOpacity)
109+
globalOverviewLayer.value?.setOpacity(olOpacity)
106110
},
107111
)
108112

@@ -157,11 +161,14 @@ const updateLayers = () => {
157161
if (!globalPredictionsController.value) {
158162
// Only handle first initialization here, year changes are handled by a watcher on year above
159163
globalPredictionsController.value = createGlobalPredictionsLayer(settings.value)
160-
globalPredictionsController.value.layer.setVisible(settings.value.showFieldBoundaries)
164+
globalPredictionsController.value.layer.setOpacity(
165+
settings.value.fieldBoundariesOpacity / 100,
166+
)
161167
map.value.addLayer(globalPredictionsController.value.layer)
162168
}
163169
if (!globalOverviewLayer.value) {
164170
globalOverviewLayer.value = createGlobalOverviewLayer(settings.value)
171+
globalOverviewLayer.value.setOpacity(settings.value.fieldBoundariesOpacity / 100)
165172
map.value.addLayer(globalOverviewLayer.value)
166173
}
167174
} else {

src/composables/usePermalink.ts

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ export interface PermalinkStateInference extends PermalinkState {
3030

3131
export interface PermalinkStateGlobal extends PermalinkState {
3232
threshold: number
33-
showFieldBoundaries: boolean
33+
fieldBoundariesOpacity: number
3434
}
3535

3636
export default function usePermalink() {
@@ -59,7 +59,7 @@ export default function usePermalink() {
5959
center: [0, 0],
6060
year: 2025,
6161
threshold: 0.4,
62-
showFieldBoundaries: true,
62+
fieldBoundariesOpacity: 90,
6363
}
6464

6565
const getDefaultState = (mode: string): PermalinkStateInference | PermalinkStateGlobal => {
@@ -175,7 +175,7 @@ export default function usePermalink() {
175175
zoom,
176176
center,
177177
threshold: defaultGlobalState.threshold,
178-
showFieldBoundaries: defaultGlobalState.showFieldBoundaries,
178+
fieldBoundariesOpacity: defaultGlobalState.fieldBoundariesOpacity,
179179
}
180180

181181
for (const part of keyValueParts) {
@@ -185,8 +185,9 @@ export default function usePermalink() {
185185
} else if (part.startsWith('year:')) {
186186
const year = parseInt(part.substring(5), 10)
187187
if (!isNaN(year)) result.year = year
188-
} else if (part.startsWith('field_boundaries:')) {
189-
result.showFieldBoundaries = part.substring(17) === '1'
188+
} else if (part.startsWith('opacity:')) {
189+
const opacity = parseInt(part.substring(8), 10)
190+
result.fieldBoundariesOpacity = isNaN(opacity) ? 90 : opacity
190191
}
191192
}
192193

@@ -289,15 +290,15 @@ export default function usePermalink() {
289290
if (settings.value.year) {
290291
hashParts.push(`year:${settings.value.year}`)
291292
}
292-
hashParts.push(`field_boundaries:${settings.value.showFieldBoundaries ? 1 : 0}`)
293+
hashParts.push(`opacity:${settings.value.fieldBoundariesOpacity}`)
293294

294295
state = {
295296
mode,
296297
zoom,
297298
center,
298299
threshold: settings.value.threshold,
299300
year: settings.value.year,
300-
showFieldBoundaries: settings.value.showFieldBoundaries,
301+
fieldBoundariesOpacity: settings.value.fieldBoundariesOpacity,
301302
}
302303
}
303304

@@ -334,7 +335,7 @@ export default function usePermalink() {
334335

335336
function restoreGlobalState(state: PermalinkStateGlobal) {
336337
settings.value.threshold = state.threshold
337-
settings.value.showFieldBoundaries = state.showFieldBoundaries
338+
settings.value.fieldBoundariesOpacity = state.fieldBoundariesOpacity
338339
if (state.year) {
339340
settings.value.year = state.year
340341
}
@@ -366,7 +367,7 @@ export default function usePermalink() {
366367
settings.value.areaCoverage,
367368
settings.value.buffer,
368369
settings.value.threshold,
369-
settings.value.showFieldBoundaries,
370+
settings.value.fieldBoundariesOpacity,
370371
],
371372
() => {
372373
if (!map.value) {

src/composables/useSettings.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export interface Settings {
1212
expertMode: boolean
1313
mode: string
1414
threshold: number
15-
showFieldBoundaries: boolean
15+
fieldBoundariesOpacity: number
1616
}
1717

1818
export interface ModelInfo {
@@ -58,7 +58,7 @@ const defaultSettings: Settings = {
5858
expertMode: false,
5959
mode: defaultMode,
6060
threshold: 0.4,
61-
showFieldBoundaries: true,
61+
fieldBoundariesOpacity: 90,
6262
}
6363

6464
const defaultModel = computed(() => {

src/workers/predictions-worker.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ layer.setStyle((feature, resolution) => {
3737
const widthPx = (extent[2] - extent[0]) / resolution
3838
const heightPx = (extent[3] - extent[1]) / resolution
3939
if (widthPx < 3 && heightPx < 3) return smallStyle
40-
fill.setColor(getColorForValue(confidenceColorScale, confidence, 0.3))
40+
fill.setColor(getColorForValue(confidenceColorScale, confidence, 0.35))
4141
return polyStyle
4242
})
4343

0 commit comments

Comments
 (0)