Figma 甘特图与项目排期系统(Gantt Chart & Resource Scheduling Architecture)组件架构实战:从多级时间刻度标尺(Time Scale Header)、任务树与排期画布双向联动、依赖连线(Dependency Arrows)到 Variables 缩放状态机与 Dev Mode 前端代码交付
1. 业务痛点与甘特图排期系统架构挑战 #
在现代敏捷项目协同系统(如 Jira、Linear、Monday.com、ClickUp、飞书项目)以及企业资源计划(ERP)软件中,甘特图与项目排期系统(Gantt Chart & Resource Scheduling Architecture) 是工程研发管理、交付里程碑跟进和跨职能资源分配的最核心视图。
然而,在设计系统的搭建过程中,甘特图往往是让 UI/UX 设计师最头疼的“复杂度天花板”之一:
- 时间标尺缩放失控(Scale Distortion):设计师在日视图、周视图、月视图与季度视图切换时,常常采用手工硬编码的矩形拼凑,导致时间跨度与像素宽度不成正比,无法实现等比排期演算;
- 左侧任务树与右侧画布脱节(Vertical Alignment Desync):甘特图由左侧的任务分解结构(WBS,Work Breakdown Structure)树形列表和右侧的水平台阶画布组成,若两者没有严格绑定行高 Token 与统一的 Auto Layout 驱动模型,极易在任务折叠或高度变化时产生垂直错位;
- 任务依赖关系(Dependency Arrows)难以维护:传统流式布局无法表达“完成-开始(Finish-to-Start)”等跨行跨时间网格的依赖箭头,导致设计师要么纯手绘矢量线,一旦任务时间微调就全图崩塌;
- 进度与里程碑组件缺乏状态机:未能将常规任务条(Task Bar)、汇总群组条(Summary Bar)与里程碑节点(Milestone Diamond)解耦,缺乏基于 Figma Variables 的动态计算支持;
- 前端代码交付困难:未能将画布几何尺寸、列宽 Token、连线拐点逻辑与成熟 Web 甘特图框架(如 Frappe Gantt、DHTMLX Gantt、React Timeline)进行映射,导致工程开发返工成本极高。
一套工业级甘特图系统的标准架构拓扑如下所示:
┌─────────────────────────────────────────────────────────────────────────────┐
│ Gantt Chart Component Architecture Topology │
├─────────────────────────┬───────────────────────────────────────────────────┤
│ Left Panel: WBS Tree │ Right Panel: Time Scale Header & Virtual Canvas │
│ [Task Name | Assignee] │ Nov 10 Nov 11 Nov 12 Nov 13 Nov 14 Nov 15 │
├─────────────────────────┼───────────────────────────────────────────────────┤
│ ▼ Sprint 44 Project │ [==== Group Summary Task Bar =================] │
│ ├─ API Spec Design │ [==== Task A ====]──┐ (Finish-to-Start) │
│ ├─ Core Dev Work │ └──►[====== Task B ======] │
│ └─ QA Acceptance │ ◆ M-1 │
├─────────────────────────┼───────────────────────────────────────────────────┤
│ Fixed Row: 44px │ Today Marker (Vertical Red Dotted Line Overlay) │
└─────────────────────────┴───────────────────────────────────────────────────┘
结合站内 Figma Auto Layout 弹性自适应与流体布局深度实战 与 Figma 绝对定位(Absolute Positioning)与负间距实战,本文将深入拆解从原子任务条、正交依赖连线到 Variables 状态机的一整套工程化设计方案。
2. 双栏联动拓扑:左侧 WBS 任务树与右侧画布行高对齐 #
甘特图的核心布局骨架是典型的左右双栏结构。为了确保左侧的任务详情行与右侧的时间滑块行在垂直维度上永远保持像素级 1:1 对齐,必须在顶层实施统一的行高规范。
2.1 行高 Token 与对齐规范 #
必须制定标准化的行高尺寸阶梯,禁止任意行随意撑开:
- 紧凑型行高(Compact Row):
36px(适用于上百个微任务的精细项目甘特图); - 标准型行高(Default Row):
44px(容纳 24px 头像徽标、单行标题与状态标签的最佳体验); - 宽松型行高(Comfortable Row):
52px(适用于包含任务副标题、起止日期两行展示的看板)。
2.2 双分栏 Auto Layout 结构搭建 #
- 左侧固定面板(wbs-left-panel):
- 设置宽度固定(如
320px),高度设置为Fill container; - 内部包含表头
wbs-header(高度固定56px,对应右侧两层时间刻度的高)与垂直列表wbs-row-list(Auto Layout 垂直排列,间距为0); - 每一行
wbs-row高度锁定为44px,包含缩进导轨、折叠展开箭头、任务名称和负责人头像。关于层级缩进结构,可参考 Figma 树形控件与手风琴折叠面板实战。
- 设置宽度固定(如
- 右侧排期画布(gantt-right-canvas):
- 设置宽度为
Fill container(在桌面端自适应撑满,横向允许溢出滚动); - 顶部为时间标尺
time-scale-header(高度56px); - 下方为与左侧行列表 1:1 对齐的排期行容器
canvas-row-list,内部每一行canvas-row高度严格锁定为44px;
- 设置宽度为
- 行对齐保障:左右两侧的行使用相同的实例数组,确保左侧展开或折叠某个父任务时,右侧对应的排期行同步切换显隐状态。
3. 多维时间刻度标尺(Time Scale Header)与网格系统 #
甘特图右侧的时间标尺负责为整个画布建立时间坐标基准。根据项目周期的不同,通常需要在“日(Day)”、“周(Week)”、“月(Month)”与“季度(Quarter)”四种刻度模式间切换。
3.1 四大时间刻度网格参数对比 #
| 视图刻度 | 主表头(Top Tier) | 次表头(Sub Tier) | 单列基准宽度(Column Width) | 适用项目周期 |
|---|---|---|---|---|
| 日视图(Day) | 年-月(如 2026年11月) | 单日(1, 2, 3... 30) | 32px 或 40px | 1~2 周敏捷冲刺(Sprint) |
| 周视图(Week) | 年-月 | 第 N 周(W45, W46...) | 96px 或 120px | 1~3 个月季度迭代排期 |
| 月视图(Month) | 年份(2026) | 月份(1月, 2月... 12月) | 160px 或 200px | 半年到 1 年中长期规划 |
| 季度视图(Quarter) | 年份 | 季度(Q1, Q2, Q3, Q4) | 240px 或 300px | 2~3 年战略战略规划路线图 |
3.2 今日时间指示线(Today Marker)的绝对定位实现 #
在排期画布中,高亮指示“当前时间点(Today)”能极大提升用户对项目进度的感知:
- 创建一条垂直线图层
today-line,宽度为2px,设置为红色或主题强调色虚线(如#EF4444); - 顶部增加一个
today-badge倒三角或圆角气泡标签,标明“今天 (11月14日)”; - 将该组元素设为 绝对定位(Absolute Positioning),锚定在排期画布容器的最顶层;
- 利用 Figma Variables 的数字变量(如
var_today_offset_x = 480),通过变量控制其X坐标偏移,确保无论画布网格如何拉伸,今天线均能精准落在对应日期的网格交界处。
4. 任务条(Task Bar)与里程碑原子组件解耦 #
排期画布中的核心图元分为三类:普通任务条(Task Bar)、分组汇总条(Summary Task Bar)和关键里程碑(Milestone)。
1. Normal Task Bar:
┌───────────────────────┬──────────────┐
│ █ █ █ Complete 65% │ Remaining │ 👤 Alice
└───────────────────────┴──────────────┘
2. Group Summary Bar:
▲══════════════════════════════════════▲
3. Milestone:
◆ Launch v2.0 (Nov 20)
4.1 普通任务条(Task Bar)组件设计 #
- 外层容器:Auto Layout 水平 Frame,高度固定为
24px(在44px行高内垂直居中,上下各有10px呼吸留白); - 圆角与背景:圆角设为
4px或6px,背景为浅主题色(如#DBEAFE); - 进度填充轨(Progress Track):
- 内部嵌套子 Frame
progress-fill,背景设为深色主色(如#2563EB); - 勾选
Clip content,宽度绑定 Variables 变量或设置按比例填充,用于直观展示60%已完成进度;
- 内部嵌套子 Frame
- 左右拖拽手柄(Resize Handles):设置在任务条首尾两侧,平时隐藏,悬停时通过 Component Properties 切换显示,提示可按日调整任务起止周期;
- 尾部附加信息插槽:紧跟在任务条右侧的负责人微型头像与完成度百分比文字,配置为不挤压任务条本身的弹性伸缩结构。
4.2 汇总条(Summary Bar)与里程碑(Milestone) #
- 群组汇总条:用于反映整个父模块或史诗(Epic)的时间跨度,首尾两端带有向下的小三角折角(Bracket Ends),颜色采用沉稳的深石墨灰(
#334155); - 里程碑节点:使用一个
16px × 16px的正方形,旋转45°构成菱形(Diamond),填充警示色或金黄色(如#F59E0B),并在右侧附带无折行的时间节点标签。
有关组件属性的最佳实践,请进一步参阅 Figma 组件属性(Component Properties)企业级实战。
5. 跨任务依赖连线(Dependency Arrows)与正交导轨系统 #
甘特图的一大精髓是任务之间的先后依赖逻辑。常见依赖包含四种:
- 完成-开始(FS: Finish-to-Start):任务 A 完成后,任务 B 才能开始(最常见模式,占 90% 以上);
- 开始-开始(SS: Start-to-Start):任务 A 启动的同时,任务 B 必须协同启动;
- 完成-完成(FF: Finish-to-Finish):任务 A 结束时,任务 B 必须同时结束;
- 开始-完成(SF: Start-to-Finish):任务 A 启动后,任务 B 才能结束。
5.1 正交折线(Orthogonal Path)与绝对定位架构 #
在 Figma 中,由于依赖线跨越了两个独立的 Auto Layout 行,不能直接放入行内部。标准的实现方案为:
- 在右侧画布层创建一个名为
dependency-overlay的绝对定位透明 Frame,覆盖在所有任务行之上,尺寸与画布完全重合; - 绘制标准的 正交折线(Z-shape 或 L-shape Connector):
- 起点:从任务 A 的右边缘中心引出,水平延伸
12px; - 拐角:垂直折向任务 B 所在的行高度;
- 终点:水平延伸并带有一个
6px的实心三角形箭头,指向任务 B 的左边缘;
- 起点:从任务 A 的右边缘中心引出,水平延伸
- 将折线样式抽离为组件
component/dependency-link,并通过属性控制线型:- 普通依赖:
1.5px浅灰实线(#94A3B8); - 关键路径(Critical Path):
2px红色高亮实线(#EF4444),标明任何延误都会导致最终工期推迟的核心任务链; - 冲突警告(Conflict Link):橙色虚线配警告图标,提示任务排期前后倒置。
- 普通依赖:
6. 基于 Figma Variables 的视图缩放与交互状态机 #
利用 Figma Variables 的模式(Modes)和数值变量,可以实现不用复制多个画板就能一键无缝切换日、周、月视图的高保真甘特图。
6.1 核心 Variables 变量表定义 #
| 变量名称(Variable Name) | 类型(Type) | Day 模式值 | Week 模式值 | Month 模式值 | 作用描述 |
|---|---|---|---|---|---|
gantt/col-width | Number | 36 | 120 | 200 | 驱动时间网格每一列的像素宽度 |
gantt/sub-header-text | String | "14" | "W46" | "11月" | 次表头显示的时间维度文字 |
gantt/task-a-start-col | Number | 4 | 1 | 0 | 任务 A 在当前时间刻度下的起始列数 |
gantt/task-a-span-cols | Number | 5 | 2 | 1 | 任务 A 所跨越的列单元格总数 |
gantt/show-critical-path | Boolean | false | false | true | 是否高亮显示关键路径连线 |
6.2 动态计算任务宽度与偏移 #
在 Figma 变量绑定中:
- 将任务条的宽度绑定为公式计算或者直接在不同模式下指定对应宽度;
- 在画板顶层通过切换 Variable Mode,整个甘特图的时间网格自动重新分布,任务条和时间指示线平滑位移,大幅减少维护成本。详细变量配置机制可查阅 设计系统 Design Tokens 规范速查。
7. Dev Mode 现代前端交付与 React / Tailwind CSS 映射 #
在 Figma Dev Mode 下,前端开发能够直接读取甘特图的栅格数据,并与 Web 生态成熟的甘特图开源方案(如 Frappe Gantt 或自研基于 CSS Grid 的排期器)无缝对接。
以下是高度契合 Figma 组件架构的现代 React + Tailwind CSS 生产级实现参考:
import React, { useState } from 'react';
interface GanttTask {
id: string;
name: string;
assignee: string;
startDay: number; // 相对于项目第 0 天的偏移量
durationDays: number;
progress: number; // 0 ~ 100
isMilestone?: boolean;
}
const COLUMN_WIDTH_PX = 36; // 对应 Figma 中 Day 模式的 col-width Token
const ROW_HEIGHT_PX = 44; // 对应 Figma 44px 标准行高
const SAMPLE_TASKS: GanttTask[] = [
{ id: 't1', name: '需求与架构评审', assignee: '张工', startDay: 1, durationDays: 4, progress: 100 },
{ id: 't2', name: '核心 API 服务开发', assignee: '李工', startDay: 5, durationDays: 7, progress: 65 },
{ id: 't3', name: '前端甘特图组件集成', assignee: '王工', startDay: 8, durationDays: 6, progress: 30 },
{ id: 't4', name: '灰度发布里程碑', assignee: '全体', startDay: 15, durationDays: 1, progress: 0, isMilestone: true },
];
export const EnterpriseGanttChart: React.FC = () => {
const [tasks] = useState<GanttTask[]>(SAMPLE_TASKS);
const totalDays = 20;
return (
<div className="flex border border-gray-200 rounded-lg overflow-hidden bg-white shadow-sm">
{/* 1. 左侧 WBS 任务结构树面板 */}
<div className="w-72 flex-shrink-0 border-r border-gray-200 bg-gray-50 flex flex-col">
<div className="h-14 border-b border-gray-200 px-4 flex items-center font-semibold text-gray-700 text-sm">
任务名称与执行人
</div>
<div className="flex flex-col">
{tasks.map((task) => (
<div
key={task.id}
className="px-4 border-b border-gray-100 flex items-center justify-between text-sm hover:bg-gray-100/60 transition-colors"
style={{ height: `${ROW_HEIGHT_PX}px` }}
>
<span className="truncate font-medium text-gray-800">{task.name}</span>
<span className="text-xs text-gray-500 bg-gray-200/80 px-2 py-0.5 rounded-full">{task.assignee}</span>
</div>
))}
</div>
</div>
{/* 2. 右侧时间轴与排期画布面板 */}
<div className="flex-1 overflow-x-auto relative">
{/* 时间刻度表头 */}
<div className="h-14 border-b border-gray-200 bg-gray-50 flex">
{Array.from({ length: totalDays }).map((_, i) => (
<div
key={i}
className="flex-shrink-0 border-r border-gray-200 text-center flex flex-col justify-center text-xs text-gray-600 font-mono"
style={{ width: `${COLUMN_WIDTH_PX}px` }}
>
<span className="text-[10px] text-gray-400">D</span>
<span>{i + 1}</span>
</div>
))}
</div>
{/* 今日红色基准标线(Today Marker) */}
<div
className="absolute top-0 bottom-0 border-l-2 border-red-500 border-dashed z-20 pointer-events-none"
style={{ left: `${8 * COLUMN_WIDTH_PX + COLUMN_WIDTH_PX / 2}px` }}
>
<span className="bg-red-500 text-white text-[10px] px-1.5 py-0.5 rounded shadow absolute -top-1 -translate-x-1/2">
今日
</span>
</div>
{/* 任务排期行容器 */}
<div className="relative">
{/* 背景纵向时间网格线 */}
<div className="absolute inset-0 flex pointer-events-none">
{Array.from({ length: totalDays }).map((_, i) => (
<div
key={i}
className="flex-shrink-0 border-r border-gray-100 h-full"
style={{ width: `${COLUMN_WIDTH_PX}px` }}
/>
))}
</div>
{/* 任务条与里程碑渲染 */}
{tasks.map((task) => (
<div
key={task.id}
className="relative border-b border-gray-100 flex items-center"
style={{ height: `${ROW_HEIGHT_PX}px` }}
>
{task.isMilestone ? (
/* 里程碑菱形节点 */
<div
className="absolute z-10 flex items-center gap-1.5"
style={{ left: `${task.startDay * COLUMN_WIDTH_PX}px` }}
>
<div className="w-4 h-4 bg-amber-500 rotate-45 shadow-sm rounded-sm" />
<span className="text-xs font-semibold text-amber-700 whitespace-nowrap">{task.name}</span>
</div>
) : (
/* 常规任务条(含完成度进度条) */
<div
className="absolute z-10 h-6 bg-blue-100 rounded border border-blue-300 overflow-hidden shadow-sm group hover:ring-2 hover:ring-blue-400 transition-all cursor-pointer"
style={{
left: `${task.startDay * COLUMN_WIDTH_PX}px`,
width: `${task.durationDays * COLUMN_WIDTH_PX}px`,
}}
>
{/* 进度条填充 */}
<div
className="h-full bg-blue-600 transition-all"
style={{ width: `${task.progress}%` }}
/>
<span className="absolute inset-0 flex items-center px-2 text-[11px] font-medium text-gray-800 drop-shadow-sm select-none">
{task.progress}%
</span>
</div>
)}
</div>
))}
</div>
</div>
</div>
);
};
8. 甘特图排期系统综合对比与选型决策 #
在选择甘特图呈现模式与设计系统规格时,应结合具体业务的敏捷周期与数据密度进行权衡:
| 评估维度 | 敏捷研发冲刺甘特图(Sprint Gantt) | 跨年大型工程交付甘特图(Enterprise Plan) | 资源负载排班视图(Resource Allocation) |
|---|---|---|---|
| 主流时间标尺 | 日(Day)/ 双日 | 周(Week)/ 月(Month)/ 季度 | 半天 / 工作日日历单元 |
| 行高与信息密度 | 44px(含任务名、负责人头像) | 32px ~ 36px(追求一屏呈现更多节点) | 56px(含人员饱和度百分比柱状图) |
| 依赖关系复杂度 | 中等(主要为顺序 FS 依赖) | 极高(网络状交叉依赖,需关键路径算法) | 较低(以人为主线,很少跨任务强依赖) |
| 里程碑重要程度 | 标定 Sprint 交付或上线时刻 | 标定甲乙方阶段验收与付款节点(高价值) | 标定项目封板或人员调配窗口 |
| 交互核心 | 拖拽调整工期、左右滑动进度百分比 | 视图缩放切换、关键路径高亮过滤 | 跨人员拖拽转派任务、工时超载告警 |
通过统一的左右双栏 Auto Layout 拓扑、精确的列宽与行高 Token、解耦的任务条与里程碑原子、正交依赖连线以及基于 Figma Variables 的时间刻度切换,设计团队可以构建出既灵活美观、又严谨契合前端工程化落地的高韧性甘特图设计系统。想要进一步了解代码化交付,可继续阅读 Figma to Code 生产级代码转换深度实战 与 Figma 复杂数据表格系统架构实战。
核心手册与速查工具
高频手册与实用设计生产力工具直达常见问题与答疑 (FAQ)
高频疑难解析与避坑指南完全不需要。绝大多数核心功能在免费 Starter 计划中均可完整体验与实操练习,无需额外付费购买付费团队版。