WEB개발이야기/웹퍼블리싱

javascript로 드레그가 가능한 HTML 요소 만들기

어쩌다보니여기까지~ 2019. 9. 30. 13:57
반응형

javascript로 HTML의 DIV를 드레그할 수 있게 하는 간단한 기능 구현입니다.
이와 비슷한 기능은 jquery UI에서 제공해 주고 있긴 하지만 드레그 기능 하나 구현하겠다고 jquery UI를 붙히기는 웬지 손해 보는 느낌입니다.
바닐라JS로 구현하는 코드와 설명입니다.

HTML

먼저 간단하지만 HTML 구성요소 입니다.

<div id="dragdiv">
</div>

CSS

CSS도 간단하게 구현합니다.
마우스가 해당 요소에 올라가때 화살표 마우스 표시가 이동이 가능한 표시로 바뀜니다.

#dragdiv {
  cursor: move;
}

javascript

핵심기능인 javascript 코드 입니다.
바닐라JS로 구현 시 3가지의 단계로 구현이 되면 하나씩 설명을 하겠습니다.

  1. 마우스로 요소를 클릭 할 때 기능 구현
  2. 클릭한 요소를 움직일 떄 기능 구현
  3. 움직인 요소를 놓았을 때 기능 구현

전체적인 구현 형태

전체적인 기능 구현은 아래와 같습니다.

function dragElement(elmnt) {
    var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0; // 해당 기능 전체에서 사용할 변수를 초기화 합니다. 
     elmnt.onmousedown = dragMouseDown; // 요소를 마우스로 눌렀을 경우 dragMouseDown()을 실행 시키게 됩니다 
      function dragMouseDown(e) {}
      function elementDrag(e) {}
      function closeDragElement() {}
}

1. 마우스로 요소를 클릭 할 때 기능 구현

마우스로 클릭한 요소를 놓았을 떄와 클릭한 요소를 움직일때 발생하는 이벤트를 다룹니다.

e = e || window.event;
||문법은 변수 선언할떄 앞의 값이 존재한다면 앞의 값을 선언하고 앞의 값이 없다면 뒤의 값을 선언하게 됩니다.
여기에서 e의 값이 있다면 그대로 e의 값을 사용하겠다는 뜻이고 만약 없다면 window.event값을 대신 사용하겠다는 뜻입니다.
예전에 나온 멍청한 Internet Explorere값을 발생시키지 않기 떄문에 크로스브라우징 차원으로 Internet Explorer에서 발생시키는 window.event를 대신 사용하겠다는 뜻입니다.

e.preventDefault();
기본 이벤트의 수행을 막습니다. 다시말해서 <a href="링크"> 일 때 클릭 시 실행되는 기본 이벤트 수행은 href에 적혀있는 링크 로 이동하는 것인데 이것을 무력화 시키겠다는 의미입니다. 일단 기본 기능은 막고 내가 작성한 javascript를 실행시킬때 많이 사용합니다.

function dragMouseDown(e) {
   e = e || window.event; // e값이 있는 경우 e 값을 그대로 사용하고 없는 경우 window.event값을 e 로 사용하겠다는 선언(Internet Explorer가 e가 없음)
   e.preventDefault(); // 일단 e의 기본 수행을 막습니다. 
   pos3 = e.clientX;  // 마우스 이벤트가 발생할 떄 마다 당시의 마우스 x좌표를 pos3에 저장합니다. 
   pos4 = e.clientY;  // 마우스 이벤트가 발생할 떄 마다 당시의 마우스 y좌표를 pos4에 저장합니다. 
   document.onmouseup = closeDragElement;   // 마우스 클릭을 해제 했을 떄 closeDragElement()을 호출합니다 
   document.onmousemove = elementDrag;      // 마우스를 움직일때 elementDrag()을 호출합니다. 
}

2. 클릭한 요소를 움직일 떄 기능 구현

클릭한 마우스를 움직일때 발생하는 이벤트로 실제 요소를 마우스를 따라 움직이게 합니다.

function elementDrag(e) {
    e = e || window.event; // e값이 있는 경우 e 값을 그대로 사용하고 없는 경우 window.event값을 e 로 사용하겠다는 선언(Internet Explorer가 e가 없음)
    e.preventDefault(); // 일단 e의 기본 수행을 막습니다. 
    pos1 = pos3 - e.clientX;  // 기존의 마우스 위치값을 비교하여 움직인 새로운 x좌표를 구하여 pos1에 저장합니다. 
    pos2 = pos4 - e.clientY;  // 기존의 마우스 위치값을 비교하여 움직인 새로운 y좌표를 구하여 pos2에 저장합니다. 
    pos3 = e.clientX;         // 다시 새로운 x좌표를 pos3에 저장합니다. 
    pos4 = e.clientY;         // 다시 새로운 y좌표를 pos3에 저장합니다. 
    elmnt.style.top = (elmnt.offsetTop - pos2) + "px";      // 요소의 y위치를 변경합니다. (마우스에 따라 요소가 y방향으로 움직입니다)
    elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";    // 요소의 x위치를 변경합니다. (마우스에 따라 요소가 x방향으로 움직입니다)
}

3. 움직인 요소를 놓았을 때 기능 구현

클릭되어 있는 마우스를 놓았을 때 발생하는 이벤트로 기능을 해제 하고 위치좌표값을 얻을 수 있습니다.

function closeDragElement() {
   document.onmouseup = null;   // onmouseup을 초기화 시킴니다. 
   document.onmousemove = null; // onmousemove을 초기화 시킴니다. 
   console.log("현재 요소의 위치 y는 " + elmnt.top +", x는" + elmnt.left  + "입니다.");
}

합쳐진 전체 코드는 아래와 같습니다.

function dragElement(elmnt) {
   var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0; 
   elmnt.onmousedown = dragMouseDown;

   function dragMouseDown(e) {
      e = e || window.event;
      e.preventDefault(); 
      pos3 = e.clientX;
      pos4 = e.clientY; 
      document.onmouseup = closeDragElement;
      document.onmousemove = elementDrag;
   }

   function elementDrag(e) {
      e = e || window.event;
      e.preventDefault();
      pos1 = pos3 - e.clientX;
      pos2 = pos4 - e.clientY;
      pos3 = e.clientX;
      pos4 = e.clientY; 
      elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
      elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
   }

   function closeDragElement() {
      document.onmouseup = null;
      document.onmousemove = null;
      console.log("현재 요소의 위치 y는 " + elmnt.top +", x는" + elmnt.left  + "입니다.");
   }
}

기능수행

마지막으로 위의 작성된 javascript 기능(functin)을 실행시킴니다.

// 기능 실행
dragElement(document.getElementById("mydiv"));

기타

해당 기능은 jquery UI의 dragable()로도 구현 가능합니다.

$( "#dragdiv" ).draggable();

참조

위의 코드는 아래의 w3schools의 코드를 참조했습니다.

https://www.w3schools.com/howto/howto_js_draggable.asp 참조