v1.4.3 - 垂直虚拟加载优化
This commit is contained in:
@@ -657,6 +657,11 @@ let hideBubblesTimeout: number | null = null // 半圆显示恢复定时器
|
||||
const HOUR_WIDTH = 40 // 每小时40px
|
||||
const VIRTUAL_BUFFER = 10 // 减少缓冲区以提升滑动性能
|
||||
|
||||
// 纵向虚拟滚动相关状态
|
||||
const ROW_HEIGHT = 51 // 每行高度51px (50px + 1px border)
|
||||
const VERTICAL_BUFFER = 5 // 纵向缓冲区行数
|
||||
const timelineBodyScrollTop = ref(0) // 纵向滚动位置
|
||||
|
||||
// 数据缓存
|
||||
const timelineDataCache = new Map<string, unknown>()
|
||||
|
||||
@@ -701,6 +706,30 @@ const visibleHourRange = computed(() => {
|
||||
}
|
||||
})
|
||||
|
||||
// 计算纵向可视区域的任务范围
|
||||
const visibleTaskRange = computed(() => {
|
||||
const scrollTop = timelineBodyScrollTop.value
|
||||
const containerHeight = timelineBodyHeight.value || 600
|
||||
|
||||
// 计算可视区域的开始和结束任务索引
|
||||
const startIndex = Math.floor(scrollTop / ROW_HEIGHT) - VERTICAL_BUFFER
|
||||
const endIndex = Math.ceil((scrollTop + containerHeight) / ROW_HEIGHT) + VERTICAL_BUFFER
|
||||
|
||||
return {
|
||||
startIndex: Math.max(0, startIndex),
|
||||
endIndex: Math.min(tasks.value.length, Math.max(startIndex + 1, endIndex)),
|
||||
}
|
||||
})
|
||||
|
||||
// 获取虚拟滚动优化后的可见任务列表
|
||||
const visibleTasks = computed(() => {
|
||||
const { startIndex, endIndex } = visibleTaskRange.value
|
||||
return tasks.value.slice(startIndex, endIndex).map((task, index) => ({
|
||||
task,
|
||||
originalIndex: startIndex + index,
|
||||
}))
|
||||
})
|
||||
|
||||
// 防抖处理滚动事件(优化:增加防抖时间)
|
||||
const debounce = <T extends (...args: unknown[]) => void>(func: T, wait: number): T => {
|
||||
let timeout: number | null = null
|
||||
@@ -724,6 +753,11 @@ const debouncedUpdateCanvasPosition = debounce(() => {
|
||||
updateSvgSize() // 重新计算 Canvas 位置和尺寸
|
||||
}, 50)
|
||||
|
||||
// 防抖更新纵向滚动位置
|
||||
const debouncedUpdateVerticalScroll = debounce((scrollTop: number) => {
|
||||
timelineBodyScrollTop.value = scrollTop
|
||||
}, 16) // 使用16ms约等于60fps,保证流畅性
|
||||
|
||||
// 缓存时间轴数据的函数
|
||||
const getCachedTimelineData = (): unknown => {
|
||||
const scale = currentTimeScale.value
|
||||
@@ -2162,6 +2196,10 @@ onMounted(() => {
|
||||
// 处理TaskList垂直滚动同步
|
||||
const handleTaskListVerticalScroll = (event: CustomEvent) => {
|
||||
const { scrollTop } = event.detail
|
||||
|
||||
// 立即更新纵向滚动位置(用于虚拟滚动计算)
|
||||
timelineBodyScrollTop.value = scrollTop
|
||||
|
||||
if (timelineBodyElement.value && Math.abs(timelineBodyElement.value.scrollTop - scrollTop) > 1) {
|
||||
// 使用更精确的比较,避免1px以内的细微差异导致的循环触发
|
||||
timelineBodyElement.value.scrollTop = scrollTop
|
||||
@@ -2175,6 +2213,9 @@ const handleTimelineBodyScroll = (event: Event) => {
|
||||
|
||||
const scrollTop = target.scrollTop
|
||||
|
||||
// 立即更新纵向滚动位置(用于虚拟滚动计算)
|
||||
timelineBodyScrollTop.value = scrollTop
|
||||
|
||||
// 拖拽时不同步滚动事件,避免性能问题
|
||||
if (isDragging.value) return
|
||||
|
||||
@@ -3510,13 +3551,13 @@ const handleAddSuccessor = (task: Task) => {
|
||||
<!-- 同时需要考虑左侧TaskList包含1px的bottom border -->
|
||||
<div class="task-bar-container" :style="{ height: `${contentHeight}px` }">
|
||||
<div class="task-rows" :style="{ height: `${contentHeight}px` }">
|
||||
<!-- 使用v-memo减少渲染 -->
|
||||
<!-- 使用虚拟滚动渲染可见任务 -->
|
||||
<div
|
||||
v-for="(task, index) in tasks"
|
||||
v-for="{ task, originalIndex } in visibleTasks"
|
||||
:key="task.id"
|
||||
class="task-row"
|
||||
:class="{ 'task-row-hovered': hoveredTaskId === task.id }"
|
||||
:style="{ top: `${index * 51}px` }"
|
||||
:style="{ top: `${originalIndex * 51}px` }"
|
||||
@mouseenter="handleTaskRowHover(task.id)"
|
||||
@mouseleave="handleTaskRowHover(null)"
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user