样式与扩展
定制应从成本最低、契约最稳定的入口开始:先调整主题令牌与尺寸,再使用 Resolver 修改几何和算法,只有业务结构确实不同才替换 Slot、Render Prop 或 Builder。这样能最大限度保留虚拟化、拖放与无障碍行为。
选择扩展层级
| 目标 | 推荐入口 | 保留的内置能力 |
|---|---|---|
| 颜色、圆角、行高、任务条高度 | 主题令牌与尺寸参数 | 全部 |
| 按任务决定宽高、纹理或依赖线样式 | Layout / Style / Effect Resolver | 几何、交互与虚拟化 |
| 自定义财务周、班次或不等宽时间格 | Timeline Resolver | 坐标转换、吸附与聚焦 |
| 替换任务内容或宿主业务控件 | Slot / Render Prop / Builder | 可见窗口与事件协议 |
自定义入口应保持纯计算或轻量渲染。不要在每个可见任务中创建独立观察器、复杂滤镜或不受预算限制的持续动画。
Vue 插槽
组件开放表头、任务信息、负责人、进度、任务条、纹理层、动效层、依赖线、空状态、工具条和行级边缘按钮插槽。
<YgGantt :tasks="tasks">
<template #bar="{ task, progress }">
<MyTaskBar :task="task" :progress="progress" />
</template>
<template #edge-indicator="{ task, side, jump }">
<button type="button" @click="jump">
{{ side === 'left' ? '←' : '→' }} {{ task.title }}
</button>
</template>
</YgGantt>barLayoutResolver 可以按任务、维度与几何结果修改任务条高度、最小宽度和圆角。dependencyPathResolver、dependencyStyleResolver 可接管依赖线路径与样式。
自定义时间维度与表头
IMPORTANT
本节 Resolver API 已进入 Core alpha.2、Vue alpha.5、React alpha.1 源码候选版。当前 npm alpha 标签尚未包含它们,以发布与兼容性页面的 Registry 版本为准。
Web 端把时间轴定制拆成两个层级,避免为了改一个标题复制整套日期算法:
timelineLabelResolver只替换上下两层表头文字,适合财务周、冲刺编号、班次和本地化。timelineResolver接收 Core 生成的defaultTimeline,可以替换时间格、分组、宽度或完整模型,适合 4-4-5 财务日历、生产班次和企业专用周期。
只修改内置维度的表头:
const timelineLabelResolver: TimelineLabelResolver = ({
view,
tier,
cell,
defaultLabel,
}) => {
if (view === 'week' && tier === 'upper') {
return `Sprint · ${defaultLabel}`
}
if (view === 'week' && tier === 'lower') {
return `${cell.start.getMonth() + 1}/${cell.start.getDate()}`
}
return defaultLabel
}定义专用时间格:
const timelineResolver: TimelineResolver = ({ view, defaultTimeline }) => {
if (view !== 'week') return defaultTimeline
let x = 0
const cells = defaultTimeline.cells.map((cell) => {
const width = cell.weekend ? 36 : 88
const next = { ...cell, x, width }
x += width
return next
})
return { cells, width: x }
}当 Resolver 只返回 cells 时,Core 会按日期交集重新计算上层分组的 x 和 width;如果你的分组语义也不同,可以同时返回 upperCells。dateToX、xToDate、拖放吸附、边缘跳转和自动定位都会使用解析后的模型。
<YgGantt
:tasks="tasks"
:timeline-resolver="timelineResolver"
:timeline-label-resolver="timelineLabelResolver"
/><YgGantt
tasks={tasks}
timelineResolver={timelineResolver}
timelineLabelResolver={timelineLabelResolver}
/>如果宿主需要一个不出现在内置六档切换器中的专用维度,可以关闭 showToolbar,在宿主工具栏里维护当前模式,并让 timelineResolver 根据该模式返回对应模型。这样不会扩大 ViewPresetId,联动协议仍然保持稳定。
React Render Props
<YgGantt
tasks={tasks}
renderBar={({ task, progress, selected }) => (
<TaskBar task={task} progress={progress} selected={selected} />
)}
renderEdgeIndicator={({ task, side, jump }) => (
<button type="button" onClick={jump}>{side} · {task.title}</button>
)}
/>renderDependency 可替换完整 SVG 路径;renderTask、renderOwner、renderProgress 可接入宿主任务表组件。
Flutter Builder
YotsubaGantt(
tasks: tasks,
taskBarBuilder: (context, details) {
return ColoredBox(
color: details.task.color ?? Colors.green,
child: Text(details.task.title),
);
},
rowHeaderBuilder: (context, task, rowIndex) {
return ListTile(dense: true, title: Text(task.title));
},
entryTransitionBuilder: (context, child, animation) {
return FadeTransition(opacity: animation, child: child);
},
edgeIndicatorBuilder: (context, details) {
return IconButton(
onPressed: details.jump,
icon: Icon(details.side == YgEdgeSide.left
? Icons.chevron_left
: Icons.chevron_right),
);
},
)默认动效只使用 transform、opacity 或描边偏移,并受视口预算控制。宿主可以关闭内置过渡,或通过插槽、Builder 和 CSS 自行实现效果。
