오브젝트 이동 시 가이드라인 표시 기능

편집을 편리하게 해주는 가이드라인 기능

XELF에서는 간편하게 문서를 편집할 수 있습니다. 특히 오브젝트의 위치나 크기를 마우스 드래그만으로 조정할 수 있어서 간편합니다. 하지만 마우스 드래그에도 단점이 있는데요. 바로 조정한 값이 정확하지 않거나 일정하지 않다는 것입니다. 물론 XELF에서는 속성 패널에서 직접 수치를 입력하는 편집 방법도 제공하고 있습니다. 세밀한 조정이 필요할 때는 속성을 직접 입력해야겠죠. 그렇지만 XELF에서는 마우스 드래그만으로도 최소한의 정확도를 유지할 수 있도록 두 가지 편리한 기능을 제공하고 있습니다. 가이드라인과 스냅입니다. 가이드라인은 오브젝트가 그리드, 다른 오브젝트와 라인이 일치할 때 표시를 해주는 기능이고, 스냅은 오브젝트가 그리드, 다른 오브젝트와 가까워지면 딱 붙여주는 기능입니다. 가이드라인과 스냅 기능 덕분에 오브젝트의 편집이 한결 편리해집니다.

가이드라인 기능의 구현

가이드라인 기능을 구현해보겠습니다. XELF에서 제공하는 가이드라인의 모든 기능을 구현하지 않고 오브젝트의 이동 시 그리드와의 가이드라인 기능만 구현해보겠습니다. 코드 작성에 들어가기 전에 우선 구현 순서를 생각해보겠습니다.

1. 오브젝트와 가이드라인의 레이어 분리
2. 가이드라인 지우기
3. 가이드라인 그리기
4. 오브젝트가 이동할 때 가이드라인 그리기

간단하게 네 단계로 나눌 수 있으며 각 단계에 맞춰 상세한 구현에 들어가도록 하겠습니다.

오브젝트와 가이드라인 레이어 분리

오브젝트와 가이드라인이 한 공간에 섞여있으면 코드 구현 시 어려움이 발생할 수 있습니다. 역할 별, 기능 별로 분리해서 정리하는 것이 좋습니다.

<div id="object-layer">
 <div id="obj"></div>
 </div>
 <div id="guideline-layer">
 </div>

오브젝트가 있는 공간을 object-layer, 가이드라인이 있는 공간을 guideline-layer라는 id를 붙이고 나눴습니다. 가이드라인 레이어의 경우 자식으로 엘리멘트를 아무것도 가지고 있지 않습니다. 다음 단계에서 구현할 가이드라인 지우기, 그리기 기능에서 가이드라인을 가이드라인 레이어에 추가하고 삭제하게 됩니다.

가이드라인 지우기

가이드라인 그리기가 있다면 당연히 가이드라인 지우기가 있어야 하겠죠? 가이드라인 그리기를 구현하기 전에 가이드라인 지우기를 먼저 구현하겠습니다.

function removeAllGuideLines() {
 $('#guideline-layer').empty();
 }

간단하게 구현되었습니다. 오브젝트 레이어와 가이드라인 레이어를 기능과 역할에 맞게 이미 분리했습니다. 가이드라인 레이어를 분리함으로써 가이드라인 레이어 내부에는 가이드라인만 존재한다는 것이 보장되었습니다. 따라서 가이드라인 레이어 내부의 자식 엘리멘트를 모두 지우면 가이드라인이 모두 지워지게 됩니다.

가이드라인 그리기

가이드라인 그리기는 지우기와 다르게 조금 복잡합니다. 먼저 그리드의 좌표를 알아야 하고 오브젝트의 좌표를 알아야 하고 이미 그려진 가이드라인을 지워야 하고 그리드의 좌표와 오브젝트의 좌표가 일치하는지 알아야 하고 일치하는 좌표에 맞게 가이드라인을 그려야 합니다. 문장으로 보니 복잡하네요. 다시 정리해보겠습니다.

1. 그리드의 좌표 확인
2. 오브젝트의 좌표 확인
3. 이미 그려진 가이드라인 지우기
4. 그리드와 오브젝트의 좌표가 일치하는지 확인
5. 일치하는 위치에 가이드라인 그리기

번호를 붙여 하나씩 정리하니까 한결 보기 편해졌습니다. 위 조건에 맞춰 코드를 작성해보겠습니다.

