Skip to content
🔵Entwurf (gut)62%
Vollständigkeit:
80%
Korrektheit:
75%
⏳ Noch nicht geprüft

Layer Management ​

Overview ​

The layer-manager.ts module manages the base layers of the p2d2 mapping application. It provides functions for creating WMS layers, toggle logic for visibility, and automatic state persistence in localStorage.

Managed Layers ​

Aerial Imagery (City of Cologne) ​

WMS Endpoint:

https://geoportal.stadt-koeln.de/wss/service/luftbilder_2024_wms/guest

Layer Name: luftbilder_2024_23

Supported Projections:

  • EPSG:3857 (Web Mercator)
  • EPSG:25832 (UTM Zone 32N)

Z-Index: 7 (from MAP_CONFIG.Z_INDEX.LUFTBILD)

Features:

  • Initially invisible (visible: false)
  • Automatic projection detection
  • Cross-origin configured for image loading

basemap.de ​

WMS Endpoint:

https://sgx.geodatenzentrum.de/wms_basemapde

Layer Name: de_basemapde_web_raster_farbe

Supported Projections:

  • EPSG:3857 (Web Mercator)

Z-Index: 15 (from MAP_CONFIG.Z_INDEX.BASEMAP)

Features:

  • Color variant (standard)
  • Gray variant available: de_basemapde_web_raster_grau
  • Transparency enabled for overlays
  • Initially invisible (visible: false)

API Reference ​

createLuftbildLayer(projection: string): TileLayer ​

Creates WMS layer for Cologne aerial imagery 2024.

Parameters:

  • projection (string): EPSG code ('EPSG:3857' or 'EPSG:25832')

Returns:

  • OpenLayers TileLayer with TileWMS source

Implementation:

typescript
export function createLuftbildLayer(projection: string): TileLayer {
  const supportedProjections = ["EPSG:3857", "EPSG:25832"];
  const useProjection = supportedProjections.includes(projection)
    ? projection
    : "EPSG:3857";

  const layer = new TileLayer({
    source: new TileWMS({
      url: "https://geoportal.stadt-koeln.de/wss/service/luftbilder_2024_wms/guest",
      params: {
        LAYERS: "luftbilder_2024_23",
        FORMAT: "image/png",
        TILED: true,
      },
      projection: useProjection,
      crossOrigin: "anonymous",
    }),
    zIndex: MAP_CONFIG.Z_INDEX.LUFTBILD,
    visible: false,
  });

  luftbildLayer = layer;
  return layer;
}

createBasemapLayer(): TileLayer ​

Creates WMS layer for basemap.de.

Parameters: None

Returns:

  • OpenLayers TileLayer with TileWMS source

Implementation:

typescript
export function createBasemapLayer(): TileLayer {
  const layer = new TileLayer({
    source: new TileWMS({
      url: "https://sgx.geodatenzentrum.de/wms_basemapde",
      params: {
        LAYERS: "de_basemapde_web_raster_farbe",
        FORMAT: "image/png",
        TRANSPARENT: "true",
        TILED: true,
      },
      projection: "EPSG:3857",
      crossOrigin: "anonymous",
    }),
    zIndex: MAP_CONFIG.Z_INDEX.BASEMAP,
    visible: false,
  });

  basemapLayer = layer;
  return layer;
}

toggleBaseLayer(layerName: string): void ​

Toggles visibility of a base layer.

Parameters:

  • layerName (string): 'luftbild' or 'basemap'

Behavior:

  • Independent toggle: Both layers can be active simultaneously
  • Persistence in localStorage
  • Button highlighting via CSS class highlighted
  • Console logging for debugging

localStorage Keys:

  • luftbildVisible: 'true' | 'false'
  • basemapVisible: 'true' | 'false'

Implementation:

typescript
export function toggleBaseLayer(layerName: string): void {
  if (layerName === "luftbild" && luftbildLayer) {
    // Toggle Luftbild independently
    const newVisibility = !luftbildLayer.getVisible();
    luftbildLayer.setVisible(newVisibility);

    // Update only the Luftbild button
    const luftbildBtn = document.querySelector(
      '[data-layer-toggle="luftbild"]',
    );
    if (luftbildBtn) {
      if (newVisibility) {
        luftbildBtn.classList.add("highlighted");
      } else {
        luftbildBtn.classList.remove("highlighted");
      }
    }
  } else if (layerName === "basemap" && basemapLayer) {
    // Toggle basemap.de independently
    const newVisibility = !basemapLayer.getVisible();
    basemapLayer.setVisible(newVisibility);

    // Update only the basemap button
    const basemapBtn = document.querySelector('[data-layer-toggle="basemap"]');
    if (basemapBtn) {
      if (newVisibility) {
        basemapBtn.classList.add("highlighted");
      } else {
        basemapBtn.classList.remove("highlighted");
      }
    }
  }

  // Persist both states separately in localStorage
  try {
    localStorage.setItem(
      "luftbildVisible",
      String(luftbildLayer ? luftbildLayer.getVisible() : false),
    );
    localStorage.setItem(
      "basemapVisible",
      String(basemapLayer ? basemapLayer.getVisible() : false),
    );
  } catch (error) {
    console.warn("Could not persist layer states", error);
  }

  console.log("Layer toggle:", {
    luftbild: luftbildLayer ? luftbildLayer.getVisible() : false,
    basemap: basemapLayer ? basemapLayer.getVisible() : false,
  });
}

