Mermaid Zustandsdiagramm Editor
Ein Zustandsdiagramm zeigt, in welchen Zuständen eine Sache sein kann und welche Ereignisse sie zwischen ihnen bewegen. Nimm es, wenn es um einen Lebenszyklus geht — eine Bestellung, ein Abonnement, ein Dokument in Prüfung. Das Erkennungszeichen: Deine Beschriftungen sind Eigenschaften statt Tätigkeiten — offen, versendet, storniert.
Ein Bestell-Lebenszyklus mit endgültiger Stornierung
Die Zustände sind, was eine Bestellung ist; die Beschriftungen an den Pfeilen sind, was mit ihr passiert ist. Beachte, dass Storniert aus drei Zuständen erreichbar ist, aber nirgendwohin führt — genau solche Asymmetrien macht ein Zustandsdiagramm sichtbar und ein Flussdiagramm versteckt sie.
stateDiagram-v2
[*] --> Eingegangen: Bestellung erfasst
Eingegangen --> Bezahlt: Zahlung eingegangen
Eingegangen --> Storniert: Kunde storniert
Bezahlt --> Kommissioniert: Lager packt
Bezahlt --> Erstattet: Zahlung zurückgebucht
Kommissioniert --> Versendet: Übergabe an Versanddienstleister
Kommissioniert --> Storniert: Bestand fehlt
Versendet --> Zugestellt: Empfang bestätigt
Versendet --> Verschollen: 14 Tage ohne Scan
Zugestellt --> [*]
Erstattet --> [*]
Storniert --> [*]
Verschollen --> Erstattet: Reklamation anerkanntDurchgearbeitete Beispiele
1. Die kleinste Zustandsmaschine
`[*]` ist sowohl Start- als auch Endpseudozustand — was davon gemeint ist, entscheidet die Seite des Pfeils, auf der es steht.
stateDiagram-v2
[*] --> Entwurf
Entwurf --> Veroeffentlicht: freigeben
Veroeffentlicht --> [*]2. Zustände mit Leerzeichen benennen
Zustands-IDs dürfen keine Leerzeichen enthalten, aber `state "Beschriftung" as id` liefert einen lesbaren Text bei sicherer ID. Das ist das Gegenstück zur zitierten Beschriftung im Flussdiagramm.
stateDiagram-v2
state "Wartet auf Prüfung" as pruefung
state "Änderungen erbeten" as aenderung
[*] --> pruefung
pruefung --> aenderung: Prüfer widerspricht
aenderung --> pruefung: Autor bessert nach
pruefung --> [*]: freigegeben3. Zusammengesetzte Zustände
Ein Zustand kann eine eigene Zustandsmaschine enthalten. Nutze das, wenn eine Phase innere Schritte hat, die sonst die oberste Ebene zumüllen — hier alles, was innerhalb der Verarbeitung passiert.
stateDiagram-v2
[*] --> Eingereiht
Eingereiht --> Verarbeitung: Worker übernimmt
state Verarbeitung {
[*] --> Pruefen
Pruefen --> Umwandeln: Schema in Ordnung
Umwandeln --> Schreiben: Zeilen zugeordnet
Schreiben --> [*]
}
Verarbeitung --> Erfolgreich: keine Fehler
Verarbeitung --> Fehlgeschlagen: Ausnahme geworfen
Fehlgeschlagen --> Eingereiht: erneut versuchen
Erfolgreich --> [*]4. Auswahl-Pseudozustände
Ein `<<choice>>` ist eine Verzweigung, die von einer Bedingung abhängt statt von einem Ereignis. So bleibt die Entscheidung sichtbar, ohne so zu tun, als sei sie ein Zustand, in dem das Objekt verweilt.
stateDiagram-v2
state pruefung <<choice>>
[*] --> Eingereicht
Eingereicht --> pruefung: Risikobewertung
pruefung --> Freigegeben: Punktwert < 40
pruefung --> Handpruefung: Punktwert >= 40
Handpruefung --> Freigegeben: Sachbearbeiter stimmt zu
Handpruefung --> Abgelehnt: Sachbearbeiter lehnt ab
Freigegeben --> [*]
Abgelehnt --> [*]5. Nebenläufige Bereiche
Zwei Bindestriche auf einer eigenen Zeile teilen einen zusammengesetzten Zustand in Bereiche, die gleichzeitig aktiv sind. Das ist das Einzige, was ein Zustandsdiagramm kann und ein Flussdiagramm wirklich nicht.
stateDiagram-v2
[*] --> Registrierung
state Registrierung {
[*] --> MailOffen
MailOffen --> MailBestaetigt: Link angeklickt
--
[*] --> ProfilLeer
ProfilLeer --> ProfilVollstaendig: Formular abgeschickt
}
Registrierung --> Aktiv: beides erledigt
Aktiv --> [*]Syntaxreferenz für Zustandsdiagramme
Nimm `stateDiagram-v2` statt `stateDiagram`. Beides rendert, aber v2 ist die aktiv weiterentwickelte Layout-Engine und kommt mit zusammengesetzten und nebenläufigen Zuständen deutlich besser zurecht.
| Syntax | Bedeutung |
|---|---|
| stateDiagram-v2 | Öffnet das Diagramm. `stateDiagram` funktioniert weiterhin, ist aber das ältere Layout. |
| [*] --> A | Startzustand — der Einstiegspunkt. |
| A --> [*] | Endzustand. |
| A --> B | Übergang ohne benanntes Auslöser-Ereignis. |
| A --> B: Ereignis | Übergang mit dem auslösenden Ereignis beschriftet. |
| state "Beschriftung" as id | Lesbarer Text bei einer ID ohne Leerzeichen. |
| state A { ... } | Zusammengesetzter Zustand mit eigener Maschine. |
| -- | Teilt einen zusammengesetzten Zustand in nebenläufige Bereiche. |
| state x <<choice>> | Verzweigung anhand einer Bedingung. |
| state f <<fork>> / <<join>> | Aufteilen in und Zusammenführen aus parallelen Übergängen. |
| note right of A: Text | Notiz anhängen. Auch `note left of`. |
| direction LR | Die Maschine von links nach rechts statt von oben nach unten anordnen. |
Sechs Fehler in Zustandsdiagrammen
Nachgestellt mit Mermaid 11.12.2. Die ersten vier verhindern, dass das Diagramm gezeichnet wird. Die letzten beiden sind schlimmer: Sie rendern anstandslos und liefern ein Diagramm, das etwas anderes bedeutet, als du geschrieben hast.
Was du siehst
Parse error, endet mit: got 'INVALID'
Warum
Ein Bindestrich in einer Zustands-ID. Namen in Kebab-Schreibweise liegen nahe — in-pruefung, vor-freigabe —, aber der Bindestrich wird als Anfang eines Übergangspfeils gelesen.
Lösung
Für die ID ein Wort oder Unterstriche verwenden und den lesbaren Text in eine zitierte Beschriftung setzen.
stateDiagram-v2
[*] --> in-pruefung
in-pruefung --> FertigstateDiagram-v2
state "In Prüfung" as pruefung
[*] --> pruefung
pruefung --> FertigWas du siehst
Parse error innerhalb eines zusammengesetzten Zustands
Warum
Ein mit `{` geöffneter Zustand, der nie geschlossen wurde. Die schließende Klammer gehört auf eine eigene Zeile.
Lösung
Den Block schließen.
stateDiagram-v2
[*] --> Aussen
state Aussen {
[*] --> InnenstateDiagram-v2
[*] --> Aussen
state Aussen {
[*] --> Innen
}Was du siehst
Lexical error on line N. Unrecognized text.
Warum
Der Trenner für nebenläufige Bereiche mit der falschen Zahl an Bindestrichen. Es sind genau zwei, auf einer eigenen Zeile, innerhalb eines zusammengesetzten Zustands. Drei Bindestriche sind ein völlig anderes Token.
Lösung
Genau `--` verwenden.
stateDiagram-v2
state Beides {
[*] --> A
---
[*] --> B
}stateDiagram-v2
state Beides {
[*] --> A
--
[*] --> B
}Was du siehst
Parse error on line 1, endet mit: got 'ID'
Warum
Eine Versionsangabe, die es nicht gibt. Es existieren `stateDiagram` und `stateDiagram-v2`, sonst nichts — `-v3` scheitert schon in der ersten Zeile.
Lösung
`stateDiagram-v2` verwenden.
stateDiagram-v3
[*] --> EntwurfstateDiagram-v2
[*] --> EntwurfWas du siehst
Es rendert, aber aus einem Zustand sind still mehrere Kästchen geworden
Warum
Ein Leerzeichen in einer Zustands-ID. Mermaid weist das nicht zurück und liest den Rest auch nicht als Beschreibung — es erzeugt für jedes Wort ein eigenes Kästchen. Gemessen an den ausgegebenen state-IDs: Aus `[*] --> Wartet auf Pruefung` werden drei Zustände, `Wartet`, `auf` und `Pruefung`, von denen nur der erste am Pfeil hängt; die übrigen stehen unverbunden daneben. Das Diagramm wird dadurch still breiter. Die Beschreibung gibt es wirklich, sie braucht aber einen Doppelpunkt — `pruefung: wartet auf einen Prüfer` — und genau damit wird dieser Fehler verwechselt.
Lösung
Den Zustand mit `state "Beschriftung" as id` deklarieren und immer über die ID ansprechen.
stateDiagram-v2
[*] --> Wartet auf Pruefung
Wartet auf Pruefung --> FertigstateDiagram-v2
state "Wartet auf Prüfung" as pruefung
[*] --> pruefung
pruefung --> FertigWas du siehst
Es rendert, aber der Auswahlknoten wird als gewöhnlicher Zustand gezeichnet
Warum
Die `<<choice>>`-Deklaration kam nach den Übergängen, die sie benutzen. Mermaid legt den Zustand bei der ersten Erwähnung an, und ein späterer Stereotyp ändert nichts mehr an dem, was bereits existiert.
Lösung
Pseudozustände vor den Übergängen deklarieren, die sie verwenden.
stateDiagram-v2
[*] --> pruefung
pruefung --> Freigegeben
pruefung --> Abgelehnt
state pruefung <<choice>>stateDiagram-v2
state pruefung <<choice>>
[*] --> pruefung
pruefung --> Freigegeben
pruefung --> AbgelehntHinweise zum Rendern
Gemessen an Mermaid 11.12.2, so wie diese Seite es einsetzt.
Sowohl stateDiagram als auch stateDiagram-v2 rendern — und das ist eine Falle
Ein verbreiteter Ratschlag lautet, man müsse `stateDiagram-v2` verwenden, sonst werde nichts gezeichnet. In 11.12.2 stimmt das nicht: Beide Schlüsselwörter rendern fehlerfrei. Der Unterschied liegt in der Layout-Qualität, besonders bei zusammengesetzten und nebenläufigen Zuständen, und es gibt keine Warnung, wenn du die alte Variante benutzt. Wirkt ein zusammengesetzter Zustand gedrängt oder laufen die Pfeile seltsam, prüfe zuerst das Schlüsselwort, bevor du das Diagramm umbaust.
Die Höhe wächst um rund 108 px pro Zustand
Drei Zustände ergeben eine viewBox von etwa 52×462, vierzig Zustände 60×4680. Wie bei Flussdiagrammen bewegt sich die Breite kaum — Zustandsmaschinen wachsen nach unten. `direction LR` im Diagramm ist der übliche Ausweg, wenn ein Lebenszyklus lang, aber flach ist.
Zusammengesetzte Zustände werden eigenständig angeordnet
Die innere Maschine eines zusammengesetzten Zustands wird für sich bemessen und dann platziert. Deshalb kann ein einzelner großer Block das ganze Diagramm viel breiter machen, als die Zahl der Zustände vermuten lässt. Dominiert ein Kasten, liest es sich meist besser, seinen Inhalt auf die oberste Ebene zu holen und auf ein zweites Diagramm zu verweisen, statt gegen das Layout zu kämpfen.
Beschriftungen sind HTML, deshalb rendert der PNG-Export neu
Wie bei Fluss-, Klassen- und ER-Diagrammen stecken die Beschriftungen in einem SVG-`<foreignObject>`. Browser weigern sich, so etwas auf ein Canvas zu zeichnen, deshalb rendert der PNG-Export auf dieser Seite das Diagramm zuerst mit reinen SVG-Textbeschriftungen neu. Das PNG ist korrekt und in voller Größe; die Typografie weicht minimal vom Bildschirm ab.
Das Theme ändert Farben, niemals das Layout
Helles und dunkles Theme ergeben für dieselbe Quelle eine identische viewBox. Eine Zustandsmaschine kann beim Themewechsel also nicht umbrechen.
Wann etwas anderes besser passt
Sind deine Beschriftungen Tätigkeiten — prüfen, senden, wiederholen —, beschreibst du einen Prozess und keinen Lebenszyklus; dann ist ein Flussdiagramm die ehrliche Wahl. Das deutlichste Zeichen: Du kannst die Frage nicht beantworten, was denn eigentlich in diesem Zustand ist.
Haben mehrere Komponenten je einen eigenen Lebenszyklus und ist das Zusammenspiel das Interessante, schlägt ein Zustandsdiagramm pro Komponente plus ein Sequenzdiagramm für die Interaktion jede riesige Einzelmaschine.
Und wenn jeder Zustand mit jedem anderen verbunden ist, wird das Diagramm ein Knäuel, egal wie man es zeichnet. Das heißt meist, dass die Zustände gar keine Zustände sind, sondern frei kombinierbare Merkmale — dann sagt eine Tabelle der gültigen Kombinationen weit mehr als ein Bild.
Andere Diagrammtypen
Geschrieben von Dominik Malsch · Zuletzt aktualisiert: