状态图
“状态图是计算机科学和相关领域用来描述系统行为的一种图。状态图要求所描述的系统由有限数量的状态组成;有时,情况确实如此,而在其他时候,这是一个合理的抽象。维基百科
美人鱼可以渲染状态图。该语法尝试与plantUml中使用的语法兼容,因为这将使用户更容易在美人鱼和plantUml之间共享图表。
代码:
---
title: Simple sample
---
stateDiagram-v2
[*] --> Still
Still --> [*]
Still --> Moving
Moving --> Still
Moving --> Crash
Crash --> [*]
较旧的渲染器:
stateDiagram
[*] --> Still
Still --> [*]
Still --> Moving
Moving --> Still
Moving --> Crash
Crash --> [*]
在状态图中,系统是根据状态以及一个状态如何通过转换更改为另一个状态来描述的。上面的示例图显示了三种状态:静止、移动和崩溃。您从静止状态开始。从静止,您可以更改为“正在移动”状态。从“移动”中,您可以更改回“静止”状态或“崩溃”状态。没有从静止到崩溃的过渡。(如果你还在,你就不会崩溃。
状态
可以通过多种方式声明状态。最简单的方法是定义一个只用 id 的状态:
代码:
stateDiagram-v2
stateId
另一种方法是使用 state 关键字和如下描述:
代码:
stateDiagram-v2
state "This is a state description" as s2
使用描述定义状态的另一种方法是定义状态 id,后跟冒号和说明:
代码:
stateDiagram-v2
s2 : This is a state description
转换
转换是一个状态进入另一个状态时的路径/边。这使用文本箭头“-->”表示。
在两个状态之间定义转换并且尚未定义状态时,将使用转换中的 id 定义未定义的状态。稍后可以向以这种方式定义的状态添加说明。
代码:
stateDiagram-v2
s1 --> s2
可以在过渡中添加文本以描述其所代表的内容:
代码:
stateDiagram-v2
s1 --> s2: A transition
开始和结束
有两种特殊状态指示关系图的开始和停止。这些是用 [*] 语法编写的,过渡到它的方向将其定义为开始或停止状态。
stateDiagram-v2
[*] --> s1
s1 --> [*]
复合状态
在现实世界中使用状态图时,您通常会得到多维图,因为一个状态可以有多个内部状态。这些在此术语中称为复合状态。
为了定义复合状态,您需要使用 state 关键字,后跟 id 和 {} 之间的复合状态的主体。请参阅以下示例:
代码:
stateDiagram-v2
[*] --> First
state First {
[*] --> second
second --> [*]
}
您可以在多个层中执行此操作:
代码:
stateDiagram-v2
[*] --> First
state First {
[*] --> Second
state Second {
[*] --> second
second --> Third
state Third {
[*] --> third
third --> [*]
}
}
}
您还可以定义复合状态之间的转换:
代码:
stateDiagram-v2
[*] --> First
First --> Second
First --> Third
state First {
[*] --> fir
fir --> [*]
}
state Second {
[*] --> sec
sec --> [*]
}
state Third {
[*] --> thi
thi --> [*]
}
不能定义属于不同复合状态的内部状态之间的转换
选择
有时您需要在两条或多条路径之间进行建模,您可以使用 <<choice>> 来实现。
代码:
stateDiagram-v2
state if_state <<choice>>
[*] --> IsPositive
IsPositive --> if_state
if_state --> False: if n < 0
if_state --> True : if n >= 0
分叉
可以使用在逻辑示意图中指定分叉<<fork>><<join>>。
代码:
stateDiagram-v2
state fork_state <<fork>>
[*] --> fork_state
fork_state --> State2
fork_state --> State3
state join_state <<join>>
State2 --> join_state
State3 --> join_state
join_state --> State4
State4 --> [*]
笔记
有时没有什么比便利贴更能说明问题了。状态图中也是如此。
在这里,您可以选择将注释放在节点的右侧或左侧。
stateDiagram-v2
State1: The state with a note
note right of State1
Important information! You can write
notes.
end note
State1 --> State2
note left of State2 : This is the note to the left.
并发
与在 plantUml 中一样,您可以使用 -- 符号指定并发性。
代码:
stateDiagram-v2
[*] --> Active
state Active {
[*] --> NumLockOff
NumLockOff --> NumLockOn : EvNumLockPressed
NumLockOn --> NumLockOff : EvNumLockPressed
--
[*] --> CapsLockOff
CapsLockOff --> CapsLockOn : EvCapsLockPressed
CapsLockOn --> CapsLockOff : EvCapsLockPressed
--
[*] --> ScrollLockOff
ScrollLockOff --> ScrollLockOn : EvScrollLockPressed
ScrollLockOn --> ScrollLockOff : EvScrollLockPressed
}
设置图表的方向
对于状态图,您可以使用 direction 语句来设置图将呈现的方向,如本例所示。
代码:
stateDiagram
direction LR
[*] --> A
A --> B
B --> C
state B {
direction LR
a --> b
}
B --> D
注释
注释可以在状态图图表中输入,解析器将忽略该图表。注释需要位于其自己的行中,并且必须以 %%(双百分号)开头。注释开始到下一个换行符之后的任何文本都将被视为注释,包括任何图表语法
代码:
stateDiagram-v2
[*] --> Still
Still --> [*]
%% this is a comment
Still --> Moving
Moving --> Still %% another comment
Moving --> Crash
Crash --> [*]
使用 classDefs 进行样式设置
与其他关系图(如流程图)一样,您可以在关系图本身中定义样式,并将该命名样式应用于关系图中的一个或多个状态。
这些是状态图 classDefs 的当前限制:
- 不能应用于开始或结束状态
- 不能应用于复合状态或应用于复合状态
这些正在开发中,并将在未来版本中提供。
使用 classDef 关键字定义样式,该关键字是“类定义”的缩写(其中“class”表示类似于 CSS 类的内容),后跟样式的名称,然后是一个或多个属性值对。每个属性-值对都是一个有效的 CSS 属性名称,后跟一个冒号 (:)然后是一个值。
下面是只有一个属性-值对的 classDef 的示例:
classDef movement font-style:italic;
where
- 风格的名字是movement
- 唯一的属性是 font-style 并且它的值是 italic
如果您想要多个属性-值对,则可以在每个属性-值对之间放置一个逗号 (,)。
下面是一个包含三个属性-值对的示例:
classDef badBadEvent fill:#f00,color:white,font-weight:bold,stroke-width:2px,stroke:yellow
where
- 样式的名称是 badBadEvent
- 第一个属性是 fill ,其值为 #f00
- 第二个属性是颜色,其值为白色
- 第三个属性是font-weight,它的值是粗体
- 第四个属性是描边宽度,其值为2px
- 第五个属性是Stroke,其值为黄色
将 classDef 样式应用于状态
有两种方法可以将 classDef 样式应用于状态:
- 使用 class 关键字将 classDef 样式应用于单个语句中的一个或多个状态,或者
- 使用 ::: 运算符将 classDef 样式应用于转换语句中使用的状态(例如,使用箭头来回另一个状态)
1.class声明
类语句告诉美人鱼将命名的 classDef 应用于一个或多个类。形式是:
class [one or more state names, separated by commas] [name of a style defined with classDef]
下面是将 badBadEvent 样式应用于名为 Crash 的状态的示例:
class Crash badBadEvent
下面是将movement样式应用于两种状态“movement”和“Crash”的示例:
class Moving, Crash movement
下图显示了正在使用的示例。请注意,Crash状态应用了两种类定义样式:movement和badBadEvent
代码:
stateDiagram
direction TB
accTitle: This is the accessible title
accDescr: This is an accessible description
classDef notMoving fill:white
classDef movement font-style:italic
classDef badBadEvent fill:#f00,color:white,font-weight:bold,stroke-width:2px,stroke:yellow
[*]--> Still
Still --> [*]
Still --> Moving
Moving --> Still
Moving --> Crash
Crash --> [*]
class Still notMoving
class Moving, Crash movement
class Crash badBadEvent
class end badBadEvent
2. ::: 运算符,用于将样式应用于状态
您可以使用 ::: (三个冒号) 运算符将 classDef 样式应用于状态。语法是
[state]:::[style name]
您可以使用类在语句中的关系图中使用它。这包括开始和结束状态。例如:
stateDiagram
direction TB
accTitle: This is the accessible title
accDescr: This is an accessible description
classDef notMoving fill:white
classDef movement font-style:italic;
classDef badBadEvent fill:#f00,color:white,font-weight:bold,stroke-width:2px,stroke:yellow
[*] --> Still:::notMoving
Still --> [*]
Still --> Moving:::movement
Moving --> Still
Moving --> Crash:::movement
Crash:::badBadEvent --> [*]
为状态名称添加空格
您可以通过首先使用一个标识符定义某个状态,然后在稍后引用该标识符的方式,为状态名称添加空格。
在以下示例中,有一个带有标识符 yswsii 和描述为“在其中带有空格的您的状态”的状态。在对其进行定义后,yswsii 被用于图表中的第一个转换([*] --> yswsii),同时还在指向另一个状态 YetAnotherState 的转换中使用了 yswsii(yswsii --> YetAnotherState)。
(yswsii 的样式已进行设置,以便与其他状态区分开。)
代码:
stateDiagram
classDef yourState font-style:italic,font-weight:bold,fill:white
yswsii: Your state with spaces in it
[*] --> yswsii:::yourState
[*] --> SomeOtherState
SomeOtherState --> YetAnotherState
yswsii --> YetAnotherState
YetAnotherState --> [*]