Code/Javascript

[Javascript] 마우스를 이용한 svg 드래그 이동 기능 구현

ki1111m2 2023. 11. 9. 14:45

 

const zoom = () => {
    const svg = document.querySelector('svg');

    // zooming
    svg.onwheel = function (event) {
        event.preventDefault();

        // set the scaling factor (and make sure it's at least 10%)
        let scale = event.deltaY / 1000;
        scale = Math.abs(scale) < .1 ? .1 * event.deltaY / Math.abs(event.deltaY) : scale;

        // get point in SVG space
        let pt = new DOMPoint(event.clientX, event.clientY);
        pt = pt.matrixTransform(svg.getScreenCTM().inverse());

        // get viewbox transform
        let [x, y, width, height] = svg.getAttribute('viewBox').split(' ').map(Number);

        // get pt.x as a proportion of width and pt.y as proportion of height
        let [xPropW, yPropH] = [(pt.x - x) / width, (pt.y - y) / height];
        
        // calc new width and height, new x2, y2 (using proportions and new width and height)
        let [width2, height2] = [width + width * scale, height + height * scale];
        let x2 = pt.x - xPropW * width2;
        let y2 = pt.y - yPropH * height2;        
        console.log(x, y, width, height)

        svg.setAttribute('viewBox', `${x2} ${y2} ${width2} ${height2}`);
    }
}

window.addEventListener("DOMContentLoaded", zoom)


const drag = () => {
    const svg = document.querySelector('svg');
    let isDragging = false;
    let startClientX, startClientY;
    let startViewBoxX, startViewBoxY;
    let viewport_width, viewport_height;
    let newX, newY;

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

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

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

window.addEventListener("DOMContentLoaded", drag)

const drag = () => {
    const svg = document.querySelector('svg');
    let isDragging = false;
    let startClientX, startClientY;
    let startViewBoxX, startViewBoxY;
    let viewport_width, viewport_height;
    let newX, newY;

 

여러 함수에서 같은 변수값을 쓰기 위해 바깥에서 선언


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

 

마우스를 클릭했을 때 실행

svg.getAttribute

클릭한 시점의 뷰박스 값을 가져오기 위해 해당 함수 안에서 변수 불러옴


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

 

delta: 이동한 값 (현재 위치 - 시작 위치)

new에서 *0.000005 한 이유: 드래그시 움직이는 비율(속도) 맞추기 위함

 

정확히 마우스 포인트 값을 중앙으로 오게 만들고 싶다..