so woon!

[FRAMER MOTION] Drag Constraint (드래그 제약) 본문

Framer Motion/개념정리

[FRAMER MOTION] Drag Constraint (드래그 제약)

xowoony 2023. 5. 12. 14:47

학습일 : 2023. 05. 12


이번에는 드래그에 제약을 걸어보도록 하겠다.

저번글까지를 보면 그냥 drag 라는prop을 전달하여
범위에 제약 없이 그냥 튕겨나가는 것을 볼 수 있었다.


drag="x"

or

drag="y"



그냥 drag가 아닌 

 


drag="x" 를 작성해주게 되면 x축으로만 드래그 할 수 있게 되고,
drag="y" 를 작성해주게 되면 y축으로만 드래그 할 수 있게 된다.




<App.tsx>

drag="x"를 작성

function App() {
  return (
    <Wrapper>
      <Box
        drag="x"
        whileDrag="drag"
        variants={boxVariants}
        whileHover="hover"
        whileTap="tap"
      ></Box>
    </Wrapper>
  );
}
export default App;



결과
y축으로는 이동이 잠기게 되고
이렇게 하면 x축안에 갇혀있게 된다.
하지만 여전히 x축 안에서는 화면 밖으로 날라가게 된다.




 



<App.tsx>

drag="y"를 작성

function App() {
  return (
    <Wrapper>
      <Box
        drag="y"
        whileDrag="drag"
        variants={boxVariants}
        whileHover="hover"
        whileTap="tap"
      ></Box>
    </Wrapper>
  );
}
export default App;



결과

y축으로만 드래그 할 수 있게 된다.





dragConstraints

기본적으로 어떤 box를 만들 수 있다.
제약이 있는 box 이며,
드래깅이 허용될 수 있는 영역인 것이다.

dragConstraints={{ top: 0, bottom: 0, left: 0, right: 0 }} 이렇게 적어주었기 때문에


클릭을 떼면
아이템이 다시 중앙으로 돌아오게 된다.


 

하지만 이럴 필요가 없고 숏컷이 있음

뒤에도 나오겠지만 소개하자면

dragSnapToOrigin

 

이란 숏컷임

function App() {
  return (
    <Wrapper>
      <Box
        drag
        dragConstraints={{ top: 0, bottom: 0, left: 0, right: 0 }}
        whileDrag="drag"
        variants={boxVariants}
        whileHover="hover"
        whileTap="tap"
      ></Box>
    </Wrapper>
  );
}
export default App;




실행결과

 

 



다른 박스에 넣어진 채로
드래깅 제약하기

그러기 위해 좀 더 큰 박스를 만들어주겠음;

import { styled } from "styled-components";
import { motion } from "framer-motion";

// style
const Wrapper = styled.div`
  height: 100vh;
  width: 100vw;
  display: flex;
  justify-content: center;
  align-items: center;
`;

// 큰 박스
const BiggerBox = styled.div`
  width: 600px;
  height: 600px;
  background-color: rgba(255, 255, 255, 0.4);
  border-radius: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
`;

// 박스
const Box = styled(motion.div)`
  width: 200px;
  height: 200px;
  background-color: rgba(255, 255, 255, 1);
  border-radius: 40px;
  box-shadow: 0 2px 3px rgba(0, 0, 0, 0.1), 0 10px 20px rgba(0, 0, 0, 0.06);
`;

// Variants
const boxVariants = {
  hover: { scale: 1.2, rotateZ: 90 },
  tap: { borderRadius: "100px" },
};

function App() {
  return (
    <Wrapper>
      <BiggerBox>
        <Box
          drag
          dragConstraints={{ top: -200, bottom: 200, left: -200, right: 200 }} // (300 - 중앙박스의 절반)
          variants={boxVariants}
          whileHover="hover"
          whileTap="tap"
        ></Box>
      </BiggerBox>
    </Wrapper>
  );
}
export default App;



실행결과



이렇게 적어주는건 너무 귀찮은 과정이기 때문에
ref를 만들어주도록 하겠다.


import { styled } from "styled-components";
import { motion } from "framer-motion";
import { useRef } from "react";

// style
const Wrapper = styled.div`
  height: 100vh;
  width: 100vw;
  display: flex;
  justify-content: center;
  align-items: center;
`;

// 큰 박스
const BiggerBox = styled.div`
  width: 600px;
  height: 600px;
  background-color: rgba(255, 255, 255, 0.4);
  border-radius: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
`;

