
Assignment 8 과제를 통해 얻은 지식 정리 글입니다.
과제 레파지토리 : https://github.com/6trillion/Assignmet8-TeamA
유튜브 영상을 참고해 코드를 분석했습니다.
코드 자료 : https://github.com/WebDevSimplified/Drag-And-Drop
드래그할 속성들과 속성들을 감싸는 컨테이너로 구성합니다.
draggable 속성을 이용해 드래그가 가능하도록 설정합니다.
<body>
<div class="container">
<p class="draggable" draggable>
1
</p>
<p class="draggable" draggable>
2
</p>
</div>
<div class="container">
<p class="draggable" draggable>
3
</p>
<p class="draggable" draggable>
4
</p>
</div>
</body>
CSS를 적용하고, cursor:move로 마우스 커서를 올렸을 때 스타일을 지정해 줍니다.
.draggable {
cursor: move;
}
드래그를 시작하는 순간에 발생하는 이벤트입니다.드래그가 끝나는 순간에 발생하는 이벤트입니다.드래그를 하는 도중에 발생하는 이벤트입니다.먼저 draggable, container class를 모두 선택하고 각각에 대해 dragstart, dragend 이벤트를 설정합니다. 각각의 이벤트에 대해 dragging class를 추가, 삭제합니다.
const draggables = document.querySelectorAll(".draggable");
const containers = document.querySelectorAll(".container");
draggables.forEach((draggable) => {
draggable.addEventListener("dragstart", () => {
draggable.classList.add("dragging");
});
draggable.addEventListener("dragend", () => {
draggable.classList.remove("dragging");
});
});
드래그할 속성들을 감싸고 있는 container에 대해 dragover 이벤트를 설정합니다. 따라서 이 container 안에서 드래그할 때만 이벤트가 발생합니다.
getDragAfterElement 함수를 이용해 드래그한 속성이 지나고 있는 위치의 속성 afterElement을 가져옵니다.
afterElement이 null인 경우는 지나고 있는 속성이 없는 경우, 즉 가장 아래에서 드래그 중임을 의미합니다. 이 경우 appendchild를 이용해 가장 아래에 추가하면서 구현합니다.
afterElement이 존재하는 경우, 어느 속성 어딘가 위에서 드래그하고 있다는 의미입니다. 따라서 inserBefore를 이용해 afterElement 앞에 현재 드래그하고 있는 속성을 추가합니다.
containers.forEach((container) => {
container.addEventListener("dragover", (e) => {
e.preventDefault();
const afterElement = getDragAfterElement(container, e.clientY);
const draggable = document.querySelector(".dragging");
if (afterElement == null) {
container.appendChild(draggable);
} else {
container.insertBefore(draggable, afterElement);
}
});
});
reducer 메서드와 y 좌표를 이용해 어느 속성 위를 드래그하고 있는지 알아냅니다.
먼저 드래그 되지 않은 속성들을 배열로 만든 후, 각각의 속성의 getBoundingClientRect를 이용해 top과 height 값으로 속성들의 y 값을 구합니다. 여기서는 top - (height / 2)를 이용해 속성의 절반만큼의 위치에서 드래그할 때 위치와 element를 반환합니다.
이 때 reducer 메서드를 이용해 값을 누적시켜 모든 속성들의 y 값을 알 수 있습니다.
function getDragAfterElement(container, y) {
const draggableElements = [
...container.querySelectorAll(".draggable:not(.dragging)"),
];
return draggableElements.reduce(
(closest, child) => {
const box = child.getBoundingClientRect();
const offset = y - box.top - box.height / 2;
if (offset < 0 && offset > closest.offset) {
return { offset: offset, element: child };
} else {
return closest;
}
},
{ offset: Number.NEGATIVE_INFINITY }
).element;
}