알아두면 좋은 라이브러리

[@use-gesture] 제스처 이벤트 제어 :: 마이구미

mygumi 2022. 9. 28. 20:59
반응형
이 글은 @use-gesture 이라는 라이브러리를 다룬다.
@use-gesture 은 마우스나 터치와 같은 이벤트를 활용하는 로직에 큰 도움을 줄 수 있다.
조금이나마 도움을 줄 수 있는 라이브러리들을 소개하는 카테고리로 분류된 글이다.
알아두면 좋은 라이브러리

 

 

라이브러리는 굉장히 심플하고 사용하기 쉽다.

문서도 잘 되어있고, 예제도 풍부하여 친절한 라이브러리이다.

바닐라 자바스크립트도 지원하지만, react 도 지원하고 있다. (여기서는 react 기준)

 

import { useDrag } from '@use-gesture/react'

function Component() {
  useDrag(({ first, last, movement: [mx, my] }) => {
    // first - 첫 이벤트 여부, last - 마지막 이벤트 여부
    // mx - x 축으로 이동한 거리, y 축으로 이동한 거리
  })
  
  return <div />
}

 

위는 드래그 제스처를 위해 제공해주는 훅이다.

그리고 훅에서 제공해주는 파라미터에는 제스처 이벤트에 대한 데이터들이 넘어온다.

 

제스처는 Drag, Move, Hover, Scroll, Wheel, Pinch 웬만한 제스처들은 전부 제공해주고 있다. (Gesture)

제스처 이벤트를 기반으로 우리가 원하는 movement 와 같은 데이터들도 웬만하면 다 제공해준다. (Gesture state)

 

이처럼 @use-gesture 는 제스처 이벤트 활용에 도움을 주는 라이브러리이다.

짚고 넘어가야하는 건, 이 라이브러리의 역할은 이벤트에 대한 데이터를 제공해주는 것이다.

즉, 데이터를 제공해주고, 이 데이터를 기반으로 요소들의 모션은 직접 구현해야한다는 것이다.

모션 구현을 위해 @use-gesture 의 공식 문서에서는 react-spring 을 사용하여 예제들을 구현하여 설명하고 있다.

 

react-spring 사용

function PullRelease() {
  const [{ x, y }, api] = useSpring(() => ({ x: 0, y: 0 }))

  const bind = useDrag(({ down, movement: [mx, my] }) => {
    api.start({ x: down ? mx : 0, y: down ? my : 0, immediate: down })
  })

  return <animated.div {...bind()} style={{ x, y }} />
}

 

useState 사용

function PullRelease() {
  const [point, setPoint] = useState({ x: 0, y: 0})

  useDrag(({ down, movement: [mx, my] }) => {
    setPoint({ x: down ? mx : 0, y: down ? my : 0 })
  })
  
  const translateXY = `transform: translate(${point.x}, ${point.y})`: 

  return <div style={{translateXY}} />
}

 

실제 모션에 대한 구현은 본인이 원하는대로 하면 된다.

일반적으로 useState 는 리랜더링을 유발하는 것에 비해, react-spring 은 그렇지 않기에 더 나은 퍼포먼스를 낼 수 있긴 하다.

 


 

 

2개 이상의 이벤트를 제어할 경우에도 훨씬 깔끔하다.

 

el.addEventListener("drag", dragtHandler, false);
el.addEventListener("dragStart", dragStartHandler, false);
el.addEventListener("drop", dropHandler, false);

useGesture(
  {
    onDrag: (state) => doSomethingWith(state),
    onDragStart: (state) => doSomethingWith(state),
    onDragEnd: (state) => doSomethingWith(state),
  }
}

 

 

 

모바일 환경에서도 충분히 활용할만하다.

스와이프 제스처도 라이브러리에서 판단하여 제공해주는 기능이 존재한다.

 

useDrag(
    ({ swipe: [swipeX] }) => {
      if (swipeX === 1) {
        back() // 스와이프백 제스처로 인지하면 페이지 "뒤로가기"
      }
    },
    {
      pointer: { touch: true },
      axis: 'x',
      target: elementRef
    },
  )

 

그리고 모바일 환경을 위한 경고도 주곤한다.

 

[@use-gesture]: The drag target has its `touch-action` style property set to `auto`. It is recommended to add `touch-action: 'none'` so that the drag gesture behaves correctly on touch-enabled devices. For more information read this: https://use-gesture.netlify.app/docs/extras/#touch-action.

 

제스처 이벤트를 사용하는 요소에는 기본적으로 touch-action: none 을 추가하여 다른 이벤트와 겹치지 않도록 한다.

특히 모바일에서는 스크롤 이벤트와 많이 충돌나기 때문에 이러한 부분들을 잘 인지하고 있어야한다.

이러한 이슈를 위해 라이브러리에서는 개발 모드에서는 경고 메시지로 알려주고 있다.

 

이외에도 공식 문서를 보면, 재밌는 기능들을 많이 제공해준다.

공식 문서를 양이 많지 않아서, 이 라이브러리를 사용하지 않더라도 읽어보면 굉장히 유용할 것이라고 생각한다.

 

 

활용 예제

https://mygumi.tistory.com/427

https://mygumi.tistory.com/423

반응형