dhtmlx-gantt 添加左右两侧拖拽辅助线

68 阅读1分钟
 // 添加拖拽开始事件 - 显示辅助线
  gantt.attachEvent('onTaskDragStart', function () {
    createDragGuideLines();
    return true;
  });
  // 添加拖拽过程中事件 - 更新辅助线位置
  gantt.attachEvent('onTaskDrag', function (id, mode, task, original) {
    updateDragGuideLines(task, mode, original);
    return true;
  });
// 移除拖拽辅助线
const removeDragGuideLines = () => {
  const guideLineIds = [
    'gantt-current-start-guide-line',
    'gantt-current-end-guide-line',
  ];

  guideLineIds.forEach((id) => {
    const guideLine = document.getElementById(id);
    if (guideLine) {
      guideLine.remove();
    }
  });
};


const createDragGuideLines = () => {
  // 移除已存在的辅助线
  removeDragGuideLines();

  const ganttElement = gantt.$root;
  if (!ganttElement) return;

  // 创建当前任务开始时间辅助线
  const currentStartGuideLine = document.createElement('div');
  currentStartGuideLine.className =
    'gantt-drag-guide-line gantt-current-start-guide';
  currentStartGuideLine.id = 'gantt-current-start-guide-line';
  ganttElement.appendChild(currentStartGuideLine);

  // 创建当前任务结束时间辅助线
  const currentEndGuideLine = document.createElement('div');
  currentEndGuideLine.className =
    'gantt-drag-guide-line gantt-current-end-guide';
  currentEndGuideLine.id = 'gantt-current-end-guide-line';
  ganttElement.appendChild(currentEndGuideLine);
};


// 更新拖拽辅助线位置
const updateDragGuideLines = (task, mode, original) => {
  const currentStartGuideLine = document.getElementById(
    'gantt-current-start-guide-line',
  );
  const currentEndGuideLine = document.getElementById(
    'gantt-current-end-guide-line',
  );

  if (!currentStartGuideLine || !currentEndGuideLine) return;
  if (!task.start_date || !task.end_date) return;

  // 获取任务在时间轴上的位置(这个位置已经是相对于时间轴起始位置的)
  const currentStartPos = gantt.posFromDate(task.start_date);
  const currentEndPos = gantt.posFromDate(task.end_date);

  // 获取甘特图的时间轴区域
  const timelineArea = gantt.$task_data;
  if (!timelineArea) return;

  // 获取时间轴区域相对于甘特图根元素的偏移
  const timelineRect = timelineArea.getBoundingClientRect();
  const ganttRect = gantt.$root.getBoundingClientRect();
  const timelineLeftOffset = timelineRect.left - ganttRect.left;
  const timelineWidth = timelineRect.width;

  // 计算辅助线在甘特图根元素中的实际位置
  // posFromDate返回的是相对于时间轴内容的位置,需要加上时间轴的偏移
  const currentStartLeft = timelineLeftOffset + currentStartPos;
  const currentEndLeft = timelineLeftOffset + currentEndPos;

  // 根据拖拽模式决定显示哪些辅助线
  let showStartLine = false;
  let showEndLine = false;

  if (mode === 'move') {
    // 整体移动,显示两条线
    showStartLine = true;
    showEndLine = true;
  } else if (mode === 'resize' && original) {
    // 调整大小模式,通过比较原始时间和当前时间判断拖拽方向
    const originalStartTime = new Date(original.start_date).getTime();
    const originalEndTime = new Date(original.end_date).getTime();
    const currentStartTime = new Date(task.start_date).getTime();
    const currentEndTime = new Date(task.end_date).getTime();

    // 判断是拖拽左边(开始时间变化)还是右边(结束时间变化)
    const startChanged = originalStartTime !== currentStartTime;
    const endChanged = originalEndTime !== currentEndTime;

    if (startChanged && !endChanged) {
      // 只有开始时间变化,拖拽左边
      showStartLine = true;
      showEndLine = false;
    } else if (!startChanged && endChanged) {
      // 只有结束时间变化,拖拽右边
      showStartLine = false;
      showEndLine = true;
    } else {
      // 两个时间都变化或都不变化,显示两条线
      showStartLine = true;
      showEndLine = true;
    }
  } else {
    // 默认显示两条线
    showStartLine = true;
    showEndLine = true;
  }

  // 设置当前任务开始时间辅助线位置
  if (
    showStartLine &&
    currentStartPos >= 0 &&
    currentStartPos <= timelineWidth
  ) {
    currentStartGuideLine.style.left = currentStartLeft + 'px';
    currentStartGuideLine.style.display = 'block';
  } else {
    currentStartGuideLine.style.display = 'none';
  }

  // 设置当前任务结束时间辅助线位置
  if (showEndLine && currentEndPos >= 0 && currentEndPos <= timelineWidth) {
    currentEndGuideLine.style.left = currentEndLeft + 'px';
    currentEndGuideLine.style.display = 'block';
  } else {
    currentEndGuideLine.style.display = 'none';
  }

  // 设置辅助线的高度和顶部位置
  const ganttDataArea = gantt.$task_data;
  if (ganttDataArea) {
    const dataRect = ganttDataArea.getBoundingClientRect();
    const ganttRect = gantt.$root.getBoundingClientRect();
    const topOffset = dataRect.top - ganttRect.top;
    const height = dataRect.height;

    [currentStartGuideLine, currentEndGuideLine].forEach((line) => {
      if (line) {
        line.style.top = topOffset + 'px';
        line.style.height = height + 'px';
      }
    });
  }
};

//拖拽完成之后隐藏辅助线
 gantt.attachEvent('onAfterTaskDrag', function (id) {
    // 隐藏辅助线
    removeDragGuideLines();
  });