initLayerControls(): void ​

Initializes event listeners for layer toggle buttons.

Function:

  1. Registers click handlers on [data-layer-toggle] buttons
  2. Restores previous state from localStorage
  3. Updates button styling

HTML Structure:

html
<button data-layer-toggle="luftbild">Aerial Imagery</button>
<button data-layer-toggle="basemap">basemap.de</button>

Implementation:

typescript
export function initLayerControls(): void {
  // Add event listeners for layer toggle buttons
  document.addEventListener("click", (event) => {
    const target = event.target as HTMLElement;
    const button = target.closest("[data-layer-toggle]");
    if (!button) return;

    const layerName = (button as HTMLElement).dataset.layerToggle;
    if (layerName) {
      toggleBaseLayer(layerName);
    }
  });

  // Restore previous layer states from localStorage
  try {
    const luftbildVisible = localStorage.getItem("luftbildVisible") === "true";
    const basemapVisible = localStorage.getItem("basemapVisible") === "true";

    if (luftbildVisible && luftbildLayer) {
      luftbildLayer.setVisible(true);
      const btn = document.querySelector('[data-layer-toggle="luftbild"]');
      if (btn) btn.classList.add("highlighted");
    }

    if (basemapVisible && basemapLayer) {
      basemapLayer.setVisible(true);
      const btn = document.querySelector('[data-layer-toggle="basemap"]');
      if (btn) btn.classList.add("highlighted");
    }
  } catch (error) {
    console.warn("Could not restore layer states from localStorage", error);
  }
}

Getter Functions ​

getLuftbildLayer(): TileLayer | null ​

Returns the current aerial imagery layer instance.

getBasemapLayer(): TileLayer | null ​

Returns the current basemap.de layer instance.

getLayerStates(): { luftbild: boolean; basemap: boolean } ​

Returns the current visibility status of both layers (for debugging).

State Management ​

LocalStorage Schema ​

KeyValueDescription
luftbildVisible'true' | 'false'Aerial imagery layer visibility
basemapVisible'true' | 'false'basemap.de visibility

Global Variables ​

  • luftbildLayer: TileLayer | null - Reference to aerial imagery layer
  • basemapLayer: TileLayer | null - Reference to basemap.de layer

Usage ​

Complete Setup ​

typescript
import { 
  createLuftbildLayer, 
  createBasemapLayer, 
  initLayerControls 
} from './layer-management';

// Create layers
const luftbild = createLuftbildLayer('EPSG:3857');
const basemap = createBasemapLayer();

// Add to map
map.addLayer(luftbild);
map.addLayer(basemap);

// Initialize controls
initLayerControls();

HTML Integration ​

html
<div class="layer-controls">
  <button data-layer-toggle="luftbild" class="layer-btn">Aerial Imagery</button>
  <button data-layer-toggle="basemap" class="layer-btn">basemap.de</button>
</div>

CSS for Button Highlighting ​

css
.layer-btn.highlighted {
  background-color: #007bff;
  color: white;
}

Dependencies ​

Imports:

  • ol/layer/Tile (TileLayer)
  • ol/source/TileWMS
  • ../config/map-config (MAP_CONFIG)

Exports:

  • createLuftbildLayer
  • createBasemapLayer
  • toggleBaseLayer
  • initLayerControls
  • getLuftbildLayer
  • getBasemapLayer
  • getLayerStates
  • LAYER_ZINDEX (Re-export from MAP_CONFIG.Z_INDEX)

Error Handling ​

  • localStorage errors are caught and warned
  • Missing layer instances are checked before operations
  • Console logging for debugging purposes

Best Practices ​

  1. Layer Creation Before Controls: Always create layers first, then initialize controls
  2. Projection Consistency: Create aerial imagery layer with correct projection
  3. State Persistence: localStorage is automatically managed
  4. Button Integration: HTML buttons require data-layer-toggle attribute