demo效果
甘特图
-
释义: 甘特图以图示通过活动列表和时间刻度表示出特定项目的顺序与持续时间。一条线条图,横轴表示时间,纵轴表示项目,线条表示期间计划和实际完成情况。此外,用户还可以在时间表中直接更新任务进程。 甘特图包含以下三个含义:
- 以图形或表格的形式显示活动;
- 通用的显示进度的方法;
- 构造时汉日历天和持续时间,不将周末节假算在进度内。
-
技术选型
首先就是在百度上搜了一圈,初步得到了wl-gantt、dhtmlxGantt、hightCharts-gantt、jQuery.Gantt等等插件。然后又去github上看了一圈,结果如下:
把调研的gantt都试了一遍之后,发现最合适的是
DHTMLX/gantt。那就开干吧!
DHTMLX/gantt分为标准版和pro版;此示例使用的是标准版,朋友们在使用时请注意标准版能否满足需求,pro版需要购买。
甘特图官网
这里我是在vue中使用的,官网提供了很多不同的使用方式,各位各取所需就行了。
首先是官方文档。这里建议先从文档开始的部分来学习,把红框的两部分熟悉一下,就能够开始操作了。
全英文看着费劲的话,可以在新版edge浏览器打开上述网站,将网页翻译为中文。
如果想在框架中使用该插件,官网中也给出了相应的文档,here。
确定使用方式
要在页面上显示基本甘特图,需要按照 3 个步骤操作(Vue示例):
- 在页面上包含dhtmlxGantt 代码文件
import gantt from 'dhtmlx-gantt';
import 'dhtmlx-gantt/codebase/dhtmlxgantt.css';
- 在页面上创建 DIV 容器。
<div class="plan-chart" ref="ganttRef"></div>
- 使用init方法在新创建的容器中初始化 dhtmlxGantt。init方法的参数,为需要展示的HTML 容器(或其 id)。
// 初始化
gantt.init(ganttRef.value);
// 数据解析
gantt.parse(dataFormat(props.formData));
官网在初始化模块中介绍了3种引入dhtmlxGantt到项目的方式,大家各取所需:
核心代码
ganttConfig配置方法:每一个配置都进行了注释,有的注释后方还有官网文档连接。
若想详细了解某个配置,可直接复制该配置的方法名,在官方文档中搜索;
若想了解其他配置,就去官方文档中的Api模块查找。
const ganttConfig = () => {
// 设置时间范围
// gantt.config.start_date = new Date(props.startDate.replace(/-/g, '/'));
// gantt.config.end_date = new Date(props.endDate.replace(/-/g, '/'));
// 显示连线
gantt.config.show_links = true;
// 显示进度
gantt.config.show_progress = true;
// gantt.config.drag_progress = false;
// 开启marker插件
gantt.plugins({marker: true, tooltip: true});
// 返回dateToStr函数,将本地时间转换成相应格式
const dateToStr = gantt.date.date_to_str(gantt.config.task_date);
const today = new Date();
// 添加固定时间线
gantt.addMarker({
start_date: today,
css: 'today',
text: '今日:' + moment(new Date()).format('YYYY-MM-DD'),
title: 'Today: ' + dateToStr(today)
});
// 模板定义-长条上的文字
// gantt.templates.task_text = function (start, end, task) {
// return '<b>Text:</b> ' + task.text + ',<b> Holders:</b> ' + task.users;
// };
// 提示框内容
gantt.templates.tooltip_text = (start, end, task) => {
return '<b>步骤:</b>' + task.text +
'<br/><b>负责人:</b> ' + (task.role || '') +
'<br/><b>开始时间:</b> ' + moment(task.start_date).format('YYYY-MM-DD') +
'<br/><b>结束时间:</b> ' + moment(task.end_date).format('YYYY-MM-DD');
};
// 设置周末隐藏,此功能仅在专业版可用
// gantt.ignore_time = (date) => {
// if (date.getDay() === 0 || date.getDay() === 6) {
// return true;
// }
// };
// 设置周末高亮
gantt.templates.timeline_cell_class = (item, date) => {
if (time.value === 'day' && (date.getDay() === 0 || date.getDay() === 6)) {return 'weekend';} return '';
};
// 日期格式https://docs.dhtmlx.com/gantt/desktop__date_format.html
gantt.config.scales = [
{unit: 'year', step: 1, format: '%Y年'},
{unit: 'month', step: 1, format: '%Y-%n'},
{unit: 'week', step: 1, format: '第%W周'},
{unit: 'day', step: 1, format: '周%D'},
{unit: 'day', step: 1, format: '%j'},
];
// 甘特图右侧表头的高度
gantt.config.scale_height = 90;
// 使用中文
gantt.i18n.setLocale('cn');
// 自适应甘特图的尺寸大小, 使得在不出现滚动条的情况下, 显示全部任务
gantt.config.autosize = true;
// 只读模式(用此模式就不能对图形进行编辑)
// gantt.config.readonly = true;
// 是否显示左侧树表格
gantt.config.show_grid = true;
// 表格列设置 https://docs.dhtmlx.com/gantt/api__gantt_columns_config.html
gantt.config.columns = [
{name: 'text', label: '步骤', tree: true, width: '150', align: 'center'},
// {name: 'start_date', label: '开始', width: '100', align: 'center'},
// {name: 'end_date', label: '结束', width: '100', align: 'center'},
// {name: 'duration', label: '持续时间', width: '100', align: 'center'},
// {name: 'progress', label: '进度', width: '100', align: 'center'},
{name: 'role', label: '负责人', width: '100', align: 'center'},
];
// 任务条上的文字大小 以及取消border自带样式
gantt.templates.task_class = function () {
return 'firstLevelTask';
};
// 设置任务栏颜色 https://docs.dhtmlx.com/gantt/api__gantt_task_class_template.html
gantt.templates.task_class = function (start, end, task) {
console.log(moment(start).format('YYYY-MM-DD'), moment(end).format('YYYY-MM-DD'), task, 'task');
return task?.color ?? '';
};
};
ganttRender渲染方法
const ganttRender = () => {
// 初始化
gantt.init(ganttRef.value);
// 数据解析
// gantt.parse(basicData); 可以导入基础数据进行演示查看
gantt.parse(dataFormat(props.formData));
};
css部分
.weekend{
background: #bfbfbf;
}
.over {
background-color: #e43c59;
}
.firstLevelTask {
border: none;
}
basicData数据示例
const basicData = {
// https://docs.dhtmlx.com/gantt/desktop__loading.html gantt数据结构解析
data: [
// 使用duration,会自动计算end_date
// {id: 1, text: 'Project #2', start_date: '01-11-2022', duration: 18, progress: 0.4, open: true},
// {id: 2, text: 'Task #1', start_date: '13-11-2022', duration: 8, progress: 0.6, parent: 1},
// {id: 3, text: 'Task #2', start_date: '20-11-2022', duration: 8, progress: 0.6, parent: 1}
// 使用end_date,会自动计算duration
// id可为string或者number,这个id就是links里面source和target使用的id
{id: 1, text: 'Project #2', start_date: '01-11-2022', end_date: '03-11-2022', progress: 0.4, open: true},
{id: 2, text: 'Task #1', start_date: '13-11-2022', end_date: '23-11-2022', progress: 0.6, parent: 1},
{id: 3, text: 'Task #2', start_date: '20-11-2022', end_date: '25-11-2022', progress: 0.6, parent: 1}
],
links: [
// 这个id可为string或者number,跟data的id没关系。source和target跟data的id对应
{id: 5, source: 1, target: 2, type: '1'},
{id: 6, source: 2, target: 3, type: '0'}
]
};
总结
- 本篇文章记录了实现
dhtmlxGantt甘特图的过程,经历了:了解知识背景、技术选型、技术落地、实现小demo的过程。 - 该插件比较灵活,在实际使用时,可以根据具体需求具体操作。(比如封装成组件等等)