티스토리 뷰

Web

웹 프론트 Pan Zoom 개발기

콜라먹는 펭귄이 2021. 3. 23. 13:27

서론

지금 다니는 회사에서는 위성영상을 인공지능으로 분석해 사용자들에게 정보를 제공해주는 제품을 만드는 일을 한다. 그 중 최근 위성영상을 세그멘테이션하는 툴을 만들게 되었다. 위성영상을 확대/축소하고 이동을 하는 기능이 어려울거라 생각했지만 기존에 한번 비슷한 툴을 만들었기에 코드를 어느정도 가져오면 되겠지 싶었다. 하지만 마음대로 되지 않았고 공식(?)을 정리하고 기록해야 할 필요성을 느껴 작성하게 되었다.

 

요구사항

먼저 요구사항중에 줌과 이동 기능이 있었다. 다만 줌을 할때에는 마우스 포인터를 기준으로 잡고 줌인 / 아웃을 해야했다.(GIF 참조) 그리고 이동은 여느 프로그램처럼 드래그로 이동을 하면 되었다.

 

네이버 지도의 줌 인 / 아웃

ZOOM

먼저 어려울것 같은 줌부터 해결해보았다. 이걸 어떻게 구현해야하나 고민하고 있을 때 마침 회사분께서 졸업작품으로 비슷한걸 구현하셨다. 그 분께 조언을 구해보니 동차 변환 행렬이란 것을 찾아보라고 알려주셨다. 찾아보니 잘 정리되있는 블로그가 있었다. 행렬을 대수식으로 표현하면 다음과 같은 식이 나온다

$$x\prime = s_xx +p_x(1 - s_x)$$
$$y\prime = s_yy +p_y(1 - s_y)$$

 

여기에서 S는 확대 비율을 의미한다. X는 기존의 좌표를 P는 기준이 되는 좌표를 의미한다.

(1, 1)을 (2,2)을 기준으로 2배 확대하였을때의 좌표는 다음과 같은 계산결과를 따라 (0,0)이 된다

$$x: 2 * 1 + 2(1 - 2) = 0$$

$$y: 2 * 1 + 2(1 - 2) = 0$$

 

이걸 코드로 적용해 보았다.

const leftTop = new Point(0, 0)

function zoom(zoomLevel: number) {
    const newX = zoomLevel * leftTop.x + relativePoint.x * (1 - zoomLevel)
    const newY = zoomLevel * leftTop.y + relativePoint.y * (1 - zoomLevel)
    return new Point(newX, newY)
}

 

PAN

마우스를 잡고 드래그를 하여 위치를 옮기는 것을 Panning이라고 부른다. 패닝된 좌표를 구하는 방법은 굉장히 쉽다. 다들 눈치 챘겠지만 마우스의 무브먼트만큼 기존좌표에 더해주면 된다.

const leftTop = new Point(0, 0)

const panningEventHandler = (e: MouseEvent) => {
    return new Point(leftTop.x + e.movementX, leftTop.y + e.movementY)
}

 

결과물

나는 위 코드와 svg의 transform matrix를 이용하여 Pan, Zoom 요구사항을 구현하였다.

const leftTop = new Point(0, 0)

function zoom(zoomLevel: number) {
    const newX = zoomLevel * leftTop.x + relativePoint.x * (1 - zoomLevel)
    const newY = zoomLevel * leftTop.y + relativePoint.y * (1 - zoomLevel)
    return new Point(newX, newY)
}

const panningEventHandler = (e: MouseEvent) => {
    return new Point(leftTop.x + e.movementX, leftTop.y + e.movementY)
}

//matrix 0, 3번째 자리에 줌값을 4번째 자리엔 x값을 5번째 자리엔 y값을 넣어주면 된다.
<svg transform="matrix(1, 0, 0, 1, 0, 0)"></svg>

'Web' 카테고리의 다른 글

CORS(Cross-Origin-Resource-Sharing)  (0) 2019.05.02
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함