React Framer Motion

gyujae·2022년 5월 13일
0

Framer Motion

React용 production-ready 모션 라이브러리 (오픈 소스)

Animation

Framer Motion의 애니메이션은 모션 컴포넌트의 유연한 animate 속성을 통해 제어됩니다. 간단한 애니메이션의 경우 animate props에서 직접 값을 설정할 수 있습니다.

<motion.div animate={{ rotate: 360 }} transition={{ duration: 2 }} />

Transition

Transition은 값이 한 상태에서 다른 상태로 움직이는 방식을 정의합니다.
또한 Tween, Spring 또는 Inertia를 사용할 애니메이션 유형을 정의하는 소품을 허용할 수 있습니다.

<motion.div animate={{ rotate: 180 }} transition={{ type: 'spring' }} />

Variants

Variants은 컴포넌트가 가질 수 있는 미리 정의된 시각적 state입니다.

const variants: Variants = {
visible: { opacity: 1 },
hidden: { opacity: 0 },
}

<motion.div initial="hidden" animate="visible" variants={variants} />

Orchestration

delayChildren: 딜레이 시간(초) 후에 하위 애니메이션이 시작됩니다.
staggerChildren: 하위 컴포넌트의 애니메이션에 지속 시간(초)만큼 시차를 둘 수 있습니다. 예를 들어, staggerChildren이 0.01이면 첫 번째 자식은 0초, 두 번째 자식은 0.01초, 세 번째 자식은 0.02초 지연되는 식입니다. 계산된 stagger 딜레이가 delayChildren에 추가됩니다.

inherit: boolean
부모로부터 variant 변경 사항을 상속하지 않도록 하려면 false로 설정합니다.

custom : any
각 애니메이션 컴포넌트에 대해 dynamic variants을 다르게 사용할 사용자 지정 데이터입니다.

const variants = {
  visible: (custom) => ({
    opacity: 1,
    transition: { delay: custom * 0.2 }
  })
}

<motion.div inherit={false} custom={0} animate="visible" variants={variants} />
<motion.div custom={1} animate="visible" variants={variants} />
<motion.div custom={2} animate="visible" variants={variants} />

Hover
hover 제스처는 포인터가 컴포넌트 위로 이동하거나 컴포넌트를 떠날 때를 감지합니다. onMouseEnter 및 onMouseLeave와는 달리 실제 마우스 이벤트의 결과로만 호버가 실행되도록 보장됩니다.

<motion.div whileHover={{ scale: 0.8 }} />

Tap
whileTap: VariantLabels | TargetAndTransition
컴포넌트를 누르고 있는 동안 애니메이션할 속성 또는 변형 레이블입니다.

<motion.div whileTap={{ scale: 0.8 }} /> 

Drag
drag: boolean | "x" | "y"
이 요소에 대해 끌기를 활성화합니다. 기본적으로 false로 설정됩니다. 양방향으로 드래그하려면 true로 설정하십시오. 특정 방향으로만 드래그하려면 "x" 또는 "y"를 설정합니다.

<motion.div drag="x" />

whileDrag: VariantLabels | TargetAndTransition
드래그 제스처가 인식되는 동안 애니메이션할 속성 또는 변형 레이블입니다.

<motion.div whileDrag={{ scale: 1.2 }} />

dragConstraints
허용된 드래그 가능 영역에 제약 조건을 적용합니다.
dragConstraints 에는 드래그 가능한 컴포넌트의 가장자리 거리를 정의합니다. (드래그 가능한 영역에 가장자리에서 얼마만큼까지 허용할 것인지 지정)

<motion.div drag="x" dragConstraints={{ left: 0, right: 300 }} />

// ref이용
const MyComponent = () => {
  const constraintsRef = useRef(null)

  return (
    <motion.div ref={constraintsRef}>
        <motion.div drag dragConstraints={constraintsRef} />
    </motion.div>
  )
}

dragSnapToOrigin: boolean
true인 경우 드래그 가능한 요소는 드래그를 놓을 때, 원점으로 다시 애니메이션됩니다.
dragSnapToOrigin={true}

dragElastic: DragElastic
외부 제약 조건에서 허용되는 이동 정도. 0 = 움직임 없음, 1 = 전체 움직임. 기본적으로 0.5로 설정됩니다. 움직임을 비활성화하기 위해 false로 설정할 수도 있습니다.
dragElastic={0.2}

MotionValue

MotionValues는 애니메이션 값의 상태(state)와 속도(velocity)를 추적합니다. 모든 모션 컴포넌트는 내부적으로 MotionValues를 사용하여 애니메이션 값의 상태와 속도를 추적합니다. 일반적으로 이들은 자동으로 생성됩니다. (MotionValue는 React State가 아니기 때문에 Motion Value값이 바뀌어도 리랜더링이 일어나지 않는다.)

import { motion, useMotionValue } from "framer-motion"

export function MyComponent() {
  const x = useMotionValue(0)
  return <motion.div style={{ x }} />
}
const x = useMotionValue(0)

useMotionValue 후크로 MotionValues를 생성할 수 있습니다. useMotionValue에 전달된 값은 MotionValue의 초기 상태로 작동합니다.

x.set(100)

set 메서드로 업데이트할 수 있습니다.
이것은 React 리렌더링을 트리거하지 않습니다.

x.get() // 100

MotionValue는 문자열이나 숫자가 될 수 있습니다.
get 메소드로 값을 읽을 수 있습니다.

useTransform

useTransform 훅을 통해 MotionValues를 연결합니다.
useTransform()는 한 값 범위에서 다른 값 범위로 매핑하여 다른 MotionValue의 output을 변환하는 MotionValue를 만듭니다.
x(Motion Value)값을 다른 output값으로 변환해준다.
ex) x: -400 => 1

const x = useMotionValue(0)
const input = [-200, 0, 200]
const output = [0, 1, 0]
const opacity = useTransform(x, input, output)

return <motion.div drag="x" style={{ x, opacity }} />

useViewportScroll(): ScrollMotionValues
뷰포트가 스크롤될 때 업데이트되는 MotionValues를 리턴합니다.
아래 값들은 모두 MotionValue< number >를 넘겨줍니다.
scrollX: 실제 수평 스크롤 픽셀 ex) 500px
scrollY: 실제 수직 스크롤 픽셀 ex) 500px
scrollXProgress : 0 ~ 1 사이의 수평 스크롤
scrollYProgress : 0 ~ 1 사이의 수직 스크롤(가장 상단 0, 가장 하단 1)

export const MyComponent = () => {
  const { scrollYProgress } = useViewportScroll()
  return <motion.div style={{ scaleX: scrollYProgress }} ![](https://velog.velcdn.com/images/nuo/post/7b5e9a76-5435-4581-ab20-3e19813eb5d4/image.png)
/>
}

0개의 댓글