프로그래밍/HTML+CSS+JavaScript
java script drag & drop
긴자손-1
2009. 10. 7. 11:37
반응형
출처 : http://gd452.springnote.com/pages/528849
Design
- http://www.webreference.com/programming/javascript/mk/column2/index.html
- DnD(Drag and Drop)을 구현하기 위해 다음의 정보를 알아야 한다.
- 마우스 커서가 현재 어디 있는지
- 언제 사용자가 item을 클릭했는지
- 클릭한 아이템을 Drag 하는지
- Drag 하면, 그 아이템을 움직여야 한다.
마우스 좌표를 얻기
- document.onmousemove = mouseMove;
function mouseMove(ev){
ev = ev || window.event;
var mousePos = mouseCoords(ev);
}
function mouseCoords(ev){
if(ev.pageX || ev.pageY){
return {x:ev.pageX, y:ev.pageY};
}
return {
x:ev.clientX + document.body.scrollLeft - document.body.clientLeft,
y:ev.clientY + document.body.scrollTop - document.body.clientTop
};
}
- IE의 경우 event object는 global이다. 그리고 window.event에 저장된다. Firefox나 다른 브라우져의 경우 이 event는 그 action이 실행될때 수행되는 함수에 전달된다.
- Firefox 나 기타 브라우져의 경우 document에 대한 상대좌표를 알기위해 pageX, pageY를 사용한다. 반면 MSIE의 경우 clientX, clientY를 사용한다.
- 마우스 포인트가 500x500의 윈도우에서 중앙에 있을 경우, Firefox의 경우, pageX, pageY가 250, 250이고 scroll down을 500px 했을 경우, 750이 된다. 반면 IE는 scroll down했을 경우 250으로 유지된다. 그 결과 scrollLeft, scrollTop을 붙여야 한다.
- IE의 경우 document의 원점이 0,0이 아니라 그것을 둘러싸고 있는 border(2px)만큼 크다. 이를 또한 빼주어야 한다.
==> 근데 막상 해보니 IE6.0에서는 Firefox랑 똑같다....
[edit]
마우스 클릭 잡아내기
- document.onmouseup, onmousedown에 우리가 원하는 함수를 붙이자. 이렇게 되면 모든 element에 대해 이벤트가 발생하니 Dragging을 원하는 Element에 함수를 붙이자.
- document.onmouseup = mouseUp;
var dragObject = null;
function makeDraggable(object){
object.onmousedown = function(){
dragObject = this;
}
}
function mouseUp(ev){
dragObject = null;
}
이동
- 이동을 위해 item의 position style이 absolute 여야 한다. 그리고, style.top, style.left를 set 해야 한다. 모든 마우스의 움직임은 페이지의 좌상단이 기준이 된다.
- document.onmousemove = mouseMove;
document.onmouseup = mouseUp;
var dragObject = null;
var mouseOffset = null;
function getMouseOffset(target, ev){
ev = ev || window.event;
var docPos = getPosition(target);
var mousePos = mouseCoords(ev);
return {x:mousePos.x - docPos.x, y:mousePos.y - docPos.y};
}
function mouseCoords(ev){
if(ev.pageX || ev.pageY){
return {x:ev.pageX, y:ev.pageY};
}
return {
x:ev.clientX + document.body.scrollLeft - document.body.clientLeft,
y:ev.clientY + document.body.scrollTop - document.body.clientTop
};
}
function getPosition(e){
var left = 0;
var top = 0;
while (e.offsetParent){
left += e.offsetLeft;
top += e.offsetTop;
e = e.offsetParent;
}
left += e.offsetLeft;
top += e.offsetTop;
return {x:left, y:top};
}
function mouseMove(ev){
ev = ev || window.event;
var mousePos = mouseCoords(ev);
if(dragObject){
dragObject.style.position = 'absolute';
dragObject.style.top = (mousePos.y - mouseOffset.y)+"px";
dragObject.style.left = (mousePos.x - mouseOffset.x)+"px";
return false;
}
}
function mouseUp(){
dragObject = null;
}
function makeDraggable(item){
if(!item) return;
item.onmousedown = function(ev){
dragObject = this;
mouseOffset = getMouseOffset(this, ev);
return false;
}
}
- mouseOffset 의 값은 선택한 item을 기준으로 어느 지점을 선택했느지를 알려준다. item 의 크기가 100x18이라면 내가 마우스를 클릭한 지점에 따라 mouseOffset이 달라진다.
-
offsetParent 는 offsetTop, offsetLeft속성들을 지정한 용기개체의 참조이다. 대부분의 경우 offsetParent는 body 개체를 반환한다. offsetTop과 offsetLeft는 현재 element가 offsetParent로 지정된 element에 대한 상대적인 위치를 나타낸다.
Dropping
- 여태까지의 예제를 통해 원하는 element를 옮길 수 있었다. 하지만 실제로 원하는 곳에만 Drag Drop이 가능하게 하려면 어찌하면 좋은가? 불행히도 Drag를 하고 있는 동안은 다른 element에 대해 어떤 mouse action도 불가능하다.
- 가능한 솔루션으로 우리가 Drag를 원하는 element와 Drop의 타겟이 되는 element에 영향을 주지 않는 방법을 살펴보자.
- 첫째로 Drop 타겟이 되는 리스트를 얻는다.
- 마우스가 release 된 순간, 마우스 포지션을 각각의 타겟 element위에 있는지 체크한다.
- 타겟 위에 있으면 Drop 한다.
function addDropTarget(dropTarget){
dropTargets.push(dropTarget);
}
function mouseUp(ev){
ev = ev || window.event;
var mousePos = mouseCoords(ev);
for(var i=0; i<dropTargets.length; i++){
var curTarget = dropTargets[i];
var targPos = getPosition(curTarget);
var targWidth = parseInt(curTarget.offsetWidth);
var targHeight = parseInt(curTarget.offsetHeight);
if(
(mousePos.x > targPos.x) &&
(mousePos.x < (targPos.x + targWidth)) &&
(mousePos.y > targPos.y) &&
(mousePos.y < (targPos.y + targHeight))){
// dragObject was dropped onto curTarget!
}
}
dragObject = null;
}
반응형