diff --git a/index.html b/index.html index e1f32d1..afcb4ee 100644 --- a/index.html +++ b/index.html @@ -8,6 +8,10 @@
+ diff --git a/main.js b/main.js index 0b8011a..c68591b 100644 --- a/main.js +++ b/main.js @@ -5,6 +5,7 @@ import projectionBNG from "./projection"; import TileLayer from "ol/layer/Tile"; import getWMTSLayer from "./wmts"; import getWMSLayer from "./wms"; +import initPopover from "./popover"; // Create layer from imported functions const mastermapWMTS = await getWMTSLayer("os_licensed_background_colour"); @@ -33,4 +34,6 @@ const map = new Map({ center: [279731, 693249], zoom: 6, }), -}); \ No newline at end of file +}); + +initPopover(map, woodlandWMS); \ No newline at end of file diff --git a/popover.js b/popover.js new file mode 100644 index 0000000..e3754f9 --- /dev/null +++ b/popover.js @@ -0,0 +1,65 @@ +import Overlay from "ol/Overlay"; + +// References to HTML elements we will target to create our popover +const container = document.getElementById("popup"); +const content = document.getElementById("popup-content"); +const closer = document.getElementById("popup-closer"); + +// Instantiate a new Overlay +// An Overlay is an element to be displayed over the map and attached to a single map location +// https://openlayers.org/en/latest/apidoc/module-ol_Overlay-Overlay.html +const popup = new Overlay({ + element: container, + autoPan: true, + autoPanAnimation: { + duration: 250, + }, +}); + +// Close the popop on click of the closer element +closer.onclick = () => { + popup.setPosition(undefined); + closer.blur(); + return false; +}; + +// Setup the popup position and content +const setupPopup = (coord, attributes) => { + // Clear previous attributes + content.innerHTML = ""; + // Set the position of the popop + popup.setPosition(coord); + // Iterate over the attributes, appending a simple HTML snipped for each one + Object.entries(attributes).forEach( + ([key, value]) => (content.innerHTML += `

${key}: ${value}

`) + ); +}; + +// Initialise the popover +const initPopover = (map, layer) => { + // Define the function which trigger on click of the map + map.on("singleclick", (evt) => { + // Get the previously assigned map layer + const layerName = layer.getProperties().layerName; + const viewResolution = map.getView().getResolution(); + // Get the URL for the GetFeatureInfo request + const url = layer + .getSource() + .getFeatureInfoUrl(evt.coordinate, viewResolution, "EPSG:27700", { + INFO_FORMAT: "application/json", + QUERY_LAYERS: layerName, + }); + if (url) { + fetch(url) + .then((response) => response.json()) + .then((geojson) => { + // GetFeatureInfo returns a GeoJSON objevt from which we can extract the attributes to view in our popup + setupPopup(evt.coordinate, geojson.features[0].properties); + // Finally, add the overlay to our map + map.addOverlay(popup); + }); + } + }); +}; + +export default initPopover; \ No newline at end of file diff --git a/style.css b/style.css index e5eba2f..79904ad 100644 --- a/style.css +++ b/style.css @@ -11,4 +11,58 @@ html, body { top: 0; bottom: 0; width: 100%; +} + +/* CSS for Popup */ + +.ol-popup { + position: absolute; + background-color: white; + box-shadow: 0 1px 4px rgba(0,0,0,0.2); + padding: 15px; + border-radius: 10px; + border: 1px solid #cccccc; + bottom: 12px; + left: -50px; + min-width: 280px; +} + +#popup-content > p { + margin: 5px; +} + +.ol-popup:after, .ol-popup:before { + top: 100%; + border: solid transparent; + content: " "; + height: 0; + width: 0; + position: absolute; + pointer-events: none; +} + +.ol-popup:after { + border-top-color: white; + border-width: 10px; + left: 48px; + margin-left: -10px; +} + +.ol-popup:before { + border-top-color: #cccccc; + border-width: 11px; + left: 48px; + margin-left: -11px; +} + +.ol-popup-closer { + text-decoration: none; + position: absolute; + top: 2px; + right: 8px; +} + +.ol-popup-closer:after { + content: "✖"; + color: black; } \ No newline at end of file