본문으로 건너뛰기

타임라인에서의 작업 드래그

드래그를 사용하면 사용자가 작업의 시작일(종료일)과 기간을 빠르게 변경할 수 있습니다. 기본적으로 드래그 앤 드롭이 활성화되어 있으며 사용자는 타임라인의 해당 행에서 작업을 드래그할 수 있습니다.

드래그 앤 드롭 동작을 커스터마이즈하려면 아래 이벤트를 사용하십시오:

  • onBeforeTaskDrag - 특정 작업의 드래그를 거부하기 위함
  • onTaskDrag - 드래그 영역을 제한하거나 사용자가 작업을 드래그할 때 다른 로직을 제공하기 위함
  • onAfterTaskDrag - 새로운 위치로 드래그된 후 작업을 후처리하기 위함

기본 드래그 동작을 커스터마이즈해야 하는 일반적인 경우를 살펴보겠습니다:

  1. 특정 작업의 드래그 거부
  2. 특정 날짜에서 벗어난 드래그 금지
  3. 부모와 함께 자식 드래그하기
  4. 서브태스크를 가진 프로젝트 드래그하기
  5. 최소 작업 지속 시간 설정
  6. 작업 드래그 중 자동 스크롤

특정 작업의 드래그 거부

특정 작업의 드래그를 거부하려면 onBeforeTaskDrag 이벤트를 사용합니다:

gantt.attachEvent("onBeforeTaskDrag", (taskId, dragMode, event) => {
if (gantt.getGlobalTaskIndex(taskId) % 2 === 0) {
return false; // 글로벌 작업 인덱스가 짝수인 경우 드래그 거부
}
return true; // 글로벌 작업 인덱스가 홀수인 경우 드래그 허용
});

특정 날짜에서 벗어난 드래그 금지

특정 날짜에서 벗어나 드래그하는 것을 거부하려면 onTaskDrag 이벤트를 사용합니다.

The onTaskDrag 이벤트:

  • 타임라인 영역에서 마우스로 드래그 동작을 수행할 때마다 발생합니다: 이동, 작업 크기 조정 또는 진행률 변경 등
  • 드래그 동작의 유형은 두 번째 인자 - mode 로 전달됩니다.
  • 드래그 동작 유형의 모든 값은 drag_mode 속성에 저장되어 있습니다.

간단히 말해, 전체 흐름은 아래 순서로 진행됩니다:

  1. 사용자가 이동합니다.
  2. dhtmlxGantt가 새 위치에 따라 작업의 날짜를 재계산합니다.
  3. dhtmlxGantt가 onTaskDrag 이벤트를 발생시킵니다.
  4. dhtmlxGantt가 Gantt 차트에서 작업을 다시 렌더링합니다.
    onTaskDrag 이벤트가 재계산 후에 발생하므로 핸들러에서 dragged 작업의 임의의 값을 지정해도 덮어씌워지지 않습니다. 그 결과 작업은 원하는 위치에 렌더링됩니다.

다음과 같이 "2028년 3월 31일 - 2028년 4월 11일" 간격에서 벗어나 드래그하는 것을 금지하고자 한다고 가정해 봅시다.

custom_dnd

다음과 같이 코드를 사용할 수 있습니다:

const leftLimit = new Date(2028, 2, 31);
const rightLimit = new Date(2028, 3, 12);
const millisecondsInDay = 24 * 60 * 60 * 1000;

gantt.attachEvent("onTaskDrag", (taskId, dragMode, task, originalTask) => {
const dragModes = gantt.config.drag_mode;

if (dragMode === dragModes.move || dragMode === dragModes.resize) {
const taskDuration = originalTask.duration * millisecondsInDay;

if (+task.end_date > +rightLimit) {
task.end_date = new Date(rightLimit);
if (dragMode === dragModes.move) {
task.start_date = new Date(task.end_date - taskDuration);
}
}

if (+task.start_date < +leftLimit) {
task.start_date = new Date(leftLimit);
if (dragMode === dragModes.move) {
task.end_date = new Date(+task.start_date + taskDuration);
}
}
}
});

부모와 함께 자식 드래그하기

부모 작업을 드래그할 때 자식도 함께 드래그되도록 하려면 onTaskDrag 이벤트를 사용합니다(위의 이벤트에 대해 더 자세히 보려면 참조):

gantt.attachEvent("onTaskDrag", (taskId, dragMode, task, originalTask) => {
const dragModes = gantt.config.drag_mode;

if (dragMode === dragModes.move) {
const dateShift = task.start_date - originalTask.start_date;
gantt.eachTask((child) => {
child.start_date = new Date(+child.start_date + dateShift);
child.end_date = new Date(+child.end_date + dateShift);
gantt.refreshTask(child.id, true);
}, taskId);
}
});

// 자식 아이템의 위치를 스케일에 맞게 반올림
gantt.attachEvent("onAfterTaskDrag", (taskId, dragMode, event) => {
const dragModes = gantt.config.drag_mode;

if (dragMode === dragModes.move) {
const ganttState = gantt.getState();
gantt.eachTask((child) => {
child.start_date = gantt.roundDate({
date: child.start_date,
unit: ganttState.scale_unit,
step: ganttState.scale_step
});
child.end_date = gantt.calculateEndDate(
child.start_date,
child.duration,
gantt.config.duration_unit
);
gantt.updateTask(child.id);
}, taskId);
}
});

