Code/Javascript

[Javascript] svg 드래그 이동시 정확히 마우스 위치로 이동시키기

ki1111m2 2023. 11. 13. 11:19
const drag = () => {
    const svg = document.querySelector('svg');
    let isDragging = false;
    let startClientX, startClientY;
    let startViewBoxX, startViewBoxY;
    let viewport_width, viewport_height;
    let newX, newY;
    let initialScale;

    svg.addEventListener('mousedown', (e) => {
        let [x, y, width, height] = svg.getAttribute('viewBox').split(' ').map(Number);
        isDragging = true;
        startClientX = e.clientX;
        startClientY = e.clientY;
        startViewBoxX = x;
        startViewBoxY = y;
        viewport_width = width;
        viewport_height = height;
        initialScale = viewport_width / svg.clientWidth;
    });

    svg.addEventListener('mousemove', (e) => {
        if (isDragging) {
            const deltaX = (e.clientX - startClientX) * initialScale;
            const deltaY = (e.clientY - startClientY) * initialScale;
            newX = startViewBoxX - deltaX;
            newY = startViewBoxY - deltaY;
            svg.setAttribute('viewBox', `${newX} ${newY} ${viewport_width} ${viewport_height}`);

            startClientX = e.clientX;
            startClientY = e.clientY;
            startViewBoxX = newX;
            startViewBoxY =newY;
        }
    });

    svg.addEventListener('mouseup', () => {
        isDragging = false;
    });
}

window.addEventListener("DOMContentLoaded", drag)

 

기존 코드로 드래그 기능 구현시, 마우스 위치가 아닌 일정 비율로 이동했다.

그로 인해 지도 확대 시에는 빠르게 움직이는 것처럼 보였고, 축소 시에는 느리게 움직이는 것처럼 보였다.

 

마우스의 이동 거리만큼 svg 이미지를 정확히 이동시키고 싶었다.

이를 위해 다음과 같은 과정을 거쳤다.

 

 

비율을 저장할 변수를 선언

let initialScale;

 

mousedown 함수 내에서, 클릭이 시작된 시점의 비율을 기록

웹 브라우저의 크기와 뷰박스의 크기가 다르기때문에 이를 맞추는 작업 필요

뷰포트의 너비를 화면(웹브라우저)의 비율로 나눔

initialScale = viewport_width / svg.clientWidth;

 

mousemove 함수 내에서, 델타 값의 비율 조정

마우스가 움직임에 따라 이미지를 이동할 것이기 때문에 mousemove 함수 내에서 이동을 구현

현재 마우스 위치와 시작 마우스 위치의 차이에 따라 이동 범위가 결정됨

const deltaX = (e.clientX - startClientX) * initialScale;
const deltaY = (e.clientY - startClientY) * initialScale;