1. 드래그 구현

마우스를 누른 상태에서 움직이면 선택한 요소가 함께 이동하는 것을 드래그라고 한다. 이런 드래그 기능을 구현하기 위해서는 다음의 3가지 마우스 이벤트를 사용하면 된다.

mousedown - 드래그할 객체를 선택할때 사용
mousemove - 객체를 드래그할 때 사용
mouseup - 드래그를 종료할 때 사용 


mousedown  발생하면 
드래그할 요소지정, 마우스 포인트와 요소 좌측상단 사이의 거리 저장
document 객체에 mousemove와 mouseup 이벤트를 등록한다
이벤트 전파를 중지.


mousemove 발생
드래그 할 요소 위치를 이동, 이 때 앞서 저장한 마우스 포인트와 요소 좌측 상단 사이의 거리값을 사용.
이벤트 전파를 중지.

mouseup 발생
드래그 중이 아닌 것으로 지정
이벤트 전파 중지

가장 먼저 할 작업은 드래그로 이동하길 원하는 요소에 mousedown 이벤트 핸들러를 등록하는 것이다. mousedown 이벤트가 발생하면 해당 요소를 드래그 할 것이라고 표시하게 된다. 이때 마우스 포인터와 드래그 요소의 좌측 상단 사이의 거리를 저장해야 한다. 그 이유는 마우스를 움직일 때 알맞게 요소를 이동시키기 위해서 이다. 그 이유는 마우스를 움직일 때 알맞게 요소를 이동시키기 위해서 이다.

마우스가 이동하면 요소의 좌측 상단을 마우스 이동한 거리에 비례해서 이동시켜 주어야 하는데, 드래그할 요소를 선택할 때 마우스 포인터와 요소 좌측 상단사이의 거리를 저장하지 않는다면 비례해서 이동할 수 없을 것이다.

실제로 드래그 기능을 어떻게 구현하는지 SimpleDragSource 모듈을 통해서 살펴보자.

1.1 단순 드래그를 지원하는 SimpleDragSource 모듈 작성하기

이번 절에서는 다음과 같은 코드만 실행하면 관련 요소를 드래그할수 있도록 해주는 SimpleDragSource를 만들어 보기로 한다.

var drag  = new ajax.dnd.SimpleDragSource("car");


dnd.js


  
        ajax.dnd = {};
        ajax.dnd.SimpleDrag = function (elementid) {
        this.element = document.getElementById(elementid);  //드래그 가능하게 할요소구함
        this.dragging = false; //현재 드래그 중인지 여부 표시
        this.selected = false; //현재 마우스 다운 상태인지 표시
        this.diff = null;         //마우스 위치와 객체 위치
        
        this.mouseDown = ajax.Event.bindAsListener(this.doMouseDown, this);
        this.mouseMove = ajax.Event.bindAsListener(this.doMouseMove, this);
        this.mouseup = ajax.Event.bindAsListener(this.doMouseUp, this);
        
        ajax.Event.addListener(this.element, "mousedown",this.mouseDown);
        //드래그할 요소에 mousedown 이벤트 등록
       }
       
       ajax.dnd.SimpleDrag.prototype = {
       
         doMouseDown : function(e) {
            var event = window.event || e;
            if(!ajax.Event.isLeftButton(event))           return;
         this.selected = true; //드래그 하기 위해 선택한 상태로 표시
         
         //드래그할 요소와 마우스 포인터 사이의 거리를 구해서 저장
        var elementXY = ajax.GUI.getXY(this.element);
         var mouseXY = ajax.Event.getMouseXY(event);
         this.diff = {
            x: mouseXY.x - elementXY.x,
            y: mouseXY.y - elementXY.y
            
            };
            
          ajax.Event.addListener(document, "mousemove", this.mouseMove);
          ajax.Event.addListener(document, "mouseup" , this.mouseUp);
          //document에 mousemove와 mouseup 핸들러 추가
          ajax.Event.stopEvent(event);
         
         },
         
        doMouseMove: function(e) {         //mousedown 처리 후, mousemove 발생하면 호출
           if(!this.selected) return false; //선택된 상태가 아니면 이동시키지 않음
         
         if(!this.dragging) {
            this.dragging = true;
            ajax.GUI.setOpacity(this.element, 0.60);  
            }
            // 첫 번째 mousemove 발생시 드레그 상태로 변경하고, 요소를 투명하게 처리
            
           var event = window.event || e;
           var mouseXY = ajax.Event.getMouseXY(event);
           var newXY = {
              x: mouseXY.x - this.diff.x,       //마우스 위치에서 라인 25에서 저장한 거리 값을 빼서 요소의 새로운 위치를 구함
              y: mouseXY.y - this.diff.y
            }
           ajax.GUI.setXY(this.element, newXY.x, newXY.y); //위치변경
           
           ajax.Event.stopEvent(event);
        },
        
        doMouseUp: function(e) {        // mousedown 처리 후, mouseup 발생하면 호출
            if(!this.selected) return;
            
            this.selected = false;  //선택되지 않은 상태로 변경하고 앞서 구한 마우스와의 거리 값도 없앰
            this.diff = null;
            
            var event = window.event || e;
            if(this.dragging) {
                this.dragging = false;
                ajax.GUI.setOpacity(this.element, 1.0); //드레그 중이었으면 드레그 상태 아니라고 표시하고, 요소를 불투명하게 처리
            }
            
            ajax.Event.removeListener(document, "mousemove", this.mouseMove);
            ajax.Event.removeListener(document, "mouseup" , this.mouseUp);
            ajax.Event.stopEvent(event);
        }
      }  