관련 샘플: 자식이 있는 부모 작업 드래그

서브태스크를 가진 프로젝트 드래그하기

정보

이 기능은 Gantt PRO 에디션에서만 사용할 수 있습니다.

프로젝트 타입의 작업은 기본적으로 드래그가 불가능합니다. drag_project 구성으로 프로젝트의 드래그 앤 드롭을 활성화할 수 있습니다:

gantt.config.drag_project = true;

관련 샘플: 드래그 가능한 프로젝트

의존 작업을 독립 작업과 함께 드래그하기

의존 작업을 함께 이동시키는 여러 가지 방법이 있습니다. 이 모든 방법에 대해서는 별도의 기사 [Dragging Tasks Together with Their Dependent Tasks]에서 확인할 수 있습니다. (guides/dragging-dependent-tasks.md)

최소 작업 지속 시간 설정

최소 작업 지속 시간은 min_duration 설정으로 지정할 수 있습니다.

이 옵션은 크기 조정 중에 설정될 수 있는 작업의 최소 크기를 정의하며, 사용자가 0 길이를 설정하는 것을 방지하는 데 사용할 수 있습니다.

값은 밀리초 단위로 설정됩니다:

// 1일
gantt.config.min_duration = 24 * 60 * 60 * 1000;

// OR

// 1시간
gantt.config.min_duration = 60 * 60 * 1000;

작업 드래그 중 자동 스크롤

Gantt 차트에 큰 데이터세트가 있는 경우, 작업을 멀리 떨어진 위치로 드래그하거나 상당한 거리의 작업 간에 링크를 설정해야 할 때가 자주 있습니다.

이 경우 자동 스크롤(autoscroll) 기능이 큰 도움이 됩니다. 기본적으로 활성화되어 있지만, autoscroll 구성 옵션을 통해 이 동작을 관리할 수 있습니다.

gantt.config.autoscroll = false;
gantt.init("gantt_here");

또한 자동 스크롤 속도를 밀리초 단위로 조정하려면 해당 속성 - autoscroll_speed를 사용합니다:

gantt.config.autoscroll = true;
gantt.config.autoscroll_speed = 50;

gantt.init("gantt_here");

특정 작업의 크기 조정 비활성화

특정 작업의 크기 조정을 방지하고 싶다면 두 가지 방법이 있습니다:

  1. UI에서 CSS를 통해 작업의 리사이즈 핸들을 제거합니다. 이 방법을 사용하려면 필요한 항목에 추가 CSS 클래스를 할당할 수 있도록 task_class 템플릿을 사용합니다:
gantt.templates.task_class = (startDate, endDate, task) => {
if (task.no_resize) { // no_resize는 예시를 위한 커스텀 속성
return "no_resize";
}
return "";
};

다음 CSS로 리사이즈 핸들을 숨길 수 있습니다:

.no_resize .gantt_task_drag {
display: none !important;
}
  1. 코드에서 onBeforeTaskDrag 이벤트를 사용해 드래그를 방지합니다. 핸들러에서 false를 반환하면 리사이징이 방지됩니다:
gantt.attachEvent("onBeforeTaskDrag", (taskId, dragMode, event) => {
if (dragMode === "resize" && gantt.getTask(taskId).no_resize) {
return false;
}
return true;
});

어느 쪽에서 크기 조정이 이루어지는가

드래그 앤 드롭의 "resize" 모드는 사용자가 시작일(start_date) 또는 종료일(end_date)에서 작업의 크기를 조정한다는 뜻입니다.

리사이즈로 사용자가 어떤 날짜를 수정하는지 알아내려면 gantt.getState().drag_from_start 플래그를 사용할 수 있습니다:

gantt.attachEvent("onBeforeTaskDrag", (taskId, dragMode, event) => {
if (dragMode === "resize") {
if (gantt.getState().drag_from_start === true) {
// 작업의 시작 날짜를 변경
} else {
// 작업의 종료 날짜를 변경
}
}
return true;
});

시작 날짜 또는 종료 날짜의 크기 조정 비활성화

크기 조정 핸들을 아래 선택자로 찾을 수 있습니다:

  • .gantt_task_drag[data-bind-property="start_date"]
  • .gantt_task_drag[data-bind-property="end_date"]

시작 날짜의 크기 조정을 비활성화하려면 다음 CSS를 사용할 수 있습니다:

.gantt_task_drag[data-bind-property="start_date"] {
display: none !important;
}

마찬가지로 종료 날짜의 크기 조정을 방지하는 방식은 이와 같습니다:

.gantt_task_drag[data-bind-property="end_date"] {
display: none !important;
}

또 다른 방법으로는 onBeforeTaskDrag 이벤트를 사용하는 것입니다. 핸들러에서 false를 반환하면 크기 조정이 방지됩니다:

gantt.attachEvent("onBeforeTaskDrag", (taskId, dragMode, event) => {
if (dragMode === "resize") {
if (gantt.getState().drag_from_start === true) {
return false;
} else {
// 작업의 종료 날짜를 변경
}
}
return true;
});
Need help?
Got a question about the documentation? Reach out to our technical support team for help and guidance. For custom component solutions, visit the Services page.