纯vue项目实现甘特图
使用第三方库 vue-gantt-elastic
vue-gantt-elastic 是一个基于 Vue 的甘特图组件,支持拖拽、缩放、时间轴调整等功能。安装方式如下:
npm install vue-gantt-elastic
示例代码:
<template>
<gantt-elastic
:tasks="tasks"
:options="options"
@task-changed="onTaskChange"
/>
</template>
<script>
import GanttElastic from 'vue-gantt-elastic';
export default {
components: { GanttElastic },
data() {
return {
tasks: [
{
id: '1',
label: '任务 1',
user: '用户 A',
start: '2023-01-01',
end: '2023-01-10',
progress: 50
}
],
options: {
title: {
label: '项目计划'
}
}
};
},
methods: {
onTaskChange(task) {
console.log('任务更新:', task);
}
}
};
</script>
基于原生实现简单甘特图
如果需要轻量级实现,可以手动绘制甘特图。使用 Vue 结合 CSS 和计算属性动态渲染任务条。
<template>
<div class="gantt-container">
<div class="gantt-header">
<div v-for="day in days" :key="day" class="gantt-day">{{ day }}</div>
</div>
<div class="gantt-body">
<div
v-for="task in tasks"
:key="task.id"
class="gantt-task"
:style="{
left: `${task.startPosition}%`,
width: `${task.duration}%`
}"
>
{{ task.label }}
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
days: ['周一', '周二', '周三', '周四', '周五'],
tasks: [
{ id: 1, label: '任务 A', start: 0, end: 2 },
{ id: 2, label: '任务 B', start: 1, end: 4 }
]
};
},
computed: {
processedTasks() {
return this.tasks.map(task => ({
...task,
startPosition: (task.start / this.days.length) * 100,
duration: ((task.end - task.start) / this.days.length) * 100
}));
}
}
};
</script>
<style>
.gantt-container {
width: 100%;
position: relative;
}
.gantt-header {
display: flex;
border-bottom: 1px solid #ccc;
}
.gantt-day {
flex: 1;
text-align: center;
padding: 8px;
}
.gantt-body {
position: relative;
height: 200px;
}
.gantt-task {
position: absolute;
height: 30px;
background: #4CAF50;
color: white;
padding: 4px;
border-radius: 4px;
}
</style>
集成 DHTMLX Gantt
DHTMLX Gantt 是一个功能丰富的商业甘特图库,提供 Vue 封装版本。安装方式:
npm install dhtmlx-gantt
示例代码:
<template>
<div ref="ganttContainer" style="width: 100%; height: 500px;"></div>
</template>
<script>
import 'dhtmlx-gantt';
import 'dhtmlx-gantt/codebase/dhtmlxgantt.css';
export default {
mounted() {
gantt.init(this.$refs.ganttContainer);
gantt.parse({
data: [
{ id: 1, text: '任务 #1', start_date: '2023-01-01', duration: 5 },
{ id: 2, text: '任务 #2', start_date: '2023-01-06', duration: 3 }
],
links: [{ id: 1, source: 1, target: 2, type: '0' }]
});
}
};
</script>
时间轴动态计算
对于需要动态计算时间轴的场景,可以使用 dayjs 或 moment 处理日期:
import dayjs from 'dayjs';
function calculatePosition(startDate, endDate, timelineStart, timelineEnd) {
const totalDays = dayjs(timelineEnd).diff(timelineStart, 'day');
const startOffset = dayjs(startDate).diff(timelineStart, 'day');
const duration = dayjs(endDate).diff(startDate, 'day');
return {
positionPercent: (startOffset / totalDays) * 100,
widthPercent: (duration / totalDays) * 100
};
}
响应式布局处理
在 Vue 的 computed 属性中处理窗口大小变化:
computed: {
chartWidth() {
return window.innerWidth - 40;
}
},
mounted() {
window.addEventListener('resize', this.handleResize);
},
beforeDestroy() {
window.removeEventListener('resize', this.handleResize);
}






