Framer Motion #8 | Slider by AnimatePresence

HyeonWooGa·2022년 8월 16일
0

Motion UI

목록 보기
8/9

Slider

  • AnimatePresence 컴포넌트를 활용하여 요소들이 슬라이드 되어 보이는 효과를 줍니다.
  • 기존 AnimatePresence 와 다른 점은 배열, key 프로퍼티 등만 다르고 initial, animate, exit props 를 사용하는 것은 같습니다.

Slider 기본 예시

  • 배열 map 사용
const boxVariants = {
  invisible: { x: -500, opacity: 0, scale: 0 },
  visible: {
    x: 0,
    opacity: 1,
    scale: 1,
    transition: {
      duration: 1,
    },
  },
  exit: {
    x: 500,
    opacity: 0,
    scale: 0,
    rotateX: 180,
    transition: {
      duration: 1,
    },
  },
};

function App() {
  const [visible, setVisible] = useState(1);
  const prevPlease = () => setVisible((prev) => (prev === 1 ? 1 : prev - 1));
  const nextPlease = () => setVisible((prev) => (prev === 10 ? 10 : prev + 1));
  return (
    <Wrapper>
      <AnimatePresence>
        {[1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map((i) =>
          i === visible ? (
            <Box
              variants={boxVariants}
              initial="invisible"
              animate="visible"
              exit="exit"
              key={i}
            >
              {i}
            </Box>
          ) : null
        )}
      </AnimatePresence>
      <button onClick={prevPlease}>Prev</button>
      <button onClick={nextPlease}>Next</button>
    </Wrapper>

  • html 요소 key 프로퍼티 사용 : 리액트는 html 요소의 key 프로퍼티의 값이 변하면 새로운 요소로 인식합니다.
const boxVariants = {
  entry: { x: 500, opacity: 0, scale: 0 },
  center: {
    x: 0,
    opacity: 1,
    scale: 1,
    transition: {
      duration: 1,
    },
  },
  exit: {
    x: -500,
    opacity: 0,
    scale: 0,
    rotateX: 180,
    transition: {
      duration: 1,
    },
  },
};

function App() {
  const [visible, setVisible] = useState(1);
  const nextPlease = () => setVisible((prev) => (prev === 10 ? 10 : prev + 1));
  const prevPlease = () => setVisible((prev) => (prev === 1 ? 1 : prev - 1));
  return (
    <Wrapper>
      <AnimatePresence>
        <Box
          variants={boxVariants}
          initial="entry"
          animate="center"
          exit="exit"
          key={visible}
        >
          {visible}
        </Box>
      </AnimatePresence>
      <button onClick={prevPlease}>Prev</button>
      <button onClick={nextPlease}>Next</button>
    </Wrapper>
  );
}

Slider 한 방향으로만 구동되는 오류 해결

  • Slider 반대 방향으로 구동하려면 initial 프로퍼티 값과 exit 프로퍼티 값을 변경해주면 됩니다.

  • custom 프로퍼티
    • variants 에 데이터를 보낼 수 있게 해주는 프로퍼티 입니다.
    • 사용하기 위해선 variants 가 객체가 아닌 객체를 반환하는 함수로 바뀌어야 합니다.
const boxVariants = {
  entry: (isBack: boolean) => ({
    x: isBack ? -500 : 500,
    opacity: 0,
    scale: 0,
    rotateX: -180,
  }),
  center: {
    x: 0,
    opacity: 1,
    scale: 1,
    rotateX: 0,
    transition: {
      duration: 1,
    },
  },
  exit: (isBack: boolean) => ({
    x: isBack ? 500 : -500,
    opacity: 0,
    scale: 0,
    rotateX: 360,
    transition: {
      duration: 1,
    },
  }),
};

function App() {
  const [visible, setVisible] = useState(1);
  const [isBack, setIsBack] = useState(false);
  const nextPlease = () => {
    setIsBack(false);
    setVisible((prev) => (prev === 10 ? 10 : prev + 1));
  };
  const prevPlease = () => {
    setIsBack(true);
    setVisible((prev) => (prev === 1 ? 1 : prev - 1));
  };
  return (
    <Wrapper>
      <AnimatePresence custom={isBack}>
        <Box
          custom={isBack}
          variants={boxVariants}
          initial="entry"
          animate="center"
          exit="exit"
          key={visible}
        >
          {visible}
        </Box>
      </AnimatePresence>
      <button onClick={prevPlease}>Prev</button>
      <button onClick={nextPlease}>Next</button>
    </Wrapper>
  );
}

참조

Framer Motion Docs
리액트 마스터클래스, 노마드코더

profile
Aim for the TOP, Developer

0개의 댓글