자바스크립트 복습 겸 드래그 앤 드롭 이벤트 구현 공부
HTML과 CSS를 사용해 드래그할 요소와 드래그 박스를 만들었다.
<li draggable="true">💙</li>
드래그 요소에는 draggable 속성을 작성해주면 된다.
드래그 이벤트는 드래그 가능한 대상에서 발생할 수 있는 이벤트이다.
dragstart
드래그가 처음 시작되면 1회 발생한다.
drag
드래그 중일 때 계속 발생한다.
dragend
드래그가 끝날 때 1회 발생한다.
const listItems = document.querySelector('.list-items');
listItems.addEventListener('drag', () => {
console.log('드래그 이벤트');
});
listItems.addEventListener('dragstart', (e) => {
e.target.style.opacity = 0.5;
console.log('드래그 start');
});
listItems.addEventListener('dragend', (e) => {
e.target.style.opacity = 1;
console.log('드래그 엔드');
});
위 코드는 이벤트 버블링을 이용하여 각각의 li 요소에 이벤트를 부착하는 것이 아닌, 부모 ul 요소에 drag 이벤트를 달았다.
드래그 시작할 때 해당하는 요소의 불투명도가 50%가 되면서 시각적으로 어떤 요소가 드래그 중인지 확인할 수 있다.
드래그가 끝나면 다시 불투명도를 100%로 만들어 준다.
dragenter
드롭될 박스 요소에 이 이벤트를 달면 드래그가 가능한 요소가 이곳에 닿았을 때(진입하면) 1회 발생한다.
dragover
드래그 가능한 요소가 이 이벤트가 달린 요소 위에서 이동 중이거나 위치해 있으면 계속 발생한다.
dragleave
드래그 가능한 요소가 이 이벤트가 달린 요소를 벗어났을 때 1회 발생한다.
drop
dragover 이벤트와 함께 사용한다.
dragover 이벤트와 함께 기본 동작 막기prventDefault()
를 걸어야 제대로 실행된다.
/* 드래그 이벤트가 도착하는 위치 */
dragHere.addEventListener('dragenter', (e) => {
e.stopPropagation();
console.log('드래그 엔터');
e.target.style.background = 'pink';
});
dragHere.addEventListener('dragleave', (e) => {
e.stopPropagation();
console.log('드래그 리브');
e.target.style.background = '';
});
dragHere.addEventListener('dragover', (e) => {
e.preventDefault();
console.log('드래그 오버');
});
dragHere.addEventListener('drop', (e) => {
e.preventDefault();
console.log('드롭');
e.target.style.background = '';
});
자바스크립트로 style을 조작하는 코드 부분을 class 부착, 제거하는 코드로 변경하여 작성해주었다.
드래그 박스로 드롭했을 때 드래그 박스로 요소가 이동하려면,
현재 드래그 중인 요소가 무엇인지 알아야 하고
드래그 박스에 '여기에 드래그 하세요' 문구가 있는 경우에 이 문구를 지우고 ul태그의 자식 요소로 추가하도록 한다.
/* 전체 JS 코드 */
const listItems = document.querySelector('.list-items');
const dragHere = document.querySelector('.drag-here');
let currentItem;
/* 드래그 이벤트 발생 요소 */
listItems.addEventListener('drag', (e) => {
e.target.classList.add('dragging');
});
listItems.addEventListener('dragstart', (e) => {
currentItem = e.target;
});
listItems.addEventListener('dragend', (e) => {
e.target.classList.remove('dragging');
});
/* 드롭 이벤트 발생 요소 */
dragHere.addEventListener('dragenter', (e) => {
e.stopPropagation();
e.target.classList.add('drag-enter');
});
dragHere.addEventListener('dragleave', (e) => {
e.stopPropagation();
e.target.classList.remove('drag-enter');
});
dragHere.addEventListener('dragover', (e) => {
e.preventDefault();
});
dragHere.addEventListener('drop', function (e) {
e.preventDefault();
e.target.classList.remove('drag-enter');
if (document.querySelector('#text')) {
dragHere.removeChild(document.querySelector('#text'));
}
const dragBox = document.querySelector('.drag-list-box');
dragBox.appendChild(currentItem);
currentItem.classList.remove('dragging');
});
금방 해결할 줄 알았는데 생각처럼 마음대로 동작을 안해서 애를 먹었다....😥
일단은 생각한대로 구현하긴 했는데 다음에 다시 구현하면서 더 나은 코드가 있다면 방법을 찾아봐야겠다.
요소들 사이에서 드래그 해도 위치가 이동되는 드래그 이벤트도 같이 구현해보면 좋을 것 같다.
참고 자료
MDN drag 이벤트