Code/Javascript

[Javascript] 마우스 휠(스크롤)을 이용한 svg 확대/축소 줌 기능 구현

ki1111m2 2023. 11. 9. 09:53
window.addEventListener("DOMContentLoaded", (event) => {
    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;        

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

window.addEventListener("DOMContentLoaded", zoom)

 

window 객체

1. 전역객체로써 window

작성하는 코드의 대부분은 window 객체의 프로퍼티가 됨

페이지 내의 모든 객체를 다 포함하고 있기 때문에 생략 가능하다는 특징이 있음

2. 브라우저 창으로써 window

브라우저의 창을 대변하고, 다양한 메서들르 통해 이 창을 제어할 수 있음

 

addEventListner

document의 특정 요소 이벤트를 등록할 때 사용됨

eventTarget.addEventListner('eventType', function)

  • eventTarget(이벤트 타겟)은 해당 이벤트를 적용할 DOM을 가져와 준다.
  • eventType(이벤트 타입)은 말 그대로 어떤 타입의 이벤트를 적용할 것인지 써주면 된다. 대표적으로 click DOMContentLoad, scroll submit등등이 있다. 타입을 써줄 때는 따옴표를 잊지 말고 감싸줘야 한다.
  • click: 요소를 클릭하면 이벤트 발생.
  • DOMContentLoaded: 페이지가 새로 로딩될 때마다 이벤트 발생.
  • scroll: 스크롤을 하면 이벤트 발생.
  • submit: 양식을 전송하면 이벤트 발생. (ex: input type이 submit일 때 submit 버튼을 누르는 것과 같음)
  • function(실행할함수)에는 이벤트를 발생시켰을 시 실행할 동작을 가져와 준다.

사용 방법 1. 함수를 따로 만듦 -> 호출해서 사용

const print = () => {
    console.log('print!');
}

button.addEventListener('click', print);

사용 방법 2. 이벤트 리스너 안에 함수 바로 작성

button.addEventListener('click', () => {
   	console.log('print!');
});

svg.onwheel = function (event) {

 

wheel 이벤트 (onwheel 속성)

사용자가 마우스 휠을 위/아래로 굴릴 때 발생

사용자가 터치패드를 사용해 요소를 스크롤하거나 확대/축소 할 때도 발생

  • deltaX: X축 기준 마우스휠 스크롤량
  • deltaY: Y축 기준 마우스휠 스크롤량
  • deltaZ: Z축 기준 마우스휠 스크롤량

 

        // 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;

 

deltaY 값을 1000으로 나눈 scale의 절댓값이 0.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());

 

DOMPoint

svg와 같은 그래픽 환경에서 사용되는 객체

2D/3D 좌표 공간에서 점을 나타내며, 변환 및 연산을 수행하는 데 사용됨

 

clinetX, clientY

마우스 이벤트가 발생한 시점에서 마우스 커서의 X와 Y 좌표

브라우저 창의 왼쪽 상단 모서리를 기준으로 함

 

matrixTransform

svg나 html의 <svg> 요소에 사용되는 메서드 중 하나

현재 좌표 시스템에서 지정된 변환 행렬을 적용하여 좌표를 변환함

 

getScreenCTM()

svg에서 요소의 현재 화면에 대한 변환 행렬을 가져오는 메서드

요소가 전체 화면 좌표에 대해 어떠헥 변환되었는지를 설명함

 

inverse()

역행렬을 찾는 데 사용되는 메서드

변환된 지점을 다시 원래 좌표로 돌리는 역할을 함

 

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

 

svg의 viewBox 속성을 가져옴

viexBox 속성은 아래와 같이 공백으로 구분된 숫자로 구성되어 있으므로, split을 사용하여 숫자 매핑

viewBox="0 0 500 250"

 

        // 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];

 

pt.x pt.y의 값을 너비, 높이의 비율로 계산

 

        // 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;

 

스크롤로 확대한 비율에 따라 뷰박스를 어느 위치로 설정할지 계산

 

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

 

뷰박스의 값을 새로운 값으로 설정


코드 출처

https://stackoverflow.com/questions/76150884/how-to-use-the-mouse-wheel-to-zoom-on-an-svg-using-the-viewbox

 

 

https://bigtop.tistory.com/48

https://kyounghwan01.github.io/blog/JS/JSbasic/addEventListener/

https://velog.io/@a_in/-addeventeistener-javascript

https://homzzang.com/b/js-1390