Skip to content

Commit

Permalink
Merge pull request #710 from Deltares/707-front-end-information-panel…
Browse files Browse the repository at this point in the history
…-wms-layer

707 front end information panel wms layer
  • Loading branch information
martinapippi authored and hvangeffen committed Feb 26, 2024
2 parents 6d7959c + 466d586 commit b17d694
Show file tree
Hide file tree
Showing 11 changed files with 813 additions and 316 deletions.
618 changes: 394 additions & 224 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,13 @@
"geotiff": "^2.1.3",
"lodash-es": "^4.17.21",
"luxon": "^3.4.3",
"mapbox-gl": "^2.15.0",
"maplibre-gl": "^3.6.2",
"oidc-client-ts": "^2.4.0",
"pinia": "^2.1.7",
"pinia-plugin-persistedstate": "^3.2.0",
"typescript-json-serializer": "^6.0.1",
"vue": "^3.3.7",
"vue-maplibre-gl": "^3.0.3",
"vue-router": "^4.2.5",
"vue-slider-component": "^4.1.0-beta.7",
"vuetify": "^3.4.10"
Expand All @@ -49,7 +50,6 @@
"@types/d3": "^7.4.2",
"@types/lodash-es": "^4.17.10",
"@types/luxon": "^3.3.3",
"@types/mapbox-gl": "^2.7.17",
"@types/node": "^20.8.10",
"@vitejs/plugin-vue": "^5.0.3",
"@vue/eslint-config-typescript": "^12.0.0",
Expand Down
41 changes: 17 additions & 24 deletions src/components/map/MapComponent.vue
Original file line number Diff line number Diff line change
@@ -1,44 +1,37 @@
<template>
<mapbox-map
style="width: 100%; height: 100%"
:access-token="accessToken"
map-style="https://basemaps.cartocdn.com/gl/positron-gl-style/style.json"
<mgl-map
ref="map"
:pitch="0"
:bearing="0"
:center="[0, 0]"
:min-zoom="2"
:interactive="true"
:drag-pan="true"
:scroll-zoom="true"
:transformRequest="transformRequest"
:useWebGL2="true"
@mb-created="setMapInstance"
:transform-request="transformRequest"
>
<slot></slot>
</mapbox-map>
</mgl-map>
</template>

