vue 实现拖拽甘特图
实现拖拽甘特图的核心步骤
使用 Vue 实现拖拽甘特图需要结合第三方库或自定义逻辑,核心功能包括任务条渲染、时间轴刻度、拖拽交互等。以下是具体实现方法:
选择基础库
推荐使用 vue-draggable 或 vuedraggable 处理拖拽逻辑,配合 SVG 或 Canvas 渲染甘特图。若需完整功能,可直接集成开源库如 dhtmlx-gantt 或 vue-gantt-elastic。
安装基础依赖:
npm install vuedraggable @svgdotjs/svg.js
数据结构设计
甘特图任务数据通常为嵌套结构,包含任务名称、开始/结束时间、层级关系等:
tasks: [
{
id: 1,
name: "任务A",
start: "2023-01-01",
end: "2023-01-05",
progress: 80,
children: [
{ id: 2, name: "子任务A1", start: "2023-01-01", end: "2023-01-03" }
]
}
]
时间轴渲染
使用 SVG 或 CSS Grid 绘制水平时间轴,动态计算刻度位置:

<div class="gantt-header">
<div
v-for="day in timeRange"
:key="day.date"
:style="{ width: `${dayWidth}px` }"
>
{{ day.label }}
</div>
</div>
计算时间范围的逻辑:
computed: {
timeRange() {
const range = [];
let current = new Date(this.startDate);
while (current <= new Date(this.endDate)) {
range.push({
date: current.toISOString(),
label: current.getDate()
});
current.setDate(current.getDate() + 1);
}
return range;
}
}
任务条拖拽实现
通过 vuedraggable 实现任务条的拖拽和位置更新:
<draggable
v-model="tasks"
group="gantt"
@end="onDragEnd"
>
<div
v-for="task in tasks"
:key="task.id"
class="gantt-task"
:style="{
left: `${getTaskPosition(task.start)}px`,
width: `${getTaskDuration(task.start, task.end)}px`
}"
>
{{ task.name }}
</div>
</draggable>
拖拽结束后的回调处理:

methods: {
onDragEnd(evt) {
const movedTask = this.tasks[evt.newIndex];
const newStart = this.calculateDateFromPosition(evt.item.style.left);
// 更新任务时间
movedTask.start = newStart;
movedTask.end = this.calculateEndDate(newStart, movedTask.duration);
}
}
动态调整任务时长
添加拖拽手柄允许调整任务条长度:
<div class="gantt-task">
<div class="task-content">{{ task.name }}</div>
<div
class="resize-handle"
@mousedown="startResize(task)"
></div>
</div>
调整逻辑示例:
startResize(task, evt) {
window.addEventListener('mousemove', this.handleResize);
window.addEventListener('mouseup', this.stopResize);
this.resizingTask = task;
},
handleResize(evt) {
if (!this.resizingTask) return;
const newWidth = evt.clientX - this.$el.getBoundingClientRect().left;
this.resizingTask.end = this.calculateDateFromPosition(newWidth);
}
进阶优化方向
- 性能优化:虚拟滚动处理大量任务
- 依赖关系:使用箭头连接关联任务
- 缩放控制:添加时间单位切换(天/周/月)
- 状态持久化:保存拖拽后的任务数据到后端
完整实现可参考开源项目:






