甘特图
甘特图是一种条形图,由卡罗尔·阿达米奇 (Karol Adamiecki) 于 1896 年首次开发,并由亨利·甘特 (Henry Gantt) 于 1910 年代独立开发,它展示了项目时间表和完成任何一个项目所需的时间。甘特图说明了项目终端元素和汇总元素的开始日期和结束日期之间的天数。
给用户的一则说明
甘特图将记录每个计划的任务作为一条从左到右延伸的连续条形。X 轴表示时间,Y 轴记录不同的任务以及完成它们的顺序。
重要的是要记住,当与任务相关的特定日期、天或日期集合被“排除”时,甘特图将通过向右扩展相同的天数来适应这些更改,而不是在任务内部创建间隙。如这里所示
但是,如果排除的日期介于两个设置为连续开始的任务之间,则将跳过图形中的排除日期并留空,而下一个任务将在排除日期结束之后开始。如这里所示
甘特图对于跟踪完成项目之前需要花费的时间很有用,但它也可以通过一些调整来以图形方式表示“非工作日”。
Mermaid 可以将甘特图渲染为 SVG、PNG 或 Markdown 链接,这些链接可以粘贴到文档中。
语法
默认情况下,任务是按顺序排列的。任务的开始日期默认为前一个任务的结束日期。
冒号 (:
) 将任务标题与其元数据隔开。元数据项用逗号 (,
) 隔开。有效的标签是 active
、done
、crit
和 milestone
。标签是可选的,但如果使用,则必须首先指定它们。在处理完标签后,剩余的元数据项将按以下方式解释
- 如果指定了一个项目,它将确定任务何时结束。它可以是特定的日期/时间或持续时间。如果指定了持续时间,它将添加到任务的开始日期以确定任务的结束日期,并考虑任何排除。
- 如果指定了两个项目,则最后一个项目将按前一种情况解释。第一个项目可以指定一个明确的开始日期/时间(以
dateFormat
指定的格式)或使用after <otherTaskID> [[otherTaskID2 [otherTaskID3]]...]
引用另一个任务。在后一种情况下,任务的开始日期将根据任何引用任务的最新结束日期设置。 - 如果指定了三个项目,则最后两个将按前一种情况解释。第一个项目将表示任务的 ID,可以使用
later <taskID>
语法引用它。
元数据语法 | 开始日期 | 结束日期 | ID |
---|---|---|---|
<taskID>, <startDate>, <endDate> | 使用 dateformat 解释的 startdate | 使用 dateformat 解释的 endDate | taskID |
<taskID>, <startDate>, <length> | 使用 dateformat 解释的 startdate | 开始日期 + length | taskID |
<taskID>, after <otherTaskId>, <endDate> | 先前指定的任务 otherTaskID 的结束日期 | 使用 dateformat 解释的 endDate | taskID |
<taskID>, after <otherTaskId>, <length> | 先前指定的任务 otherTaskID 的结束日期 | 开始日期 + length | taskID |
<taskID>, <startDate>, until <otherTaskId> | 使用 dateformat 解释的 startdate | 先前指定的任务 otherTaskID 的开始日期 | taskID |
<taskID>, after <otherTaskId>, until <otherTaskId> | 先前指定的任务 otherTaskID 的结束日期 | 先前指定的任务 otherTaskID 的开始日期 | taskID |
<startDate>, <endDate> | 使用 dateformat 解释的 startdate | 使用 dateformat 解释的 enddate | n/a |
<startDate>, <length> | 使用 dateformat 解释的 startdate | 开始日期 + length | n/a |
after <otherTaskID>, <endDate> | 先前指定的任务 otherTaskID 的结束日期 | 使用 dateformat 解释的 enddate | n/a |
after <otherTaskID>, <length> | 先前指定的任务 otherTaskID 的结束日期 | 开始日期 + length | n/a |
<startDate>, until <otherTaskId> | 使用 dateformat 解释的 startdate | 先前指定的任务 otherTaskID 的开始日期 | n/a |
after <otherTaskID>, until <otherTaskId> | 先前指定的任务 otherTaskID 的结束日期 | 先前指定的任务 otherTaskID 的开始日期 | n/a |
<endDate> | 前一个任务的结束日期 | 使用 dateformat 解释的 enddate | n/a |
<length> | 前一个任务的结束日期 | 开始日期 + length | n/a |
until <otherTaskId> | 前一个任务的结束日期 | 先前指定的任务 otherTaskID 的开始日期 | n/a |
信息
对关键字 until
的支持已在 (v10.9.0+) 中添加。这可用于定义一个任务,该任务运行到某个其他特定任务或里程碑开始时。
为简单起见,该表不显示使用 after
关键字列出的多个任务。以下是如何使用它以及如何解释它的示例
标题
title
是一个可选字符串,用于显示在甘特图顶部以描述整个图表。
排除
excludes
是一个可选属性,它接受以 YYYY-MM-DD 格式表示的特定日期、星期几(“星期日”)或“周末”,但不接受单词“工作日”。这些日期将在图形上标记,并将从任务的持续时间计算中排除。这意味着,如果在任务间隔期间存在排除日期,则将添加 '跳过' 天数以确保持续时间与代码中指定的持续时间相同。
周末 (v\11.0.0+)
在排除周末时,可以将周末配置为星期五和星期六或星期六和星期日。默认情况下,周末是星期六和星期日。要定义周末开始日,可以添加一个可选属性 weekend
,在新的行中加上 friday
或 saturday
。
节段语句
您可以将图表划分为多个节段,例如将项目的不同部分(如开发和文档)分开。
为此,请以 section
关键字开头一行,并为它指定一个名称。(请注意,与整个图表的标题不同,此名称是必需的)。
里程碑
您可以在图表中添加里程碑。里程碑与任务不同,因为它们表示时间中的单个瞬间,并由关键字 milestone
标识。以下是如何使用里程碑的示例。正如您可能注意到的,里程碑的确切位置由里程碑的初始日期和任务的“持续时间”决定,方法如下:初始日期+持续时间/2。
设置日期
dateFormat
定义了甘特图元素的日期输入格式。这些日期如何在渲染后的图表输出中表示由 axisFormat
定义。
输入日期格式
默认的输入日期格式为 YYYY-MM-DD
。您可以定义自己的自定义 dateFormat
。
dateFormat YYYY-MM-DD
支持以下格式选项
输入 | 示例 | 描述 |
---|---|---|
YYYY | 2014 | 4 位年份 |
YY | 14 | 2 位年份 |
Q | 1..4 | 季度。将月份设置为季度的第一个月。 |
M MM | 1..12 | 月份编号 |
MMM MMMM | 一月...十二月 | 由 dayjs.locale() 设置的语言环境中的月份名称 |
D DD | 1..31 | 月份中的日期 |
Do | 1st...31st | 带有序数的月份中的日期 |
DDD DDDD | 1..365 | 一年中的日期 |
X | 1410715640.579 | Unix 时间戳 |
x | 1410715640579 | Unix 毫秒时间戳 |
H HH | 0..23 | 24 小时制时间 |
h hh | 1..12 | 与 a A 一起使用的 12 小时制时间。 |
a A | 上午 下午 | 午后或午前 |
m mm | 0..59 | 分钟 |
s ss | 0..59 | 秒 |
S | 0..9 | 十分之一秒 |
SS | 0..99 | 百分之一秒 |
SSS | 0..999 | 千分之一秒 |
Z ZZ | +12:00 | 与 UTC 的偏移量,以 +-HH:mm、+-HHmm 或 Z 表示 |
更多信息:https://day.js.cn/docs/en/parse/string-format/
轴上的输出日期格式
默认的输出日期格式是YYYY-MM-DD
。您可以定义自定义的axisFormat
,例如2020-Q1
表示2020年的第一季度。
axisFormat %Y-%m-%d
支持以下格式字符串
格式 | 定义 |
---|---|
%a | 缩写的星期名称 |
%A | 完整的星期名称 |
%b | 缩写的月份名称 |
%B | 完整的月份名称 |
%c | 日期和时间,如 "%a %b %e %H:%M:%S %Y" |
%d | 用零填充的月份中的天数,用十进制表示 [01,31] |
%e | 用空格填充的月份中的天数,用十进制表示 [ 1,31];等同于 %_d |
%H | 小时(24 小时制),用十进制表示 [00,23] |
%I | 小时(12 小时制),用十进制表示 [01,12] |
%j | 一年中的天数,用十进制表示 [001,366] |
%m | 月份,用十进制表示 [01,12] |
%M | 分钟,用十进制表示 [00,59] |
%L | 毫秒,用十进制表示 [000, 999] |
%p | AM 或 PM |
%S | 秒,用十进制表示 [00,61] |
%U | 一年中的星期数(以星期日为一周的第一天),用十进制表示 [00,53] |
%w | 星期几,用十进制表示 [0(星期日),6] |
%W | 一年中的星期数(以星期一为一周的第一天),用十进制表示 [00,53] |
%x | 日期,如 "%m/%d/%Y" |
%X | 时间,如 "%H:%M:%S" |
%y | 不带世纪的年份,用十进制表示 [00,99] |
%Y | 带世纪的年份,用十进制表示 |
%Z | 时区偏移量,例如 "-0700" |
%% | 字面上的 "%" 字符 |
更多信息请参阅:https://github.com/d3/d3-time-format/tree/v4.0.0#locale_format
轴刻度(v10.3.0+)
默认的输出刻度是自动的。您可以自定义tickInterval
,例如1day
或1week
。
tickInterval 1day
模式为
/^([1-9][0-9]*)(millisecond|second|minute|hour|day|week|month)$/;
更多信息请参阅:https://github.com/d3/d3-time#interval_every
基于星期的tickInterval
默认情况下将星期从星期日开始。如果您希望指定另一个星期几作为tickInterval
的开始,请使用weekday
选项
警告
millisecond
和 second
支持是在 v10.3.0 中添加的
以紧凑模式输出
紧凑模式允许您在同一行中显示多个任务。通过在前面的 YAML 设置中设置图表显示模式,可以为甘特图启用紧凑模式。
注释
可以在甘特图中输入注释,解析器将忽略这些注释。注释必须位于它们自己的行上,并且必须以%%
(双百分号)开头。从注释开始到下一行换行符之间的任何文本都将被视为注释,包括任何图表语法。
样式
甘特图的样式通过定义一些 CSS 类来完成。在渲染过程中,这些类是从位于 src/diagrams/gantt/styles.js 的文件中提取的。
使用的类
类 | 描述 |
---|---|
grid.tick | 网格线的样式 |
grid.path | 网格边框的样式 |
.taskText | 任务文本样式 |
.taskTextOutsideRight | 超出活动条向右的文字的样式。 |
.taskTextOutsideLeft | 超出活动条向左的文字的样式。 |
todayMarker | 切换和样式为 "Today Marker" |
示例样式表
.grid .tick {
stroke: lightgrey;
opacity: 0.3;
shape-rendering: crispEdges;
}
.grid path {
stroke-width: 0;
}
#tag {
color: white;
background: #fa283d;
width: 150px;
position: absolute;
display: none;
padding: 3px 6px;
margin-left: -80px;
font-size: 11px;
}
#tag:before {
border: solid transparent;
content: ' ';
height: 0;
left: 50%;
margin-left: -5px;
position: absolute;
width: 0;
border-width: 10px;
border-bottom-color: #fa283d;
top: -20px;
}
.taskText {
fill: white;
text-anchor: middle;
}
.taskTextOutsideRight {
fill: black;
text-anchor: start;
}
.taskTextOutsideLeft {
fill: black;
text-anchor: end;
}
今日标记
您可以对当前日期的标记进行样式设置或隐藏它。要对它进行样式设置,请为todayMarker
键添加一个值。
todayMarker stroke-width:5px,stroke:#0f0,opacity:0.5
要隐藏标记,请将todayMarker
设置为off
。
todayMarker off
配置
可以调整渲染甘特图的边距。
这可以通过定义配置对象的ganttConfig
部分来实现。如何在 mermaidCLI 页面中使用 CLI。
mermaid.ganttConfig
可以设置为带有配置参数的 JSON 字符串或相应的对象。
mermaid.ganttConfig = {
titleTopMargin: 25, // Margin top for the text over the diagram
barHeight: 20, // The height of the bars in the graph
barGap: 4, // The margin between the different activities in the gantt diagram
topPadding: 75, // Margin between title and gantt diagram and between axis and gantt diagram.
rightPadding: 75, // The space allocated for the section name to the right of the activities
leftPadding: 75, // The space allocated for the section name to the left of the activities
gridLineStartPadding: 10, // Vertical starting position of the grid lines
fontSize: 12, // Font size
sectionFontSize: 24, // Font size for sections
numberSectionStyles: 1, // The number of alternating section styles
axisFormat: '%d/%m', // Date/time format of the axis
tickInterval: '1 week', // Axis ticks
topAxis: true, // When this flag is set, date labels will be added to the top of the chart
displayMode: 'compact', // Turns compact mode on
weekday: 'sunday', // On which day a week-based interval should start
};
可能的配置参数:
参数 | 描述 | 默认值 |
---|---|---|
mirrorActor | 打开/关闭在图表下方以及上方渲染参与者 | false |
bottomMarginAdj | 调整图表结束的位置。使用 css 的宽边框样式可能会导致不需要的裁剪,这就是为什么存在此配置参数的原因。 | 1 |
交互
可以将单击事件绑定到任务。单击可以导致 JavaScript 回调或在当前浏览器选项卡中打开的链接。注意:使用securityLevel='strict'
时此功能将被禁用,使用securityLevel='loose'
时此功能将被启用。
click taskId call callback(arguments)
click taskId href URL
- taskId 是任务的 ID
- callback 是在显示图表的页面上定义的 JavaScript 函数的名称,如果未指定其他参数,则该函数将使用 taskId 作为参数被调用。
初学者提示 - 在 html 上下文中使用交互式链接的完整示例
<body>
<pre class="mermaid">
gantt
dateFormat YYYY-MM-DD
section Clickable
Visit mermaidjs :active, cl1, 2014-01-07, 3d
Print arguments :cl2, after cl1, 3d
Print task :cl3, after cl2, 3d
click cl1 href "https://mermaidjs.github.io/"
click cl2 call printArguments("test1", "test2", test3)
click cl3 call printTask()
</pre>
<script>
const printArguments = function (arg1, arg2, arg3) {
alert('printArguments called with arguments: ' + arg1 + ', ' + arg2 + ', ' + arg3);
};
const printTask = function (taskId) {
alert('taskId: ' + taskId);
};
const config = {
startOnLoad: true,
securityLevel: 'loose',
};
mermaid.initialize(config);
</script>
</body>