웹 브라우저에서 오브젝트를 이동시키기 위한 마우스 이벤트 처리 방법

오브젝트의 자유로운 이동과 모양 변경

XELF에서는 마우스를 이용해 오브젝트를 이동시키거나 크기 변경, 회전 등을 할 수 있습니다. 다른 프로그램들과 사용법을 비교해봤을 때 비슷한 점이 많기 때문에 처음 XELF를 접하거나 다른 프로그램에 익숙한 사용자들이 친숙하게 사용할 수 있습니다. 그렇다면 웹 브라우저에서 사용자의 마우스 입력을 어떻게 받고 처리하는 것일까요? 웹 브라우저에서 마우스 입력을 처리하는 방법에 대해 알아보겠습니다.

<XELF에서 오브젝트의 자유로운 이동 및 모양 변경>

마우스 이벤트

마우스 드래그로 오브젝트를 이동시키는 과정은 총 세 단계로 나뉩니다. 오브젝트의 이동을 시작하는 마우스 다운(mousedown), 오브젝트를 이동시키는 마우스 무브(mousemove), 오브젝트의 이동을 종료하는 마우스 업(mouseup)입니다. 마우스 다운, 무브, 업은 각각 이벤트 리스너를 할당하여 감지하고 이벤트 핸들러를 실행하여 처리할 수 있습니다. 마우스의 이벤트 핸들러는 파라미터로 마우스 이벤트 객체를 받습니다. 마우스 이벤트 객체에는 마우스의 위치, 입력된 버튼 종류 등의 정보를 가지고 있습니다. 마우스 이벤트에 대한 리스너, 핸들러, 이벤트 객체를 조합하면 마우스 드래그로 오브젝트를 이동시키는 프로그램을 만들 수 있습니다.

구현

위에서 알아본 것을 조합하면 오브젝트를 이동시키는 프로그램을 만들 수 있습니다. 오브젝트를 이동시키는 총 세 단계 과정을 단계별로 알아보겠습니다.

마우스 다운(mousedown)

마우스 다운 단계는 초기화를 하는 과정입니다. 이동시키려는 오브젝트와 마우스 포인터의 시작 위치를 저장해야 합니다. 그리고 마우스 무브와 업 단계를 담당할 이벤트 리스너를 할당해야 합니다.

  • 타겟 오브젝트 저장
  • 타겟 오브젝트의 시작 위치 저장
  • 마우스 포인터의 시작 위치 저장
  • 마우스 무브, 업 이벤트 리스너 할당
// 타겟, 마우스 포인터의 시작 위치 등에 대한 변수 선언
var target = null;
var startX = null;
var startY = null;
var startLeft = null;
var startTop = null;

function handleMouseDown(event) {
 // 시작 위치 등 저장
 target = event.target;
 startX = event.clientX;
 startY = event.clientY;
 startLeft = target.offsetLeft;
 startTop = target.offsetTop;

// 마우스 무브, 업 이벤트 리스너 할당
 document.addEventListener('mousemove', handleMouseMove);
 document.addEventListener('mouseup', handleMouseUp);
}

마우스 무브(MOUSEMOVE)
마우스 무브 단계는 오브젝트를 이동시키는 과정입니다. 마우스 포인터의 현재와 시작 위치의 차이를 계산해서 타겟 오브젝트의 위치를 변경합니다.

  • 마우스 포인터의 시작 위치와 현재 위치의 차이 계산
  • 타겟 오브젝트에 변경된 위치 적용
FUNCTION HANDLEMOUSEMOVE(EVENT) {
// 현재 마우스 포인터 위치와 시작 위치를 이용해 계산
VAR CURRENTX = EVENT.CLIENTX;
VAR CURRENTY = EVENT.CLIENTY;
VAR DELTAX = CURRENTX - STARTX;
VAR DELTAY = CURRENTY - STARTY;
// 계산된 위치 값을 타겟에 설정
TARGET.STYLE.LEFT = (STARTLEFT + DELTAX) + 'PX';
TARGET.STYLE.TOP = (STARTTOP + DELTAY) + 'PX';
}

마우스 업(mouseup)
마우스 업 단계는 오브젝트의 이동을 종료하는 과정입니다. 마지막으로 오브젝트의 위치 값을 확정 짓고, 더 이상 오브젝트가 이동되지 않도록 하는 과정입니다.

  • 마우스 무브, 업 이벤트 리스너 해제
function handleMouseUp(event) {
 // 마우스 무브, 업 이벤트 리스너 해제
 document.removeEventListener('mousemove', handleMouseMove);
 document.removeEventListener('mouseup', handleMouseUp);
}

타겟 오브젝트에 이벤트 리스너 할당

지금까지 오브젝트를 이동시키는 각 단계에 대한 이벤트 핸들러를 만들었습니다. 만든 이벤트 핸들러를 타겟 오브젝트의 이벤트 리스너에 할당시켜야 작동합니다.

코드 개선

위에서 작성한 코드는 전역 변수를 사용하고 브라우저 호환성 등을 생각하지 않았습니다. 또 마우스 무브 이벤트의 경우 발생 빈도가 높아서 성능 문제가 발생할 수 있습니다. 전역 변수의 경우 클로저화 하여 해결할 수 있고, 브라우저 호환성은 jQuery, 마우스 이벤트의 발생 빈도로 인한 성능 저하는 Lodash의 throttle을 이용하여 해결할 수 있습니다.

function handleMouseDown(event) {
 var target = event.target;
 var startX = event.clientX;
 var startY = event.clientY;
 var startLeft = parseInt($(target).css('left'), 10);
 var startTop = parseInt($(target).css('top'), 10);

var handleMouseMove = _.throttle(function handleMouseMove(event) {
 var currentX = event.clientX;
 var currentY = event.clientY;
 var deltaX = currentX - startX;
 var deltaY = currentY - startY;

$(target).css({
 left: (startLeft + deltaX),
 top: (startTop + deltaY)
 });
 }, 1000 / 30);

function handleMouseUp(event) {
 $(document).off('mousemove', handleMouseMove);
 $(document).off('mouseup', handleMouseUp);
 }

$(document).on('mousemove', handleMouseMove);
 $(document).on('mouseup', handleMouseUp); 
}

$('div').on('mousedown', handleMouseDown);

지금까지 마우스 드래그로 오브젝트를 이동시키는 방법에 대해 알아보았습니다. XELF에서는 오브젝트의 이동뿐만 아니라 다양한 기능을 마우스 클릭, 드래그만으로 사용할 수 있습니다. 다양한 기능을 제공하기 위해 다양한 코드로 이루어져 있죠. 위에서 알아본 것 외의 내용은 다음 기회에 소개하도록 하겠습니다.