Zum Inhalt springen

Quickstart

Diese Seite richtet sich an Entwicklerinnen und Entwickler. Wer selbst keine Software schreibt, ist hier falsch: Schritt-für-Schritt-Wege ohne Programmierkenntnisse stehen bei den Anleitungen, und ein bestimmtes Zeichen findet sich am schnellsten über Zeichen suchen.

Am Ende dieser Seite steht ein echtes Zeichen aus dem Katalog — Bergungsgruppe (recipe.E.1.1) — in vier vollständigen, lauffähigen Beispielen auf dem Bildschirm: als SVG-String ohne Framework, als React-Komponente, als Custom Element ohne Framework und als Bild auf einer echten MapLibre-Karte. Kein Beispiel ist ein Ausschnitt; jedes lässt sich unverändert in ein eigenes Projekt kopieren.

Die acht Pakete dieses Projekts sind Workspace-Pakete, kein npm-Release: alle packages/*/package.json tragen "private": true und zeigen mit main auf ./src/index.ts. npm install @einsatzzeichen/core funktioniert nirgendwo — die Beispiele unten laufen innerhalb eines Checkouts dieses Repositories, eingebunden über workspace:*. Alle vier Kanäle setzen außerdem @einsatzzeichen/catalog voraus, für zwei Dinge bekannt aus der Anleitung für Software:

  • Der Katalog-Index ist nicht browsertauglich. fonts.ts importiert node:url, und der Index re-exportiert es. Ein Import von @einsatzzeichen/catalog läuft deshalb sicher in Node — ein Build- oder Testskript, ein SSR-Schritt — aber nicht ungeprüft in einem Browser-Bundle. core, schema, react, web-component und maplibre haben dieses Problem nicht.
  • Die Schrift gehört zum Zeichen. renderSvg() schreibt font-family="Arimo" in jedes Zeichen mit Kürzel. Ohne ausgelieferte Schriftdatei setzt der Browser eine Ersatzschrift mit anderen Vorschubbreiten. Das Subset liegt in packages/catalog/assets (SIL OFL 1.1).
BergungsgruppeGrundzeichen: Taktische Formation. Organisation: Technisches Hilfswerk. Stärke: Gruppe. Kürzel: B. Trägerkürzel: THW.BTHW
recipe.E.1.1 · BergungsgruppeAnhang E.1 · BBK / BABZ: Taktische Zeichen im Bevölkerungsschutz — Empfehlungen zur Einführung einer FwDV 102/DV 102technisch geprüftfachlich: noch nicht geprüft

Alle vier Kanäle komponieren dieselbe SymbolSpec mit composeFromCatalog() zu derselben Zeichnung; sie unterscheiden sich nur darin, wie diese Zeichnung danach auf den Bildschirm kommt. Die beiden Marken unter dem Zeichen gelten für jeden der vier Wege gleichermaßen: die linke sagt, ob die Geometrie gegen die Vorlage gemessen und mit Tests belegt ist, die rechte, ob eine Fachperson bestätigt hat, dass es das richtige Zeichen für seine Bedeutung ist. Beide Marken lassen sich programmatisch abfragen — symbol.review.technical und symbol.review.domain im Katalog-Snapshot, siehe Baukasten und Stand der Prüfung.

TypeScript, ohne Framework. renderSvg() aus @einsatzzeichen/core macht aus einer Zeichnung einen SVG-String — das, was hinter den anderen drei Kanälen steckt. Läuft in Node genauso wie im Browser, ganz ohne Rahmenwerk.

React. <Einsatzzeichen> aus @einsatzzeichen/react nimmt dieselbe Zeichnung entgegen und rendert sie als SVG-Element. Wer das Markup selbst platzieren will, nimmt stattdessen den Hook useEinsatzzeichenSvg(drawing, options) aus demselben Paket.

Web Component. defineEinsatzzeichenElement() aus @einsatzzeichen/web-component registriert das Custom Element <einsatzzeichen-symbol> einmalig — danach reicht element.drawing = … in jeder Umgebung, mit oder ohne React. Der Aufruf ist idempotent und verträgt mehrfaches Ausführen.

MapLibre. addSymbolImage() aus @einsatzzeichen/maplibre rastert die Zeichnung und ruft intern map.addImage() auf, damit das Zeichen in einem Symbol Layer der Karte erscheint. Zum Ausprobieren mit echter Karte, Größe und Pixel Ratio: Karte.

import { composeFromCatalog } from '@einsatzzeichen/catalog';
import { renderSvg } from '@einsatzzeichen/core';
import type { SymbolSpec } from '@einsatzzeichen/schema';
// Spezifikation für "recipe.E.1.1"
const spec: SymbolSpec = {
"kind": "formation",
"organization": "thw",
"strength": "gruppe",
"labels": {
"center": "B",
"bottomRight": "THW"
}
};
const drawing = composeFromCatalog(spec);
const svg = renderSvg(drawing, { size: 64 });
import { Einsatzzeichen } from '@einsatzzeichen/react';
import { composeFromCatalog } from '@einsatzzeichen/catalog';
import type { SymbolSpec } from '@einsatzzeichen/schema';
// Spezifikation für "recipe.E.1.1"
const spec: SymbolSpec = {
"kind": "formation",
"organization": "thw",
"strength": "gruppe",
"labels": {
"center": "B",
"bottomRight": "THW"
}
};
const drawing = composeFromCatalog(spec);
export function Symbol() {
return <Einsatzzeichen drawing={drawing} size={64} />;
}
import {
DEFAULT_TAG_NAME,
defineEinsatzzeichenElement,
type EinsatzzeichenElement,
} from '@einsatzzeichen/web-component';
import { composeFromCatalog } from '@einsatzzeichen/catalog';
import type { SymbolSpec } from '@einsatzzeichen/schema';
// Spezifikation für "recipe.E.1.1"
const spec: SymbolSpec = {
"kind": "formation",
"organization": "thw",
"strength": "gruppe",
"labels": {
"center": "B",
"bottomRight": "THW"
}
};
// Registriert <einsatzzeichen-symbol> einmalig (ruft customElements.define auf).
defineEinsatzzeichenElement();
const element = document.createElement(DEFAULT_TAG_NAME) as EinsatzzeichenElement;
element.drawing = composeFromCatalog(spec);
document.body.append(element);
import maplibregl from 'maplibre-gl';
import { addSymbolImage } from '@einsatzzeichen/maplibre';
import { composeFromCatalog } from '@einsatzzeichen/catalog';
import type { SymbolSpec } from '@einsatzzeichen/schema';
// Spezifikation für "recipe.E.1.1"
const spec: SymbolSpec = {
"kind": "formation",
"organization": "thw",
"strength": "gruppe",
"labels": {
"center": "B",
"bottomRight": "THW"
}
};
const map = new maplibregl.Map({ container: 'map', style: 'https://example.org/style.json' });
map.on('load', () => {
// addSymbolImage rastert die Zeichnung und ruft intern map.addImage(...) auf.
addSymbolImage(map, "recipe.E.1.1", composeFromCatalog(spec), { size: 64 });
});

Texte und Code dieser Website sind mit KI-Unterstützung entstanden und werden von Menschen geprüft; der fachliche Reviewstatus steht an jedem Zeichen.