ReactSVG Class Component 리팩토링하기 2 - zoom, panning편 (작성중)

FGPRJS·2021년 12월 23일
0

이전의 Component 리팩토링에 있어서 Zoom/Panning이 완전히 적용되지 않는 문제가 있어 관련된 처리를 한다.

현재 코드의 상태 (이전 작업의 마지막 코드를 참조)에서 발생하는 문제는 다음과 같다.

  1. 아직 애니메이션을 적용 안함
  2. Panning이 끊김
    (setState()와 관련된 오류로 예상됨)
  3. Zoom이 제대로 되지 않음
  4. click 이벤트가 제대로 작동하지 않음

상기 문제들을 해결할 수 있는 코드를 새로 작성한다.


1. 애니메이션 적용

onClick시 발동하는 animation을 다음과 같은 식으로 구현해 보았다.

setState완료시 해당 변수를 갖고 애니메이션을 시도하는 코드이다.


function animatingViewBox(target, x, y, width, height){
    gsap.to(target, {
        duration: .5,
        attr: {viewBox: `${x} ${y} ${width} ${height}`},
        ease: "power3.inOut"
    });
}

//중략...

onClick(event){

  console.log('on click event');
  if(event.target.getAttribute('name'))
  {
    let rect = event.target.getBoundingClientRect();

    console.log(event.target.getAttribute('name'));

    this.setState({
      current_viewbox : {
        x : rect.top,
        y : rect.bottom,
        width : rect.width,
        height: rect.height
      }
    },
    () => {
      console.log('set state complete')
      animatingViewBox(this.svg, 
                       this.state.current_viewbox.x, 
                       this.state.current_viewbox.y, 
                       this.state.current_viewbox.width,
                       this.state.current_viewbox.height)
    })
  }
}

동작하지 않는다.

log도 기재해보았지만 log조차 console에 찍히지 않았다.

이벤트 할당 자체가 되지 않은 것.

관련된 정보를 찾는 도중 다음 링크에 대한 정보를 확인하였다.

상기 링크의 경우, React에 최적화되어있는것은 React 자체적으로 사용하는 onClick이지, JS전체에서 사용되는 addEventListener가 아니라는 것이다.

최적화 및 자동 이벤트 해제를 위하여 React 자체적인 Event on~ 변수를 사용하라는 것이 핵심이다.

하지만 이것은 React컴포넌트의 이야기인 것이지, svg 엘리먼트에 대한 이야기가 아니다. 상기 링크는 다음과 같은 이야기인 것이다.

render(){
       return <ReactSVG
            onClick = {this.onClick.bind(this)}
            beforeInjection = {(inject_svg) => {
                this.svg = inject_svg;

                inject_svg.setAttribute('width',`${this.state.current_viewbox.width}`);
                inject_svg.setAttribute('height',`${this.state.current_viewbox.height}`);
                inject_svg.setAttribute('viewBox',`${this.state.current_viewbox.x} ${this.state.current_viewbox.y} ${this.state.current_viewbox.width} ${this.state.current_viewbox.height}`);
                inject_svg.addEventListener('wheel', this.onZoom.bind(this));

                if (window.PointerEvent) {
                    inject_svg.addEventListener('pointerdown', this.onPointerDown.bind(this)); // Pointer is pressed
                    inject_svg.addEventListener('pointerup', this.onPointerUp.bind(this)); // Releasing the pointer
                    inject_svg.addEventListener('pointerleave', this.onPointerUp.bind(this)); // Pointer gets out of the SVG area
                    inject_svg.addEventListener('pointermove', this.onPointerMove.bind(this)); // Pointer is moving
                } else {
                    // Add all mouse events listeners fallback
                    inject_svg.addEventListener('mousedown', this.onPointerDown.bind(this)); // Pressing the mouse
                    inject_svg.addEventListener('mouseup', this.onPointerUp.bind(this)); // Releasing the mouse
                    inject_svg.addEventListener('mouseleave', this.onPointerUp.bind(this)); // Mouse gets out of the SVG area
                    inject_svg.addEventListener('mousemove', this.onPointerMove.bind(this)); // Mouse is moving

                    // Add all touch events listeners fallback
                    inject_svg.addEventListener('touchstart', this.onPointerDown.bind(this)); // Finger is touching the screen
                    inject_svg.addEventListener('touchend', this.onPointerUp.bind(this)); // Finger is no longer touching the screen
                    inject_svg.addEventListener('touchmove', this.onPointerMove.bind(this)); // Finger is moving
                }
        }

하지만 SVGElement에만 관심이 있는 것이지, ReactSVG 컴포넌트 자체의 onClick이벤트는 관심이 없다.

따라서 ReactComponent에는 onClick항목을 사용하되, Element에 대해서는 addEventListener를 고수한다.

조사 결과, 무조건 pointerdown이벤트를 통하는 것으로 확인되었다.


전반적으로 수정해야 하는 점은 다음과 같다.

  • ReactSVG SVGElement의 Attribute는 state에 의존하지 않게 할 것
    • 이유: 갱신속도 느려짐(React의 state update처리 관련)
profile
FGPRJS

0개의 댓글