<script setup lang="ts">
import { onBeforeMount, ref } from 'vue'
import { MapboxMap } from '@studiometa/vue-mapbox-gl'
import { configManager } from '../../services/application-config'
import type { Map, ResourceType } from 'mapbox-gl'
import { configManager } from '@/services/application-config'
import { authenticationManager } from '@/services/authentication/AuthenticationManager'
import { MglMap, useMap, MglDefaults } from 'vue-maplibre-gl'
import { type ResourceType, type RequestParameters } from 'maplibre-gl'
const accessToken = ref('')
const map = ref<Map | undefined>()
import 'maplibre-gl/dist/maplibre-gl.css'
import 'vue-maplibre-gl/dist/vue-maplibre-gl.css'
onBeforeMount(() => {
accessToken.value = configManager.get('VITE_MAPBOX_TOKEN')
})
MglDefaults.style =
'https://basemaps.cartocdn.com/gl/positron-gl-style/style.json'
function setMapInstance(mapInstance: Map) {
mapInstance.dragRotate.disable()
mapInstance.touchZoomRotate.disableRotation()
mapInstance.doubleClickZoom.disable()
map.value = mapInstance
}
const map = useMap()
function transformRequest(url: string, resourceType: ResourceType) {
function transformRequest(
url: string,
resourceType?: ResourceType,
): RequestParameters {
if (!configManager.authenticationIsEnabled)
return {
url,
Expand Down
27 changes: 0 additions & 27 deletions src/components/spatialdisplay/LayerKindControl.vue

This file was deleted.

136 changes: 101 additions & 35 deletions src/components/spatialdisplay/SpatialDisplayComponent.vue
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
<template>
<MapComponent>
<AnimatedMapboxLayer
v-if="layerKind === LayerKind.Static"
v-if="layerKind === LayerKind.Static && showLayer"
:layer="layerOptions"
@doubleclick="onCoordinateClick"
/>
<AnimatedStreamlineMapboxLayer
v-if="layerKind === LayerKind.Streamline"
v-if="layerKind === LayerKind.Streamline && showLayer"
:layerOptions="layerOptions"
:streamlineOptions="layerCapabilities?.animatedVectors"
@doubleclick="onCoordinateClick"
Expand All @@ -28,17 +28,31 @@
:ticks="elevationTicks"
:unit="elevationUnit"
/>
<LocationsLayerComponent
v-if="filterIds"
:filterIds="filterIds"
:locationId="props.locationId"
@changeLocationId="onLocationChange"
/>
<LayerKindControl
v-model="layerKind"
v-if="canUseStreamlines"
class="layer-type-control"
/>
<v-chip-group class="control-container">
<LocationsLayerComponent
v-if="filterIds"
:filterIds="filterIds"
:locationId="props.locationId"
@changeLocationId="onLocationChange"
/>
<InformationPanel
:layerTitle="props.layerCapabilities?.title"
:currentTime="currentTime"
:forecastTime="forecastTime"
:colourScales="colourScales"
:completelyMissing="props.layerCapabilities?.completelyMissing ?? false"
:firstValueTime="
new Date(props.layerCapabilities?.firstValueTime ?? '')
"
:lastValueTime="new Date(props.layerCapabilities?.lastValueTime ?? '')"
:colorScaleRange="colorScaleRange"
:canUseStreamlines="canUseStreamlines"
@color-scale-range-change="updateColorScaleRange"
v-model:color-scale-index="colorScaleIndex"
v-model:layer-kind="layerKind"
v-model:show-layer="showLayer"
/>
</v-chip-group>
<SelectedCoordinateLayer
:longitude="props.longitude"
:latitude="props.latitude"
Expand All @@ -56,7 +70,6 @@

<script setup lang="ts">
import MapComponent from '@/components/map/MapComponent.vue'
import LayerKindControl from '@/components/spatialdisplay/LayerKindControl.vue'
import AnimatedStreamlineMapboxLayer from '@/components/wms/AnimatedStreamlineMapboxLayer.vue'
import { ref, computed, onBeforeMount, watch, watchEffect } from 'vue'
Expand All @@ -69,6 +82,7 @@ import AnimatedMapboxLayer, {
MapboxLayerOptions,
} from '@/components/wms/AnimatedMapboxLayer.vue'
import LocationsLayerComponent from '@/components/wms/LocationsLayerComponent.vue'
import InformationPanel from '../wms/InformationPanel.vue'
import SelectedCoordinateLayer from '@/components/wms/SelectedCoordinateLayer.vue'
import ElevationSlider from '@/components/wms/ElevationSlider.vue'
import DateTimeSlider from '@/components/general/DateTimeSlider.vue'
Expand All @@ -79,6 +93,8 @@ import type { MapLayerMouseEvent, MapLayerTouchEvent } from 'mapbox-gl'
import { configManager } from '@/services/application-config'
import type { Layer } from '@deltares/fews-wms-requests'
import { LayerKind } from '@/lib/streamlines'
import { Style } from '@deltares/fews-wms-requests'
import { ColourMap } from '@deltares/fews-web-oc-charts'
interface ElevationWithUnitSymbol {
units?: string
Expand All @@ -87,6 +103,12 @@ interface ElevationWithUnitSymbol {
unitSymbol: string
}
export interface StyleColourMap {
style: Style
colourMap: ColourMap | undefined
title: string
}
interface Props {
layerName?: string
times?: Date[]
Expand Down Expand Up @@ -126,8 +148,10 @@ const elevationTicks = ref<number[]>()
const elevationUnit = ref('')
const currentTime = ref<Date>(new Date())
const forecastTime = ref<Date>()
const layerOptions = ref<MapboxLayerOptions>()
let debouncedSetLayerOptions!: () => void
const colorScaleIndex = ref<number>(0)
const colorScaleRange = ref<{ min: number; max: number }>()
const colorScaleRangeString = computed(() => {
Expand All @@ -138,19 +162,55 @@ const colorScaleRangeString = computed(() => {
})
const legendLayerName = ref(props.layerName)
const settings = useUserSettingsStore()
const baseUrl = configManager.get('VITE_FEWS_WEBSERVICES_URL')
const legendGraphic = useWmsLegend(
baseUrl,
legendLayerName,
() => settings.useDisplayUnits,
colorScaleRangeString,
)
const updateColorScaleRange = (range: { min: number; max: number }) => {
colorScaleRange.value = range
}
const showLayer = ref<boolean>(true)
const layerKind = ref(LayerKind.Static)
const legend = computed(() => {
return legendGraphic.value?.legend
})
const colourScales = ref<StyleColourMap[]>()
const legend = ref<ColourMap>()
const usedStyle = ref<Style>()
const legendTitle = ref<string>()
watch(
() => props.layerCapabilities?.styles,
() => {
const styles = props.layerCapabilities?.styles
if (styles === undefined) return
colourScales.value = styles.map((style) => {
const legendGraphic = useWmsLegend(
baseUrl,
legendLayerName,
() => settings.useDisplayUnits,
colorScaleRangeString,
style,
)
const colourScale = {
style: style,
colourMap: legendGraphic.value?.legend,
title: getLegendTitle(legendGraphic),
}
watch(legendGraphic, () => {
colourScale.colourMap = legendGraphic.value?.legend
colourScale.title = getLegendTitle(legendGraphic)
legend.value = colourScales.value?.[colorScaleIndex.value].colourMap
usedStyle.value = colourScales.value?.[colorScaleIndex.value].style
legendTitle.value = colourScales.value?.[colorScaleIndex.value].title
})
return colourScale
})
},
{ immediate: true },
)
const canUseStreamlines = computed(
() => props.layerCapabilities?.animatedVectors !== undefined,
Expand All @@ -175,6 +235,10 @@ const layerHasElevation = computed(() => {
watch(
() => props.layerCapabilities,
(layer) => {
if (layer?.keywordList !== undefined) {
forecastTime.value =
new Date(layer?.keywordList[0].forecastTime as string) ?? null
}
legendLayerName.value = props.layerName
colorScaleRange.value = undefined
if (layer?.elevation) {
Expand All @@ -201,14 +265,6 @@ watch(colorScaleRange, () => {
setLayerOptions()
})
const legendTitle = computed(() => {
if (!props.layerCapabilities) return ''
const unitString = legendGraphic.value?.unit
? ` [${legendGraphic.value?.unit}]`
: ''
return `${props.layerCapabilities.title}${unitString}`
})
watch(
() => props.times,
() => {
Expand Down Expand Up @@ -252,11 +308,22 @@ function setLayerOptions(): void {
}
layerOptions.value.elevation = currentElevation.value
layerOptions.value.colorScaleRange = colorScaleRangeString.value
layerOptions.value.style = usedStyle.value?.name
} else {
layerOptions.value = undefined
}
}
function getLegendTitle(
legendGraphic: ReturnType<typeof useWmsLegend>,
): string {
if (!props.layerCapabilities) return ''
const unitString = legendGraphic.value?.unit
? ` [${legendGraphic.value?.unit}]`
: ''
return `${props.layerCapabilities.title}${unitString}`
}
function onLocationChange(locationId: string | null): void {
emit('changeLocationId', locationId)
}
Expand Down Expand Up @@ -294,10 +361,9 @@ function onCoordinateClick(
box-shadow: 0 0 5px rgba(0, 0, 0, 0.5);
}
.layer-type-control {
.control-container {
position: absolute;
top: 10px;
right: 5px;
z-index: 1000;
top: 8px;
left: 10px;
}
</style>
4 changes: 4 additions & 0 deletions src/components/wms/AnimatedMapboxLayer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export interface MapboxLayerOptions {
bbox?: LngLatBounds
elevation?: number | null
colorScaleRange?: string
style?: string
}
interface Props {
Expand Down Expand Up @@ -108,6 +109,9 @@ function getImageSourceOptions(): ImageSourceOptions {
getMapUrl.searchParams.append('height', `${canvas.height}`)
getMapUrl.searchParams.append('width', `${canvas.width}`)
getMapUrl.searchParams.append('time', `${time}`)
if (props.layer.style) {
getMapUrl.searchParams.append('styles', props.layer.style)
}
if (props.layer.elevation) {
getMapUrl.searchParams.append('elevation', `${props.layer.elevation}`)
}
Expand Down
Loading

0 comments on commit b17d694

Please sign in to comment.