vue实现甘特图
使用 Vue 实现甘特图
基于开源库(如 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: '任务A', start: '2023-01-01', end: '2023-01-05' },
{ id: 2, name: '任务B', start: '2023-01-03', end: '2023-01-08' }
],
options: {
viewMode: 'day',
style: {
'bar-color': '#4CAF50',
'bar-radius': '4px'
}
}
};
}
};
</script>
自定义实现(SVG + 计算逻辑)
核心逻辑结构:
<template>
<div class="gantt-container">
<svg :width="width" :height="height">
<!-- 时间轴 -->
<g v-for="(day, i) in days" :key="i">
<text :x="i * dayWidth + 10" y="20">{{ day }}</text>
</g>
<!-- 任务条 -->
<rect
v-for="task in tasks"
:key="task.id"
:x="getTaskX(task.start)"
:y="40 + (task.id * 30)"
:width="getTaskWidth(task.start, task.end)"
height="20"
fill="#4CAF50"
/>
</svg>
</div>
</template>
<script>
export default {
data() {
return {
tasks: [
{ id: 1, name: '任务A', start: '2023-01-01', end: '2023-01-05' },
{ id: 2, name: '任务B', start: '2023-01-03', end: '2023-01-08' }
],
days: ['1月1日', '1月2日', '1月3日', '1月4日', '1月5日'],
dayWidth: 60,
width: 800,
height: 400
};
},
methods: {
getTaskX(startDate) {
const startIndex = this.days.findIndex(day => day.includes(startDate.split('-')[2]));
return startIndex * this.dayWidth;
},
getTaskWidth(startDate, endDate) {
const diffDays = (new Date(endDate) - new Date(startDate)) / (1000 * 60 * 60 * 24);
return diffDays * this.dayWidth;
}
}
};
</script>
集成第三方库(如 Chart.js)
安装 Chart.js 和 vue-chartjs:
npm install chart.js vue-chartjs
甘特图配置示例:
import { HorizontalBar } from 'vue-chartjs';
export default {
extends: HorizontalBar,
data() {
return {
chartData: {
labels: ['任务A', '任务B'],
datasets: [{
data: [
{ x: new Date('2023-01-01'), y: new Date('2023-01-05') },
{ x: new Date('2023-01-03'), y: new Date('2023-01-08') }
],
backgroundColor: '#4CAF50'
}]
},
options: {
scales: {
xAxes: [{
type: 'time',
position: 'top'
}],
yAxes: [{
ticks: { display: false }
}]
}
}
};
},
mounted() {
this.renderChart(this.chartData, this.options);
}
};
关键实现要点
日期计算处理
const dateDiff = (date1, date2) => {
const diffTime = Math.abs(new Date(date2) - new Date(date1));
return Math.ceil(diffTime / (1000 * 60 * 60 * 24));
};
响应式宽度调整
window.addEventListener('resize', () => {
this.width = window.innerWidth * 0.8;
});
任务拖拽交互
handleDragStart(e, task) {
e.dataTransfer.setData('taskId', task.id);
},
handleDrop(e, newDate) {
const taskId = e.dataTransfer.getData('taskId');
this.updateTaskDate(taskId, newDate);
}
样式优化建议
CSS 样式示例:
.gantt-container {
overflow-x: auto;
border: 1px solid #eee;
}
.task-bar {
cursor: move;
transition: all 0.2s;
}
.task-bar:hover {
opacity: 0.8;
}






