드래그 앤 드롭은 훌륭한 인터페이스 솔루션입니다. 문서를 복사 및 이동 (파일 관리자에서와 같이)에서 주문 (장바구니에 항목을 놓기)에 이르기까지 많은 작업을 수행 할 수있는 명확하고 간단한 방법입니다.
최신 HTML에서 표준에는 dragstart
, dragend
등과 같은 특수 이벤트와 함께 끌어서 놓기에 대한 섹션이 있습니다.
이러한 이벤트를 통해 OS 파일 관리자에서 파일을 드래그하여 브라우저 창에 놓는 것과 같은 특별한 종류의 드래그 앤 드롭을 지원할 수 있습니다. 그러면 JavaScript가 이러한 파일의 내용에 액세스 할 수 있습니다.
그러나 네이티브 드래그 이벤트에도 제한이 있습니다. 예를 들어 특정 영역에서 드래그하는 것을 막을 수 없습니다. 또한 드래그를 “수평”또는 “수직”으로 만 만들 수 없습니다. 그리고이를 사용하여 수행 할 수없는 다른 드래그 앤 드롭 작업이 많이 있습니다. 또한 이러한 이벤트에 대한 모바일 장치 지원은 매우 약합니다.
여기서 마우스 이벤트를 사용하여 Drag’n’Drop을 구현하는 방법을 살펴 보겠습니다.
Drag’n’Drop 알고리즘
기본 Drag’n’Drop 알고리즘은 다음과 같습니다.
- On
mousedown
– 이동을 위해 요소를 준비합니다. 필요합니다 (복제본 생성, 클래스 추가 등). - 그런 다음
mousemove
에서 withposition:absolute
. - On
mouseup
– 드래그 완료와 관련된 모든 작업 수행 ‘drop.
이것이 기본입니다. 나중에 현재 기본 요소를 드래그하는 동안 강조 표시하는 것과 같은 다른 기능에 대해 알아 보겠습니다.
공을 드래그하는 구현은 다음과 같습니다.
코드를 실행하면 이상한 것을 알아 차릴 수 있습니다. 드래그 앤 드롭이 시작될 때 볼이 “포크”됩니다. “복제본”을 드래그하기 시작합니다.
다음은 실제 예제입니다.
마우스로 드래그 앤 드롭을 시도하면 이러한 동작을 볼 수 있습니다.
브라우저가 자체적으로 이미지와 드래그 앤 드롭을 지원하기 때문입니다. 다른 요소. 자동으로 실행되며 Google과 충돌합니다.
사용 중지하려면 :
이제 모든 것이 정상입니다.
실행 중 :
또 다른 중요한 측면 – ball
가 아니라 document
에서 mousemove
를 추적합니다. 첫눈에 볼 때 마우스가 항상 공 위에있는 것처럼 보일 수 있으며 mousemove
를 그 위에 놓을 수 있습니다.
하지만 우리가 기억하는 것처럼 mousemove
는 자주 트리거되지만 모든 픽셀에 대해 트리거되지는 않습니다. 따라서 빠르게 움직 인 후에 포인터가 공에서 문서 중간 (또는 창 밖)의 어딘가에 점프 할 수 있습니다.
그러므로 document
에서 들어야합니다.
올바른 위치
위의 예에서 볼은 항상 움직여서 중심이 포인터 아래에 있습니다.
나쁘지는 않지만 부작용이 있습니다. 드래그 앤 드롭을 시작하려면 공의 아무 곳에서나 mousedown
할 수 있습니다. 그러나 가장자리에서 “점프”하면 공이 갑자기 “점프”하여 마우스 포인터 아래 중앙에 위치합니다.
포인터를 기준으로 요소의 초기 이동을 유지하는 것이 좋습니다.
예를 들어 공의 가장자리로 드래그하기 시작하면 드래그하는 동안 포인터가 가장자리 위에 있어야합니다.
알고리즘 업데이트 :
더 나은 위치를 가진 최종 코드 :
실행 중 (<iframe>
내부) :
공을 오른쪽 하단 모서리로 드래그하면 특히 두드러집니다. 이전 예에서 공은 포인터 아래로 “점프”합니다. 이제는 현재 위치에서 포인터를 유창하게 따라갑니다.
잠재적 드롭 대상 (드롭 가능)
이전 예제에서 볼은 머무르기 위해 “어디서나”떨어집니다 실생활에서 우리는 일반적으로 한 요소를 다른 요소에 드롭합니다. 예를 들어, “파일”을 “폴더”또는 다른 것에 넣습니다.
추상적으로 말하면 “드래그 가능한”요소를 “드롭 가능한”요소에 드롭합니다.
우리는 알아야 할 사항 :
- 요소가 Drag’n’Drop 끝에 드롭 된 위치 – 해당 작업을 수행하기 위해
- 그리고 바람직하게는 드롭 가능한 항목을 알고 있어야합니다. 강조 표시하기 위해 드래그합니다.
솔루션은 흥미롭고 약간 까다 롭습니다. 여기서 다루겠습니다.
첫 번째 아이디어? 잠재적 인 droppable에 mouseover/mouseup
핸들러를 설정해야할까요?
하지만 작동하지 않습니다.
문제는 드래그하면 드래그 가능한 요소가 항상 다른 요소 위에 있습니다.마우스 이벤트는 맨 위 요소에서만 발생하며 그 아래에는 발생하지 않습니다.
예를 들어, 아래에는 두 개의 <div>
요소가 있으며 파란색 위에 빨간색 하나가 있습니다. 하나 (완전히 덮음). 빨간색이 상단에 있기 때문에 파란색 이벤트를 잡을 방법이 없습니다.
드래그 가능한 요소도 마찬가지입니다. 공은 항상 다른 요소 위에 있으므로 이벤트가 발생합니다. 하위 요소에 어떤 핸들러를 설정하든 작동하지 않습니다.
그래서 잠재적 인 droppable에 핸들러를 배치하는 초기 아이디어가 실제로 작동하지 않습니다. 실행되지 않습니다.
어떻게해야합니까?
document.elementFromPoint(clientX, clientY)
라는 메서드가 있습니다. 주어진 창 상대 좌표에서 가장 많이 중첩 된 요소를 반환합니다 (또는 주어진 좌표가 창 밖에있는 경우 null
).
우리는 다음과 같이 포인터 아래에 놓을 수있는 가능성을 감지하는 마우스 이벤트 핸들러 :
참고 : (*)
를 호출하기 전에 공을 숨겨야합니다. 그렇지 않으면 포인터 아래의 맨 위 요소 인 elemBelow=ball
이므로 일반적으로 이러한 좌표에 공이 있습니다. 그래서 우리는 그것을 숨기고 즉시 다시 보여줍니다.
우리는 우리가 “날아가는”요소를 언제든지 확인하기 위해이 코드를 사용할 수 있습니다. 그리고 그것이 발생했을 때 드롭을 처리 할 수 있습니다.
“드롭 가능한”요소를 찾기위한 onMouseMove
의 확장 코드 :
공이 축구 목표 위로 드래그 될 때 아래 예에서 목표가 강조 표시됩니다.
이제 전체 프로세스 동안 변수 currentDroppable
에 현재 “드롭 대상”이 있으며이를 사용하여 강조 표시하거나 기타 사항
요약
기본 Drag’n’Drop 알고리즘을 고려했습니다.
핵심 구성 요소 :
- 이벤트 흐름 :
ball.mousedown
→document.mousemove
→ball.mouseup
(네이티브를 취소하는 것을 잊지 마세요.ondragstart
). - 드래그 시작시 – 요소를 기준으로 포인터의 초기 이동을 기억하십시오.
shiftX/shiftY
드래그하는 동안 유지합니다. - 드롭 가능한 요소 감지 및
document.elementFromPoint
를 사용하여 포인터를 가져옵니다.
우리는이 기초 위에 많은 것을 놓을 수 있습니다.
-
데이터를 변경하고 요소를 이동하는 등 지능적으로 드롭을 마무리 할 수 있습니다.
- 비행중인 요소를 강조 표시 할 수 있습니다.
- 우리는 특정 영역이나 방향으로 드래그를 제한 할 수 있습니다.
-
mousedown/up
에 이벤트 위임을 사용할 수 있습니다.event.target
를 확인하는 대 면적 이벤트 핸들러는 수백 개의 요소에 대한 Drag’n’Drop을 관리 할 수 있습니다. - 등.
그 위에 아키텍처를 구축하는 프레임 워크가 있습니다 : DragZone
, Droppable
, Draggable
및 기타 클래스. 대부분은 위에서 설명한 것과 비슷한 작업을 수행하므로 이제 이해하기 쉬울 것입니다. 또는 제 3 자 솔루션을 채택하는 것보다 쉽게 수행 할 수 있다는 것을 알 수 있듯이 직접 굴려보세요.