// 박스
const Box = styled(motion.div)`
  width: 200px;
  height: 200px;
  background-color: rgba(255, 255, 255, 1);
  border-radius: 40px;
  box-shadow: 0 2px 3px rgba(0, 0, 0, 0.1), 0 10px 20px rgba(0, 0, 0, 0.06);
`;

// Variants
const boxVariants = {
  hover: { scale: 1.2, rotateZ: 90 },
  tap: { borderRadius: "100px" },
};

function App() {
  // useRef 작성, 기본값 null, 타입스크립트 HTMLDIVELEMENT 적용
  // 작성 후 BiggerBox 컴포넌트에 전달
  const biggerBoxRef = useRef<HTMLDivElement>(null);
  return (
    <Wrapper>
      <BiggerBox ref={biggerBoxRef}>
        <Box
          drag
          dragConstraints={{ top: -200, bottom: 200, left: -200, right: 200 }} // (300 - 중앙박스의 절반)
          variants={boxVariants}
          whileHover="hover" // hover시 90도 z축 회전, 1.2배 커짐
          whileTap="tap" // 클릭했을 경우 scale1로 돌리고 원이 됨
        ></Box>
      </BiggerBox>
    </Wrapper>
  );
}
export default App;




ref를 작성해주고 적용해주었다.
그런다음 Box에게 제약을 걸어줄 것이다.
dragConstraints 안에 적어주었던 내용은 이제 없애고
dragConstraints={biggerBoxRef}
이렇게 적어주도록 한다.


준비가 끝났다.
지금까지 한 것은
레퍼런스를 만들었고, 레퍼런스를 BiggerBox에 적용했으며,
그 안에 속한 Box 컴포넌트에 constraints를 걸어주었는데
BiggerBox의 가장자리까지라고 설정해 주게 된 것이다.


실행결과
결과가 똑같음

 



dragSnapToOrigin

dragSnapToOrigin prop을 써주면
큰 박스에 작은 박스가 튕긴 후
중앙으로 돌아갈 수 있게 한다.

실행결과

 

 



dragElastic

dragElastic={값} 이렇게 써주면 된다.

dragElastic prop은 탄성 효과이다.
기본값은 0.5이며, 0과 1 사이의 값을 주어야만 한다.
값이 작을 수록 무거운 용수철이 달려있다 생각하면 될듯.
값 1을 주게 되면 용수철이 달려있지 않은 것처럼 느껴짐.


import { styled } from "styled-components";
import { motion } from "framer-motion";
import { useRef } from "react";

// style
const Wrapper = styled.div`
  height: 100vh;
  width: 100vw;
  display: flex;
  justify-content: center;
  align-items: center;
`;

// 큰 박스
const BiggerBox = styled.div`
  width: 600px;
  height: 600px;
  background-color: rgba(255, 255, 255, 0.4);
  border-radius: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  /* overflow: hidden; */
`;

// 박스
const Box = styled(motion.div)`
  width: 200px;
  height: 200px;
  background-color: rgba(255, 255, 255, 1);
  border-radius: 40px;
  box-shadow: 0 2px 3px rgba(0, 0, 0, 0.1), 0 10px 20px rgba(0, 0, 0, 0.06);
`;

// Variants
const boxVariants = {
  hover: { scale: 1.2, rotateZ: 90 },
  tap: { borderRadius: "100px" },
};

function App() {
  const biggerBoxRef = useRef<HTMLDivElement>(null);
  return (
    <Wrapper>
      <BiggerBox ref={biggerBoxRef}>
        <Box
          drag
          dragElastic={0.5} // 값이 작을수록 무거운 용수철
          dragSnapToOrigin
          dragConstraints={biggerBoxRef}
          variants={boxVariants}
          whileHover="hover"
          whileTap="tap"
        ></Box>
      </BiggerBox>
    </Wrapper>
  );
}
export default App;



실행결과

 

 

 

'Framer Motion > 개념정리' 카테고리의 다른 글

[FRAMER MOTION] useScroll  (0) 2023.05.14
[FRAMER MOTION] useMotionValue + useTransform 사용하기  (0) 2023.05.13
[FRAMER MOTION] Dragging  (0) 2023.05.11
[FRAMER MOTION] Gestures  (0) 2023.05.11
[FRAMER MOTION] Variants  (1) 2023.05.11
Comments