Documentation

Pro handbook

Layers

What a layer is and what the rules are: Layers (concept). This page shows the API. Checks between layers are described in Rules between layers.

Creating an editor with layers#

Pass a list of layers instead of a single partition. Each entry is an Ebene:

Field Type Meaning
id EbenenId Unique ID (a branded string: 'parcels' as EbenenId).
name string Display name.
partition Partition The layer's content, e.g. from importGeoJSON or createPartition().
sichtbar boolean Visible.
gesperrt boolean Locked.

The first layer of the list starts active; the last one lies on top. An empty list throws. An editor created with a single partition has one layer with the ID 'ebene' and an empty name.

import { importGeoJSON, type Ebene, type EbenenId, type FaceId, type FeatureCollection } from '@vectorstream/core';
import type { Adapter } from '@vectorstream/adapter';
import { Editor } from '@vectorstream/editor';

export const PARCELS = 'parcels' as EbenenId;
export const BUILDINGS = 'buildings' as EbenenId;

/** Two layers, each its own partition. The last entry lies on top. */
export function createLayeredEditor(adapter: Adapter, parcels: FeatureCollection, buildings: FeatureCollection): Editor {
  const layers: Ebene[] = [
    { id: PARCELS, name: 'Parcels', partition: importGeoJSON(parcels), sichtbar: true, gesperrt: false },
    { id: BUILDINGS, name: 'Buildings', partition: importGeoJSON(buildings), sichtbar: true, gesperrt: false },
  ];
  const editor = new Editor(layers, adapter); // the first layer starts active
  editor.aktiveEbene = BUILDINGS; // modes now draw into and edit the buildings layer
  return editor;
}

/**
 * Moves a face of the active layer into another layer — after asking what it would cost.
 * Returns the new face IDs in the target layer, or `undefined` if the user declined or the move
 * was rejected. The preview throws `InputRejected` where the move would be refused.
 */
export function moveFace(
  editor: Editor,
  face: FaceId,
  target: EbenenId,
  confirm: (lost: Record<string, unknown>) => boolean,
): FaceId[] | undefined {
  // A dry run: the move is executed and rolled back, so the preview cannot differ from the result.
  const preview = editor.umzugVorschau(face, target);
  if (Object.keys(preview.verdraengt).length > 0 && !confirm(preview.verdraengt)) return undefined;
  return editor.umziehen(face, target); // one undo step
}

The test of this example moves the building of the sample data into the parcel layer: the preview reports that the label 'House 7' would be lost, the move creates two building parts with use: 'house' (the upper layer wins), built: 1965 and the parcel number of the part they lie in, and one undo restores both layers.

Methods#

Call Effect Undoable
editor.ebenen The layers, bottom to top. —
editor.aktiveEbene / editor.aktiveEbene = id Read or set the active layer. Setting aborts a running gesture; a locked layer cannot be activated. no
editor.ebeneHinzufuegen(name) Adds an empty layer on top, with the same grid as the active layer, makes it active and returns its ID ('ebene-1', 'ebene-2', …). no
editor.benenneEbene(id, name) Renames a layer. no
editor.umsortieren(ids) Puts the layers in this order (bottom to top). The list must contain every layer exactly once. no
editor.setzeSichtbar(id, visible) Shows or hides a layer. Not the active one. no
editor.setzeGesperrt(id, locked) Locks or unlocks a layer. Not the active one. no
editor.inhaltVon(id) Number of faces plus nodes in the layer. —
editor.ebeneLeeren(id) Removes all content of a layer in one transaction (clear-layer). Returns false if it was empty. yes
editor.ebeneEntfernen(id) Removes an empty layer with no rule of its own and none pointing to it; never the last one. If it was active, the nearest usable layer becomes active. no
editor.umzugVorschau(face, target) What moving a face of the active layer to target would produce, without doing it. —
editor.umziehen(face, target) Moves a face of the active layer to target (move-to-layer). Returns the new face IDs, or undefined if rejected. yes

Every change to the layer list emits ebenenchange with the active layer's ID.

Refusals throw. The layer methods that are not transactions throw an InputRejected when they refuse — hiding or locking the active layer, activating a locked layer, removing a non-empty or the last layer, removing one with rules attached to it, an incomplete order. Its code ('editor.layerActiveHide', …) says why. umzugVorschau throws the same rejections as the move (same layer, locked target, different grid, a face with holes). umziehen reports them through rejected instead, like every transaction.

Exporting all layers#

exportGeoJSON works on one partition. For all layers, export each one — see GeoJSON.

Layer colors#

Each map adapter takes an option ebenenFarbe: (layerId) => string | undefined. Without it, or when it returns undefined, a layer gets a color from a fixed palette chosen by its ID.

API: Ebene, Editor, UmzugVorschau.

See it on a map.