SimpleDrag  클래스의 생성자에서 드래그할 요소에 mousedown 이벤트 핸들러를 등록한다. 사용자가 드래그할 요소에서 mousedown 이벤트를 발생 시키면 doMouseDown 함수가 호출된다.

doMouseDown 함수는 드래그 요소가 선택되었다는 것을 나타내기 위해 this.selected 변수 값을 true로 할당한다. 그런 뒤, 마우스 포인터와 드래그 요소 사이의 거리를 구해서 this.diff에 저장한다. 마지막으로 document 객체에 mousemove 이벤트 핸들러와 mouseup 이벤트 핸들러를 등록하고 이벤트 전파를 중지시킨다.

이제 사용자가 마우스를 이동하면 doMouseMove 함수가 호출된다. doMouseMove 함수는 드래그 요소를 선택한 이후(즉, mousedown 이벤트 발생 이후) 처음 마우스를 이동한 경우, 드래그 상태임을 표시하기 위해 this.dragging 변수 값을 true로 지정한다. 이때 요소를  토명하게 함으로써 이동 중임을 시각적으로 알 수 있게 하였다. 이후 mousedown 이벤트가 발생하면 this.dragging 값이 true 이므로 ,
    if(!this.dragging) {
            this.dragging = true;
            ajax.GUI.setOpacity(this.element, 0.60);  
            }
라인은 더이상 실행되지 않는다.

doMouseMove 함수는 this.dragging 값을 판단한 후, 마우스 포인터의 위치를 구한다. 마우스 포인터의 위치로부터 this.diff에 저장된 값을 빼서 드래그 요소의 새위치를 구한다. 그런 뒤 요소를 새로운 위치로 이동한다.

마우스를 이동하다가 버튼을 떼면 doMouseUp 함수가 호출된다. doMouseUp 함수는 현재 드래그 중인지의 여부를 판단한다. 그 이유는 마우스 버튼을 누른 뒤, 마우스를 이동하지 않으면 마우스가 드래그 중이지 않았으므로 이동과 관련된 마무리 처리를 할 필요가 없기 때문이다. 드래그 중이었다면 this.dragging의 값을 false로 지정해서 드래그 중이 아닌 상태로 변경하고, 드래그 중에 요소를 투명하게 설정했으므로 요소를 불투명하게 변경한다.

마지막으로 document 등록했던 mousemove 이벤트 핸들러와 mouseup 이벤트 핸들러를 등록한다. 만약 이 두 이벤트 핸들러를 제거하지 않으면, 드래그 중인지에 상관업이 마우스가 이동되거나 버튼을 뗄 때마다 이 두 이벤트 핸들러가 호출되어 불필요하게 자원을 소모하게 된다.

SimpleDrag.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="SimpleDrag.aspx.cs" Inherits="SimpleDrag" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>제목 없음</title>
    <script type="text/javascript" src="ajax.js"></script>
    <script type="text/javascript" src="dnd.js"></script>
    <script type="text/javascript">
    window.onload = function() {
        var drag1 = new ajax.dnd.SimpleDragSource("car");
        var drag2 = new ajax.dnd.SimpleDragSource("navi");
    
    }
    </script>
    <style type="text/css">
    #navi {
        position: absolute;
        background-color: #aaa;
        left:200px top:90px;
        width: 150px; height: 80px;
       }
    </style>
</head>
<body>
    <form id="form1" runat="server">
    <img src="car.jpg" id="car"/>
    자동차 이미지를 생각해봅시다.
        <div id="navi">
     플로팅 메뉴<br/>
     메뉴1<br/>메뉴2
     </div>
        </form>
</body>
</html>

실행결과


드래그 후


출처 : Ajax/최범균님의 AjaxProgramming 다시읽기




블로그 이미지

클라인STR

,