From 2895a9c5fd5d7e612c48c7c6151bbf474de6a7e1 Mon Sep 17 00:00:00 2001 From: dnoneill Date: Thu, 31 Jul 2025 17:29:52 -0400 Subject: [PATCH] initial work to get inspection into viewer --- src/components/ogm-viewer/ogm-viewer.tsx | 8 +++- src/utils/inspection.ts | 55 ++++++++++++++++++++++++ src/utils/sources.ts | 4 +- 3 files changed, 64 insertions(+), 3 deletions(-) create mode 100644 src/utils/inspection.ts diff --git a/src/components/ogm-viewer/ogm-viewer.tsx b/src/components/ogm-viewer/ogm-viewer.tsx index d38d3f0..976a3fd 100644 --- a/src/components/ogm-viewer/ogm-viewer.tsx +++ b/src/components/ogm-viewer/ogm-viewer.tsx @@ -4,6 +4,7 @@ import maplibregl from 'maplibre-gl'; import { cogProtocol } from '@geomatico/maplibre-cog-protocol'; import { OgmRecord } from '../../utils/record'; +import { addLayerInspection } from '../../utils/inspection'; import { getPreviewSource, getPreviewLayers, getBoundsPreviewSource, getBoundsPreviewLayers } from '../../utils/sources'; // Only need to call this once, at the top level @@ -149,7 +150,7 @@ export class OgmViewer { const previewLayers = getPreviewLayers(this.record, previewSource); if (previewLayers && !this.record.restricted) { this.previewLayerIds = previewLayers.map(layer => layer.id); - previewLayers.forEach(layer => this.map.addLayer(layer)); + previewLayers.forEach(layer => this.addLayerInspection(layer, previewSource.infoUrl)); } } @@ -170,6 +171,11 @@ export class OgmViewer { if (bounds) this.map.fitBounds(bounds, { padding: 40 }); } + addLayerInspection(layer, infoUrl){ + this.map.addLayer(layer) + addLayerInspection(layer.source, infoUrl, this.record.references, this.map) + } + // Style the preview layers based on the current theme (vectors only) setPreviewFill() { const layerIds = this.boundsLayerIds.concat(this.previewLayerIds); diff --git a/src/utils/inspection.ts b/src/utils/inspection.ts new file mode 100644 index 0000000..fcca342 --- /dev/null +++ b/src/utils/inspection.ts @@ -0,0 +1,55 @@ +import { LngLat } from "maplibre-gl" +import { References } from "./references"; +import maplibregl from 'maplibre-gl'; + +export const addLayerInspection = (layer_id: string, infoUrl: string, references: References, map: maplibregl.Map) => { + map.on('click', (e) => { + if (references.wms) recordWMSInspection(layer_id, infoUrl, map, e.lngLat) + }) +} + +const recordWMSInspection = (layer_id: string, infoUrl: String, map: maplibregl.Map, lngLat: LngLat) => { + const bbox = map.getBounds(); + const width = map.getCanvas().width; + const height = map.getCanvas().height; + + const point = map.project(lngLat); + const params = new URLSearchParams([ + ['SERVICE', 'WMS'], + ['REQUEST', 'GetFeatureInfo'], + ['VERSION', '1.1.1'], + ['LAYERS', layer_id.split('-').slice(-1)[0]], + ['QUERY_LAYERS', layer_id.split('-').slice(-1)[0]], + ['STYLES', ''], + ['SRS', 'EPSG:4326'], + ['BBOX', `${bbox.getWest()},${bbox.getSouth()},${bbox.getEast()},${bbox.getNorth()}`], + ['WIDTH', width.toString()], + ['HEIGHT', height.toString()], + ['FORMAT', 'image/png'], + ['INFO_FORMAT', 'application/json'], + ['X', Math.round(point.x).toString()], + ['Y', Math.round(point.y).toString()], + ]); + + const url = `${infoUrl}?${params.toString()}`; + + fetch(url) + .then(r => r.json()) // adjust if you use text/html + .then(data => { + new maplibregl.Popup({className: 'my-class'}) + .setLngLat(lngLat) + .setHTML(`
${mapFeatureContent(data.features)}
`) + .setMaxWidth("300px") + .addTo(map); + }) +} + +const mapFeatureContent = (features: any[]) => { + let html = '' + features.forEach((feature) => { + for (const [key, value] of Object.entries(feature.properties)) { + html += `
${key}
${value}
` + } + }); + return html +} \ No newline at end of file diff --git a/src/utils/sources.ts b/src/utils/sources.ts index 211d3e2..dc4cdd7 100644 --- a/src/utils/sources.ts +++ b/src/utils/sources.ts @@ -1,7 +1,7 @@ import type { SourceSpecification, AddLayerObject } from 'maplibre-gl'; import type { OgmRecord } from './record'; -type AddSourceObject = { id: string; source: SourceSpecification }; +type AddSourceObject = { id: string; source: SourceSpecification, infoUrl?: string }; type LayerType = Exclude; // Given a record, generate the appropriate source for previewing the data @@ -178,7 +178,7 @@ const recordWMSSource = (record: OgmRecord): AddSourceObject => { // Generate the source spec with a unique ID based on the record const source = createWMSSource({ wmsUrl, layerIds, attribution: record.attribution }); const id = record.id; - return { id, source }; + return { id, source, infoUrl: wmsUrl }; }; // Create a MapLibre raster source specification object for a WMS layer