function drawGuideLines(objectPoints) {
 // 1. 그리드의 좌표 확인
 var gridXPoints = [0, 100, 200, 300, 400, 500];
 var gridYPoints = [0, 100, 200, 300, 400, 500];

// 2. 오브젝트의 좌표 확인
 var objectXPoints = objectPoints.xPoints;
 var objectYPoints = objectPoints.yPoints;

// 3. 이미 그려진 가이드라인 지우기
 removeAllGuideLines();

// 4. 그리드와 오브젝트의 좌표가 일치하는지 확인
 for (var i = 0; i < objectXPoints.length; i++) {
 for (var j = 0; j < gridXPoints.length; j++) {
 var objectXPoint = objectXPoints[i];
 var gridXPoint = gridXPoints[j];

// 5. 일치하는 위치에 가이드라인 그리기
 if (objectXPoint === gridXPoint) {
 $('#guideline-layer').append(
 $('<div>')
 .addClass('guideline vertical')
 .css('left', gridXPoint)
 );
 }
 }
 }

// 4. 그리드와 오브젝트의 좌표가 일치하는지 확인
 for (var i = 0; i < objectYPoints.length; i++) {
 for (var j = 0; j < gridYPoints.length; j++) {
 var objectYPoint = objectYPoints[i];
 var gridYPoint = gridYPoints[j];

// 5. 일치하는 위치에 가이드라인 그리기
 if (objectYPoint === gridYPoint) {
 $('#guideline-layer').append(
 $('<div>')
 .addClass('guideline horizontal')
 .css('top', gridYPoint)
 );
 }
 }
 }
 }

그리드의 X, Y 좌표는 0부터 500까지 100 간격으로 이루어져 있다고 가정했습니다. 또 오브젝트의 경우 X좌표 최소, 최대, Y좌표 최소, 최대로 이루어져 있다고 가정했습니다. 위의 구현 조건에 맞춰 코드를 구현하였습니다. 실제로 가이드라인을 그리는 부분을 보면 css의 left나 top 값만 지정했습니다. 대신 색깔 모양 등 항상 고정된 속성은 코드로 처리하지 않고 class를 지정하여 처리하도록 했습니다.

.guideline {
 background-color: #5f3dc4;
 }

.vertical {
 width: 1px;
 height: 500px;
 }

.horizontal {
 height: 1px;
 width: 500px;
 }

오브젝트가 이동할 때 가이드라인 그리기

오브젝트가 이동할 때 가이드라인을 그리게 하려면 어떻게 해야 할까요? 마우스 무브 이벤트가 발생할 때 가이드라인을 그리면 됩니다.
오브젝트를 이동시키려면 어떻게 해야 할까요? 이전에 작성한 웹 브라우저에서 오브젝트를 이동시키기 위한 마우스 이벤트 처리 방법 포스트를 참조해주세요.

 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)
 });

// 여기에 가이드라인 그리기 추가
 var minX = $(target).offset().left;
 var maxX = minX + $(target).width();
 var minY = $(target).offset().top;
 var maxY = minY + $(target).height();

drawGuideLines({
 xPoints: [minX, maxX],
 yPoints: [minY, maxY]
 });

}, 1000 / 30);

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

// 여기에 가이드라인 지우기 추가
 removeAllGuideLines();
 }

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

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

오브젝트를 이동시키는 코드에 가이드라인을 그리는 코드를 추가했습니다. 오브젝트의 X좌표 최대, 최솟값과 Y좌표 최대, 최솟값을 파라미터로 받아 가이드라인을 그리는 함수를 실행시켰고 오브젝트의 이동이 종료되었을 때 이미 그려진 가이드라인을 지우는 함수를 실행시켰습니다.

오브젝트의 이동 시 가이드라인 표시

지금까지 오브젝트의 이동 시 가이드라인 표시 기능을 구현해보았습니다. 사실 가이드라인 기능만으로는 사용자에게 편리성을 충분히 제공해주지 못 합니다. 그리드와 오브젝트가 정확히 일치해야 가이드라인이 표시되기 때문이죠. 스냅 기능과 동시에 실행된다면 오브젝트가 그리드와 가까워지면 그리드에 붙으면서 가이드라인이 표시됩니다. 오브젝트를 정확하고 일정한 위치로 이동시킬 수 있죠. XELF에서 가이드라인과 스냅 기능을 동시에 제공하고 있습니다. XELF에서 간편하게 문서를 작성해보시기 바랍니다.