addTaskLayer
此功能仅在 PRO 版中可用。
Description
在时间线区域为任务显示一个带自定义元素的附加图层
addTaskLayer: (func: AdditionalTaskLayer['TaskLayerRender'] | AdditionalTaskLayer['TaskLayerConfig']) => string
Parameters
func- (required) TaskLayerRender | TaskLayerConfig - 一个渲染函数或配置对象
Returns
layerId- (string) - 将在图层中显示的 DOM 元素
Example
gantt.init("gantt_here");
gantt.addTaskLayer((task) => {
if (task.deadline) {
const el = document.createElement("div");
el.className = "deadline";
const sizes = gantt.getTaskPosition(task, task.deadline);
el.style.left = `${sizes.left}px`;
el.style.top = `${sizes.top}px`;
el.setAttribute("title", gantt.templates.task_date(task.deadline));
return el;
}
return false;
});
Details
参数可以是以下类型之一:
-
taskLayerRender (task, timeline, config, viewport): HTMLElement|boolean|void - 一个函数,接收任务对象作为参数,且必须返回将在图层中显示的 DOM 元素。
- task - (Task) - 任务对象
- timeline? - (any) - 时间线视图
- config? - (GanttConfigOptions) - Gantt 配置对象
- viewport? - (LayerViewport) - 视口对象
-
taskLayerConfig - (object) - 附加任务层的配置对象。具有以下属性:
- id? - (string | number) - 可选,图层 ID
- renderer - (object) - 必填,负责渲染图层元素的函数
- render - (TaskLayerRender) - 返回应渲染的 HTML 元素的函数
- update? - (Function): void - 可选,可在其中更新已渲染的 HTML 元素
- task - (Task) - 任务对象
- node - (HTMLElement) - 渲染节点的容器
- timeline? - (any) - 时间线视图
- config? - (GanttConfigOptions) - Gantt 配置对象
- viewport? - (LayerViewport) - 视口对象
- onrender? - (Function): void - 可选,在渲染完成后调用此函数。可以用来渲染原生组件(例如,使用 ReactDOM.render 方法)
- task - (Task) - 任务对象
- node - (HTMLElement) - 渲染节点的容器
- view? - (any) - 添加图层的布局单元(默认是 timeline)
- getRectangle? - (Function): { left: number, top: number, height: number, width: number } | void - 可选,返回自定义元素的坐标的函数
- task - (Task) - 任务对象
- view? - (any) - 添加图层的布局单元(默认是 timeline)
- config? - (GanttConfigOptions) - Gantt 配置对象
- gantt? - (GanttStatic) - Gantt 对象
- getVisibleRange - (Function): {start: number, end: number} | undefined | void - 返回可见范围对象的函数
- gantt? - (GanttStatic) - Gantt 对象
- view? - (any) - 添加图层的布局单元(默认是 timeline)
- config? - (GanttConfigOptions) - Gantt 配置对象
- datastore? - (any) - 任务数据存储对象
- viewport? - (LayerViewport) - 视口对象
- container? - (HTMLElement) - 可选,图层的容器
- topmost? - (boolean) - 可选,如果为 true,元素将显示在任务之上
- filter? - (Function): boolean - 可选,一个接收任务对象作为参数的函数。如果返回 'false',将不会为该任务调用 renderer 函数
- task - (Task) - 任务对象
图层视口具有以下属性:
-
viewport - (object) - 图层视口对象
- x - (number) - 左边矩形的位置
- x_end - (number) - 右边矩形的位置
- y - (number) - 上方矩形的位置
- y_end - (number) - 下方矩形的位置
- width - (number) - 矩形宽度
- height - (number) - 矩形高度
-
请注意,自定义图层会在下一次调用 gantt.init 后被清除。
-
同时,调用 gantt.resetLayout() 会重置自定义图层。若要保持自定义图层可见,需要在调用 resetLayout 后重新定义 gantt.addTaskLayer。
自定义图层的智能渲染
智能渲染旨在仅显示用户可 见的HTML元素,避免渲染被滚动条遮挡的元素。
然而,对于自定义图层,Gantt本身并不知道自定义元素的位置,因为渲染逻辑完全由用户控制。
为了解决这个问题,智能渲染假设自定义元素位于其关联任务的同一行。只有当任务所在行在屏幕上可见时,自定义元素才会被添加到DOM中。在此方式下,Gantt忽略水平滚动条的位置,因此自定义元素可能存在于标记中,但如果水平滚动超出视野,则不可见。
为此,请使用 addTaskLayer() 方法的对象参数,并向 renderer 对象提供以下方法:
- render - 渲染函数
- getRectangle - 返回自定义元素坐标的函数
gantt.addTaskLayer({
renderer: {
render: (task, timeline, viewport) => {
// ...
return /* HTMLElement */;
},
getRectangle: (task, view) => {
// ...
return { left, top, height, width };
}
}
});
自定义元素的渲染流程如下:
1. 当水平滚动位置变化时,智能渲染获取当前可见区域的坐标。
2. dhtmlxGantt 调用 getRectangle 获取每个任务/链接的自定义元素精确坐标。
3. 若 getRectangle 返回 null,则跳过调用 render,不显示自定义元素。
4. 若 getRectangle 返回的坐标与当前视口重叠,则调用 render 显示自定义元素。
gantt.addTaskLayer({
renderer: {
render: (task) => {
if (task.planned_start && task.planned_end) {
const sizes = gantt.getTaskPosition(
task,
task.planned_start,
task.planned_end
);
const el = document.createElement('div');
el.className = 'baseline';
el.style.left = sizes.left + 'px';
el.style.width = sizes.width + 'px';
el.style.top = (sizes.top + gantt.config.task_height + 13) + 'px';
return el;
}
return false;
},
// define getRectangle in order to hook layer with the smart rendering
getRectangle: (task, view) =>
gantt.getTaskPosition(
task,
task.planned_start,
task.planned_end
)
}
});
渲染自定义元素的可见部分
addTaskLayer() 中的 renderer 对象还支持通过 update 方法更新节点标记,仅显示自定义元素的可见部分:
gantt.addTaskLayer({
renderer: {
render: (task, timeline, viewport) => {
// ...
return /* HTMLElement */;
},
update: (task, node, timeline, viewport) => {
// ...
// put the currently visible part of the element into node inner html
},
getRectangle: (task, view) => {
// ...
return { left, top, height, width };
}
}
});
- update - 允许更新自定义元素的 innerHTML,即隐藏不可见的单元格并显示可见的部分
update 方法会在 onGanttScroll 事件后触发,提供由 render 创建的任务节点及当前视口。
渲染可见的任务行
从v7.1.8开始,renderer 对象支持 getVisibleRange 函数,用于指定任务行的可见范围:
gantt.addTaskLayer({
renderer: {
render: (task, timeline, viewport) => {
// ...
return /* HTMLElement */;
},
getVisibleRange: () => {
// ...
return {
start: indexStart,
end: indexEnd
};
}
}
});
- getVisibleRange - 返回一个对象,包含可见任务行的起始和结束索引。范围外的任务不会渲染额外图层。
如果 getVisibleRange 返回 false 而非对象,Gantt 会假设所有任务均可见,并为所有任务渲染额外图层。
元素渲染回调
renderer 对象还包含一个 onrender 回调:
gantt.addTaskLayer({
renderer: {
render: (task, timeline, viewport) => {
// ...
return /* HTMLElement */;
},
onrender: (item, node, view) => {
console.log("render", item, node);
}
}
});
onrender 函数在每次数据项渲染到DOM时调用,提供对数据项、生成的DOM元素以及触发渲染的视图(grid或timeline)的访问。
此回调可用于渲染后修改DOM元素,或在渲染元素内初始化第三方控件。