vue实现甘特图展示
使用第三方库实现甘特图
推荐使用 vue-ganttastic 或 dhtmlx-gantt 这类成熟的第三方库快速实现甘特图功能。vue-ganttastic 是一个轻量级 Vue 组件,适合简单需求;dhtmlx-gantt 功能更强大,支持复杂场景。
安装 vue-ganttastic:
npm install vue-ganttastic
基础示例代码:
<template>
<GanttChart
:tasks="tasks"
:options="options"
/>
</template>
<script>
import { GanttChart } from 'vue-ganttastic';
export default {
components: { GanttChart },
data() {
return {
tasks: [
{ id: 1, name: 'Task 1', start: '2023-01-01', end: '2023-01-05' },
{ id: 2, name: 'Task 2', start: '2023-01-06', end: '2023-01-10' }
],
options: {
viewMode: 'day',
style: { height: '300px' }
}
};
}
};
</script>
自定义实现甘特图
若需完全自定义,可通过 SVG 或 Canvas 绘制。以下为基于 SVG 的简化实现思路:
-
定义数据结构:
tasks: [ { id: 1, name: '开发', start: new Date(2023, 0, 1), end: new Date(2023, 0, 5), progress: 80 }, { id: 2, name: '测试', start: new Date(2023, 0, 6), end: new Date(2023, 0, 10), progress: 30 } ] -
计算时间轴和任务位置:
computed: { timeRange() { // 计算最早开始时间和最晚结束时间 }, scaleX(value) { // 将日期转换为像素坐标 } } -
模板结构:
<template> <div class="gantt-container"> <div class="gantt-header"> <!-- 时间轴刻度 --> </div> <svg class="gantt-body"> <g v-for="task in tasks" :key="task.id"> <rect :x="scaleX(task.start)" :width="scaleX(task.end) - scaleX(task.start)" y="30" height="20" fill="#4CAF50" /> <!-- 进度条和文本 --> </g> </svg> </div> </template>
关键功能扩展
时间轴缩放
通过修改 viewMode(day/week/month)动态调整时间轴显示粒度,重计算 scaleX 函数。
任务交互
添加拖拽事件处理:
methods: {
handleTaskDrag(task, newStart) {
// 更新任务开始/结束时间
}
}
依赖关系
使用箭头绘制任务间的关联线:
<line
v-for="link in links"
:x1="scaleX(getTask(link.source).end)"
:y1="getTaskY(link.source)"
:x2="scaleX(getTask(link.target).start)"
:y2="getTaskY(link.target)"
stroke="#999"
marker-end="url(#arrow)"
/>
样式优化建议
-
使用 CSS 变量统一颜色主题:
.gantt-container { --bar-color: #4CAF50; --progress-color: #2E7D32; } rect.task-bar { fill: var(--bar-color); } -
添加响应式布局:
@media (max-width: 768px) { .gantt-header { font-size: 12px; } }
性能优化
对于大数据量场景:

- 虚拟滚动:只渲染可视区域内的任务
- 防抖处理:频繁的时间轴缩放操作
- Web Worker:复杂计算移至后台线程
// 虚拟滚动示例
visibleTasks() {
return this.tasks.slice(
Math.floor(this.scrollTop / this.rowHeight),
Math.floor((this.scrollTop + this.containerHeight) / this.rowHeight)
);
}






