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.