這個甘特圖之前插件里,沒有找到能固定label標簽在屏幕上的辦法,用css各種辦法都沒有實現,所以我我直接手寫定位,用js監聽滾動條滾動的距離,然后同步移動甘特圖label標簽,造成一種定位的錯覺,以下是代碼:
我用的是介紹 | Pure Admin 保姆級文檔(已更新至最新版v6.0.0)這個前端框架,感覺功能還是非常完善的,作者全職做開源,希望大家也多多支持。
這個是全部甘特圖的示例代碼
<script setup lang="ts">
import { ref, onMounted, onUnmounted } from "vue";
// https://zunnzunn.github.io/vue-ganttastic/introduction.html
import { GGanttChart, GGanttRow } from "@infectoone/vue-ganttastic";// 添加滾動位置狀態
const scrollLeft = ref(0);
// 添加容器引用
const containerRef = ref(null);// 現有數據保持不變
const context = ref([[{week: "星期一",beginDate: "06:00",endDate: "22:00",label_column_title: "123",ganttBarConfig: {id: "0",hasHandles: true,label: "需求收集和分析 負責人:小張",style: {background: "#e96560"}}}],[{week: "星期二",beginDate: "09:00",endDate: "18:00",ganttBarConfig: {id: "1",hasHandles: true,label: "系統設計 負責人:小強",style: {background: "#5ccfa3"}}}],[{week: "星期三",beginDate: "07:00",endDate: "20:00",ganttBarConfig: {id: "2",hasHandles: true,label: "編碼實現 負責人:老李",style: {background: "#77d6fa"}}}],[{week: "星期四",beginDate: "06:00",endDate: "21:00",ganttBarConfig: {id: "3",hasHandles: true,label: "編碼實現 負責人:小明",style: {color: "#fff",background: "#1b2a47"}}}],[{week: "星期五",beginDate: "05:00",endDate: "19:00",ganttBarConfig: {id: "4",hasHandles: true,label: "內部測試 負責人:小雪",style: {background: "#5ccfa3"}}}],[{week: "星期六",beginDate: "10:00",endDate: "22:00",ganttBarConfig: {id: "5",hasHandles: true,label: "系統優化和文檔整理 負責人:小欣",style: {background: "#f8bc45"}}}],[{week: "星期天",beginDate: "04:00",endDate: "23:59",ganttBarConfig: {id: "6",immobile: false,hasHandles: false,label: "部署和上線 負責人:老王",style: {background: "#f3953d"}}}],[{week: "星期天",beginDate: "04:00",endDate: "23:59",ganttBarConfig: {id: "6",immobile: false,hasHandles: false,label: "部署和上線 負責人:老王",style: {background: "#f3953d"}}}]
]);// 滾動事件處理函數
function handleScroll(e) {scrollLeft.value = e.target.scrollLeft;console.log("滾動事件觸發", scrollLeft.value);const labels = document.querySelectorAll(".g-gantt-row-label, .g-gantt-row-label-container");labels.forEach(label => {label.style.position = "absolute";label.style.left = scrollLeft.value + "px";});
}// 添加和移除滾動事件監聽
onMounted(() => {// 延遲添加事件監聽,確保DOM已完全渲染setTimeout(() => {if (containerRef.value) {containerRef.value.addEventListener("scroll", handleScroll);console.log("滾動監聽已添加", containerRef.value);}}, 500);
});onUnmounted(() => {if (containerRef.value) {containerRef.value.removeEventListener("scroll", handleScroll);console.log("滾動監聽已移除");}
});function getWeekRange() {const today = new Date();const dayOfWeek = today.getDay();const startDate = new Date(today);startDate.setDate(today.getDate() - dayOfWeek + 1);const endDate = new Date(startDate);endDate.setDate(startDate.getDate() + 6);const formatDate = date => {const year = date.getFullYear();const month = String(date.getMonth() + 1).padStart(2, "0");const day = String(date.getDate()).padStart(2, "0");return `${year}-${month}-${day}`;};const currentWeekStart = formatDate(startDate);const currentWeekEnd = formatDate(endDate);return {currentWeekStart,currentWeekEnd};
}const weekRangeInChina = getWeekRange();
</script><template><div ref="containerRef" class="gantt-container"><g-gantt-chartchart-start="00:00"chart-end="23:59"precision="hour"date-format="HH:mm"bar-start="beginDate"bar-end="endDate"gridclass="full-width-gantt"><template #upper-timeunit><h1>{{`${weekRangeInChina.currentWeekStart} / ${weekRangeInChina.currentWeekEnd}`}}</h1></template><g-gantt-rowv-for="(item, index) in context":key="index":bars="item":label="item[0].week"highlight-on-hover/></g-gantt-chart></div>
</template><style>
/* 全局樣式,確保能覆蓋組件內部樣式 */
.g-gantt-row-label,
.g-gantt-row-label-container {position: relative !important;transition: none !important;
}.gantt-container {width: 100%;overflow-x: auto;padding-bottom: 10px;
}.full-width-gantt {min-width: 1500px;width: 200%;
}/* 修改標簽寬度樣式 */
.g-gantt-row-label {width: 100px !important;min-width: 100px !important;max-width: 100px !important;box-sizing: border-box !important;overflow: hidden !important;text-overflow: ellipsis !important;
}
</style>
重點處理方法是:
// 添加滾動位置狀態
const scrollLeft = ref(0);
// 添加容器引用
const containerRef = ref(null);// 添加和移除滾動事件監聽
onMounted(() => {// 延遲添加事件監聽,確保DOM已完全渲染setTimeout(() => {if (containerRef.value) {containerRef.value.addEventListener("scroll", handleScroll);console.log("滾動監聽已添加", containerRef.value);}}, 500);
});// 滾動事件處理函數
function handleScroll(e) {scrollLeft.value = e.target.scrollLeft;console.log("滾動事件觸發", scrollLeft.value);const labels = document.querySelectorAll(".g-gantt-row-label, .g-gantt-row-label-container");labels.forEach(label => {label.style.position = "absolute";label.style.left = scrollLeft.value + "px";});
}
onUnmounted(() => {if (containerRef.value) {containerRef.value.removeEventListener("scroll", handleScroll);console.log("滾動監聽已移除");}
});