안녕하세요 정말 오랜만에 포스팅을 하는거 같습니다...
회사일이 너무 바쁜것..
이번 포스팅에서는 HTML5 에서 제공하는 Drag and Drop 에 대해서 작성할 예정입니다.
물론 테스트 브라우저는 Chrome 입니다.
우선적으로 HTML5에 drag and drop 에 대한 mdn 주소입니다.
// HTML5 drag and drop MDN
https://developer.mozilla.org/ko/docs/Web/API/HTML_%EB%93%9C%EB%9E%98%EA%B7%B8_%EC%95%A4_%EB%93%9C%EB%A1%AD_API
우선 드래그를 하기 위한 target 데이터와 드롭을 할수 있는 드롭 존 2개를 만들어 보도록 하겠습니다.
자 이렇게 2개의 div를 만들었습니다. (HTML 코드는 볼수 있도록 아래에 적어 놓겠습니다.)
해당 Drag Target을 드래그하여 초록색 Drop Zone 에 넣을 겁니다.
일단 그냥 드래그를 해볼까요?
역시 안됩니다.
드래그하기 위해서는 draggable 속성을 true로 주어야 합니다.
그런데 여기서 특이점이 제가 dragtarget을 일부러 2개의영역으로 잡았습니다.
반반씩 있는 영역이 아니라 dragtarget이라는 영역 내부에 dragInner를 넣은 형태 입니다.
<div class="dragtarget">
<div class="dragInner">
Drag Target
</div>
</div>
코드는 이와 같습니다.
이렇게 한 이유는 조금있다 알수 있습니다.
드래그포인트는 dragInner 에만 줄려고 합니다. 다른 영역은 드래그는 대부분 제목 표시줄에만 되는경우가 많으니까요
자 드래그를 해봅시다
드래그가 되긴 하는데 썸네일이 조금 맘에 안드네요 ( draggable이 dragInner에만 들어가있어서 해당 객체에 대한 썸네일만 제공됩니다.)
최대 root객체를 지정하여서 다 같이 나오게 하고 싶은데요 이부분을 처리 해주는 곳이 setDragImage입니다. (IE에선안됩니다. )
테스트용이기 때문에 div 태그 안에 inline 으로 ondragstart 함수를 하나 만들어 줍니다.(태그안에 ondragstart같이 넣는 방법은 좋은 방법은 아닙니다. 지금은 테스트용이기 때문에 이렇게 작성합니다.
> addEventListener('dragstart',dragStart,false); 와 같은 형식을 취하는게 더 좋습니다.
div class="dragtarget">
<div class="dragInner" draggable="true" ondragstart="dragStart_(event)"
ondrag="drag_(event)">
Drag Target
</div>
</div>
function dragStart_(e){
console.warn('drag Start');
}
function drag_(e){
console.log("drag");
}
와 같은 형태로 작성을 해줍니다.
잘 되는 점확인이 됩니다. 이제 썸네일 부터 바꿔 보겠습니다.
event로 들어오는 값을 이용해서 작성 합니다.
function dragStart_(e){
console.warn('drag Start');
var parentNode = e.target.parentElement;
e.dataTransfer.setDragImage(parentNode,0,0);
}
setDragImage의 첫번째 인자로는 썸네일 을 받게되는데
event.dataTransfer.setDragImage(image, xOffset, yOffset);
를 확인해보면 image를 dragInner가 아닌 부모의 값 전체를 선택하게 하고 오프셋 x와 y 를 0으로 주게되면 현재 마우스의 위치에서 바로 부모의 객체가 나타날것으로 보입니다.
짜잔 ㅎㅎ 부모의 객체를 그대로 썸네일 형태로 가져와서 사용하게 됩니다.
이제 드래그가 가능한 상태가 되었고 해당 객체를 Drop Zone 에넣어 줘야 되는데요 아무리 이동을 해도 넘어가지 않습니다.
드래그가 가능하기 위해서 draggable 속성을 주게 되는데 드롭도 마찬 가지입니다. droppable 이라는 속성이 필요합니다.
<div class ="dropzone" droppable="true"> Drop Zone </div>
dropzone 에도 추가 해줍니다.
draggable ondragstart , ondrag 가 짬뽕이였듯이
droppable ondrop , ondragover 가 짬뽕입니다.
<div class ="dropzone" droppable="true" ondragover="dragOver_(event)"
ondrop="drop_(event)"> Drop Zone </div>
function dragOver_(e){
console.log('dragOver');
}
function drop_(e){
console.log("drop");
}
하고 드래그앤 드롭시 보면 drop 이 발생하지 않는 점을 확인 하실수 있습니다.
mdn 에 는 dragover시 drop 을 활성화 하기위한 2가지 방법을 제시하고있습니다.
<div ondragover="return false">
<div ondragover="event.preventDefault()">
Calling the preventDefault()
method during both a dragenter
and dragover
event will indicate that a drop is allowed at that location. However, you will commonly wish to call the preventDefault()
method only in certain situations, for example, only if a link is being dragged.
저는 event.preventDefault 로 처리하였는데 대부분 이 방식대로 처리 한다고 합니다.
Drop 처리가 되는 점을 확인 하실 수 있습니다.
하지만 실제 설정한 target이 이동되지는 않았기 때문에 이 이동에 대한 내용을 다음 에 작성 하겠습니다.
감사합니다.
코드
<!DOCTYPE html>
<html>
<head>
<title> 드래그앤드롭 </title>
<meta charset="utf-8">
<style>
.dragtarget{
width:100px;
height:100px;
background-color:tomato;
}
.dragInner{
width:inherit;
height:30px;
background-color:slateblue;
color:white;
}
.dropzone{
position:absolute;
width:500px;
height:500px;
background-color:yellowgreen;
left:300px;
top:300px;
}
</style>
</head>
<body>
<div class="dragtarget">
<div class="dragInner" draggable="true" ondragstart="dragStart_(event)" ondrag="drag_(event)">
Drag Target
</div>
</div>
<div class ="dropzone" droppable="true" ondragover="dragOver_(event)" ondrop="drop_(event)"> Drop Zone </div>
<script>
function dragStart_(e){
console.warn('drag Start');
var parentNode = e.target.parentElement;
e.dataTransfer.setDragImage(parentNode,0,0);
}
function drag_(e){
console.log("drag");
}
function dragOver_(e){
e.preventDefault();
console.log('dragOver');
}
function drop_(e){
console.log("drop");
}
</script>
</body>
</html>