Javascript를 이용한 DIV 이동 알고리즘
- 정재욱(커뮤니티본부 개발2팀), 2006년 11월?
UCC에 대한 좋은 검색질을 위해선 사용자 데이타를 위미있는 정보로 유지하기 위한 노력이 계속되고 있다. 이를 위해 블로그 테마 서비스가 기획되었고 의미있는 데이타를 추출하기 위해 템플릿 방식을 사용하였으며 그에 따라 사용자의 자유도를 높이기 위한 기능을 구현하게 되었다. Web2.0에 맞추어 블록간의 이동을 구현하였는데 이 블록 단위는 DIV Element였으며, 이동하고자 하는 위치를 선정하고 선정된 위치에 알맞게 DIV Element를 변경하였다. 현재 서비스되고 있는 블로그의 Theme에 적용 되어 있으며, 아직 초기 단계라 부족한 부분이 많지만 계속적인 업그레드 작업이 이루어질 예정이다.
서론 #
- 템플릿 방식의 Theme Editor의 자유도를 주기 위하여 블록 단위 이동 기능이 필요했다.
- 마우스를 이용하여 이동하고자 하는 위치에 블록을 놓으면 높여진 위치 정보를 계산해야 한다.
- 높여진 위치가 지정되면 그 위치에 들어갈수 있도록 HTML Element를 변경해야 한다.
DIV 이동을 위한 기본 가정 #
- 이동을 블록 단위로 한다.
- 블록은 DIV Element이다.
- 블록을 싸고 있는 Element 역시 DIV 이며 이를 Parent라고 부른다.
- 가로로 배열되어 있는 블록의 DIV style은 float:left로 설정되며 그 Parent의 style은 clear:all 로 설정된다.
- 세로로 배열되어 있는 블록의 DIV style은 clear:all로 설정되며 그 Parent의 style은 float:left로 설정된다.
- 최상위 Parent는 항상 존재해야 하며 style은 clear:all 이다.
- 위치정보는 Target 블록의 Up(위), Down(아래), Right(오른쪽), Left(왼쪽)으로 표현한다.
DIV 이동 위치 선정 방법 1 #
- 이동하고자 하는 블록를 B라고 하고 이의 중앙점을 x,y라고 한다.
- 이동을 원하는 블록을 제외한 나머지 블록를 Bi라고 하고 그 중앙점을 xi,yi라고 한다.
- (x,y), (xi,yi)의 Distance를 Di라한다.
- (x,y), (xi,yi)사이의 각도를 Ai라 한다..
- 위치정보를 Li라 하면 Li는 Ai>-45 이고 Ai<=45 이면 Right, Ai>45 이고 Ai <=135 이면 Up,
Ai<135 이고 Ai<=-135 이면 Left, Ai>-135 이고 Ai<=-45이면 Down
- Di와 Ai의 정확도등 계산하여 Di에 다시 반영한다.
- D0~Di중 가장 작은 Distance값이 t일 경우 Bt를 Target블록으로 선정하고 Lt를 그 Target블록을 기준으로한 위치 정보이다.
DIV 이동 위치 선정 방법 2 #
- 이동하고자 하는 블록를 B라고 하고 이의 왼위꼭지점부터 시계방향으로 4개의 꼭지점을 (x1,y1)(x2,y1)(x1,y2)(x2,y2)라 한다.
- 이동을 원하는 블록을 제외한 나머지 블록를 Bi라고 하고 시계방향으로 4개의 꼭지점을 (xi1,yi1)(xi2,yi1)(xi1,yi2)(xi2,yi2)라 한다.
- (x1,y1)과 (xi2,yi1)의 Distance를 Di라 하고 Li는 Right이다.
- (x1,y1)과 (xi1,yi2)의 Distance를 Di라 하고 Li는 Down이다.
- (x1,y2)와 (xi1,yi1)의 Distance를 Di라 하고 Li는 Up이다.
- (x2,y1)과 (xi1,yi1)의 Distance를 Di라 하고 Li는 Left이다.
- Di가 가장 작은 Li를 Bi의 Li로 선정한다.
- D0~Di중 가장 작은 Distance값이 t일 경우 Bt를 Target블록으로 선정하고 Lt를 그 Target블록을 기준으로한 위치 정보이다.
- 경험적으로 선정 방법2가 더 정확한 Target 블록의 위치를 찾아 낼수 있었으며, 서비스 적용한 선정 방법이다.
DIV 이동에 따른 Element 변경 방법 #
* Right일 경우
if Parent가 최상위 노드의 경우
RightAttachBody();return;
if Parent노드가 clear:both의 경우( 좌우 배열일 경우 )
if B가 Bt의 nextSibling이면
return;(이미 오른쪽에 배열되어 있다)
if Parent가 같을 경우
RightInDiv();return;
if Bt의 Parent가 마지막 childNode일 경우
if Bt의 Parent의 Height와 B의 Height보가 크거나 차이가가 10이하의 경우
RightInDiv();return;
else
Bt의 Parent의 Child의 width를 계산하여 B의 width와의 차이가 10이하인 Child를 찾는다.
RightJoinAndAttach(Child);return;
else
RightInDiv();return;
else
if Bt의 Parent의 child node가 1이면
RightAppendNodeByHor();return;
else Bt의 Parent의 child node가 2이고 B의 Parent와 같으면
RightChangeParentAttr();return;
else
RightAppendParent();return;
* Down일 경우
if Parent노드가 float:left의 경우( 상하 배열일 경우 )
if B가 Bt의 nextSibling이면
return;(이미 아래쪽에 배열되어 있다)
if Parent가 같을 경우
DownInDiv();return;
if Bt의 Parent가 마지막 childNode일 경우
if Parent의 Parent인 Grand Parent의 최상위 Parent일 경우
DownFromParent();return;
if Bt의 Grand Parent의 Width와 B의 Width가 10이하의 경우
DownInDiv();return;
else
if Bt의 Grand Parent의 height와 Bt의 Parent의 height 차이가 10이하의 경우
DownFromParent();return;
if Bt의 Parent의 Height와 B의 height를 더한값이 Bt의 Grand Parent 보다 크거나 차이가 10이하면
DownInDiv();return;
else
if Bt의 width보다 B의 width가 크면
DownFromParent();return;
else
DownIndiv();
else
DownInDiv();
else // 좌우 배열의 경우
if Bt의 Parent의 height와 Bt의 height차이가 10이하면
DownFromParent();return;
else if Bt의 width가 B의 width보다 작거나 차이가 10이하면
DownWithLeftBlock();return;
else if Bt의 width가 B의 width보다 크면
DownFromParent();return;
else
DownWithLeftBlock();return;
* Left일 경우
if Parent노드가 float:left의 경우( 상하 배열일 경우 )
if Bt의 Parent의 child node수가 1일경우
LeftVerOneNode();return;
else Bt의 Parent의 child node수가 2이고 Bt의 Parent와 B의 Parent가 같을경우
LeftVerOneNode();return;
else
LeftMakeInBlock();return;
else
LeftAppendNode();return;
* Up일 경우
if Parent노드가 float:left의 경우( 상하 배열일 경우 )
UpInDiv();return;
else
if Bt의 Parent의 child node수가 1인 경우
UpChangeFromLeftOneChild();return;
else Bt의 Parent의 child node수가 2이고 Bt의 Parent와 B의 Parent가 같을경우
UpChangeFromLeft();return;
else
UpFromParent();return;
예외적인 이동 방법 #
- 현재 위치와 이동해야할 위치의 Distance가 10이하의 경우 이동하지 않은걸로 간주한다.
- Up이 경우 Editor의 상위에 이동할경우, Left의 경우 Editor의 가장 왼쪽으로 이동할 경우면 반영하고 나머지의 경우는 Right와 Down으로 간주한다.
- 특정 Pattern에 대해서는 Target선정 및 위치 선정 알고리즘을 사용하지 않는다.
결론 #
- 테마의 템플릿적 요소에 자유도를 주기 위해 블록 단위의 이동을 구현하였다.
- 이동하고자하는 블록의 위치와 현재 배치되어 있는 블록의 위치의 연관도를 계산하여 블록이 놓여져야 하는 위치를 선정하였다.
- 선정된 위치에 따라 블록이 놓여지도록 HTML Element를 변경하였다.
- 블록의 이동에 있어서 어느정도 예측 가능한 이동이 가능하게 되었다.
- 좀더 나은 완성도를 위한 업그레이드 작업이 필요하다.
참고 문헌 #
- Javascript Guide, http://wp.netscape.com/eng/mozilla/3.0/handbook/javascript/
- Microsoft msdn Dhtml Reference,http://msdn.microsoft.com/library/default.asp?url=/workshop/author/dhtml/reference/dhtml_reference_entry.asp