官网示例地址:https://docs.dhtmlx.com/gantt/samples/
可以在这里查看绑定数据的格式
安装依赖
npm install dhtmlx-gantt --save
创建一个甘特图组件
<template>
<el-scrollbar ref="gantt_scrollbar" class="gantt-box">
<div ref="gantt" class="gantt-container"></div>
</el-scrollbar>
</template>
<script>
import { gantt } from 'dhtmlx-gantt';
import "dhtmlx-gantt/codebase/dhtmlxgantt.css"
export default {
name: "gantt",
props: {
ganttTasks: {
type: Array,
default () {
return []
}
}
},
data() {
return {
ganttData: []
}
},
mounted() {
this.initGantt() // gantt初始化配置
this.getGanttData() // 数据format以及gantt reload
},
methods: {
initGantt() {
let _this = this
// 在初始化前设置配置项
// 初始化gantt
gantt.init(this.$refs.gantt);
// 绑定数据
gantt.parse({
data: [], // 时间轴上横条的数据
link: [] // 连接线的数据
});
},
reload() {
gantt.clearAll();// 从甘特图中删除所有任务和其他元素(包括标记)
gantt.parse({
data: this.ganttData,
link: []
}); // 数据解析
gantt.render(); // 呈现整个甘特图
},
getGanttData() {
let ganttData = []
// toDo
// formatGanttData()
this.ganttData = ganttData
this.reload()
}
}
}
</script>
<style lang="less" scoped>
/*@import "dhtmlx-gantt/codebase/dhtmlxgantt.css"*/
.gantt-container {
width: 10000px;
height: 400px;
}
.gantt-box {
width: calc(100% - 10px);
overflow-y: scroll;
overflow-x: scroll;
height: 400px;
}
</style>
到这里传入数据就可以显示甘特图啦
配置
gantt.init()
以下是需要在gantt.init前配置好的,放在initGantt()方法里
- 设置甘特图只读
initGantt() {
let _this = this
// gantt只读
gantt.config.readonly = true;
// 初始化gantt
gantt.init(this.$refs.gantt);
// 绑定数据
gantt.parse({
data: [], // 时间轴上横条的数据
link: [] // 连接线的数据
});
},
- 设置甘特图的row是否可以选中
gantt.config.select_task = false;
- 设置表格列宽自适应
gantt.config.autofit = false;
- 设置日期格式
gantt.config.xml_date = "%Y/%m/%d";
- 自定义表格列
表格列的内容可以通过template返回
gantt.config.columns=[
{
name:"text", width: 160, label:"标题", align: "left", tree:true,
template: function (obj) {
// 通过 template 回调可以指定返回内容值
return `
<div class="gantt-span-${obj.taskType}" style="width:130px;text-overflow:ellipsis;overflow: hidden;">${obj.taskNum} ${obj.text}</div>
`;
},
}
];
这里要注意,数据有一些字段是必须保留的,包括:
id: stage.id, // id-gantt必填字段
text: stage.stageName, // 名称-gantt必填字段
start_date: stage.createDate.substring(0, 10), // 开始时间-gantt必填字段
duration: stage.duration, //工作时长-gantt必填字段
这里duration字段也可以用end_date代替
- 添加自定义class,可以用来设置一些特定日期的样式
// 今日高亮
// 周末高亮
// 这里在时间轴表头添加class
var daysStyle = function(date){
let todayDate = new Date().setHours(0,0,0,0)
let paramsDate = new Date(date).setHours(0,0,0,0)
if (todayDate === paramsDate) {
return "today";
}
if (date.getDay() === 0 || date.getDay() === 6){
return "weekend";
}
return "";
};
//这里在时间轴表格内的cell上添加class
gantt.templates.timeline_cell_class = function (item, date) {
if (date.getDay() == 0 || date.getDay() == 6) {
return "weekend"
}
};
<style lang="less" scope>
/* 周末高亮 */
/deep/ .weekend {
background: #F8F8F8;
color: #999999!important;
// height: 47px!important;
}
/* 今日高亮 */
/deep/ .gantt_task_scale {
.gantt_scale_line > .gantt_scale_cell {
color: #333333;
&.today {
background: #0066FF;
color: #FFFFFF;
}
}
}
</style>
- 设置时间轴多层表头
gantt.config.scales = [
{unit: "month", step: 1, format: "%Y/%M"},
{unit: "day", format: "%d", css:daysStyle}
];
- 设置条形图里要显示的文字和自定义的class,实现文字、颜色等自定义
// 条形图里的文字
gantt.templates.task_text = function (start, end, task) {
return `<span style='text-align:left;'>${task.text} # ${task.taskHolder}</span>`;
};
// 条形图自定义class
gantt.templates.task_class = function (start, end, task) {
return `task-${task.taskType}-${task.status}`
};
- 行高
gantt.config.scale_height = 60;
gantt.config.task_height = 24;
gantt.config.row_height = 48;
gantt.config.min_column_width = 50;
- 添加今日标线
// 今日标线需要用到插件marker
// gantt需要用到的插件
gantt.plugins({
marker: true,
});
let today = new Date();
gantt.addMarker({
start_date: today,
css: 'today',
text: '',
});
- 添加tooltip
gantt.plugins({
tooltip: true
});
// 自定义tooltip内容
gantt.templates.tooltip_text = function (start, end, task) {
const t = gantt;
const output = `<div style="font-size:14px;padding: 0 10px;width:250px;line-height:20px;white-space:normal;">
<p style="font-weight:bold;margin: 8px 0;">${task.text}</p>
<p style="margin: 4px 0;">当前进度:${task.progress*100}%</p>
<p style="margin: 4px 0;">标准工时:${task.standardTime}</p>
<p style="margin: 4px 0;">实际工时:${task.actualTime}</p>
<p style="margin: 4px 0;">工作状态:${task.statusText}</p>
</div>`;
return output;
}
- 设置表头显示中文
gantt.i18n.setLocale("cn");
- 树形是否自动展开
gantt.config.open_tree_initially = false;
- 自定义的点击事件
gantt.attachEvent("onTaskClick", function(id,e){
let box = document.querySelector('.gantt_tooltip');
if (box) {
box.parentNode.removeChild(box);
}
let classList = e.target.className.split(' ')
// 这里自定义了展开/收起树形的点击事件
if (classList.includes('gantt_open')) {
gantt.open(id); // 展开
return true
}
if (classList.includes('gantt_close')) {
gantt.close(id); // 收起
return true
}
// 这里是其他的点击事件
let task = _this.ganttData.find(item => {return item.id == id})
if (task.taskType === 'stage') {
// toDo()
return true
}
});
gantt.render()
这里因为我的数据需要异步请求格式化,这是gantt已经初始化了,所以需要使用gantt.render()重新渲染
在gantt重新render前,要清除缓存
这里会把一些配置项也清掉,比如今日标线
reload() {
gantt.clearAll();// 从甘特图中删除所有任务和其他元素(包括标记)
gantt.parse({
data: this.ganttData,
link: []
}); // 数据解析
// 今日标线
let today = new Date();
gantt.addMarker({
start_date: today,
css: 'today',
text: '',
});
gantt.render(); // 呈现整个甘特图
},
style
- 去掉树形的文件夹图标
/* 去掉文件夹图标 */
/deep/ .gantt_tree_icon {
&.gantt_folder_closed, &.gantt_file, &.gantt_folder_open {
display:none
}
}
/* 把展开收起图标替换成element-ui的icon */
/* 这里没有找到在js中配置图标的方法,为省事,使用css */
/* 扒了element-ui的icon样式表 */
/deep/ .gantt_tree_icon.gantt_open {
background-image: none;
font-family: element-icons!important;
speak: none;
font-style: normal;
font-weight: 400;
font-variant: normal;
text-transform: none;
vertical-align: baseline;
display: inline-block;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
&::before {
content: "\e6df";
}
}
/deep/ .gantt_tree_icon.gantt_close {
background-image: none;
font-family: element-icons!important;
speak: none;
font-style: normal;
font-weight: 400;
font-variant: normal;
text-transform: none;
vertical-align: baseline;
display: inline-block;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
&::before {
content: "\e6e1";
}
}