Animation(1)

์ดˆ์—ฐ2ยท2022๋…„ 11์›” 11์ผ
0

MUTSA_Front.archive

๋ชฉ๋ก ๋ณด๊ธฐ
15/16

๐Ÿ“– 7์ฃผ์ฐจ ๊ณผ์ œ: ๋…ธ๋งˆ๋“œ์ฝ”๋” React JS ๋งˆ์Šคํ„ฐํด๋ž˜์Šค 8.animation ์ˆ˜๊ฐ•





๐ŸŽˆ Framer Motion


  • Framer Motion : ReactJS์šฉ production-ready ๋ชจ์…˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

  • https://www.framer.com/motion/

  • ์„ค์น˜: npm i framer-motion
    (import { motion } from "framer-motion"; ํ•„์š”)



div๋ฅผ framer motion์„ ํ†ตํ•ด ์ง์ ‘์ ์œผ๋กœ animateํ•˜๋Š” ๊ฒƒ์€ ๋ถˆ๊ฐ€๋Šฅ

๋Œ€์‹  <motion.div> ํ˜•์‹์œผ๋กœ ์ž‘์„ฑ

motion. ์„ ์ž‘์„ฑํ•ด๋ณด๋ฉด ์œ„์™€ ๊ฐ™์ด ์šฐ๋ฆฌ๊ฐ€ animate ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋Š” ๋ชจ๋“  HTML๋“ค์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

์ฆ‰, ์šฐ๋ฆฌ๊ฐ€ ๋ฌด์–ธ๊ฐ€๋ฅผ animateํ•˜๊ฒŒ ๋งŒ๋“œ๋ ค๋ฉด ํ•ญ์ƒ motion์œผ๋กœ๋ถ€ํ„ฐ HTML element๋ฅผ ๋ถˆ๋Ÿฌ์™€์•ผ๋งŒ ํ•จ!




styled components animate


Box๋ผ๋Š” styled components๊ฐ€ ์žˆ๋Š”๋ฐ ์ด๊ฑธ animate์‹œํ‚ค๊ณ  ์‹ถ๋‹ค๊ณ  ํ•˜์ž.

์ผ๋‹จ์€, motion.Box๋Š” ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค.. ์ด๋ ‡๊ฒŒ ํ•  ์ˆ˜ X

โญโญโญ ๋Œ€์‹ , styled components๋ฅผ ์„ ์–ธํ–ˆ๋˜ ๊ณณ์— ๊ฐ€์„œ styled.div๋ฅผ styled(motion.div)๋กœ ๋ฐ”๊ฟ”์ฃผ์ž!!!!!!

์ž˜ ์„ ์–ธ๋œ์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด props๋ฅผ ๋„˜๊ฒจ์ฃผ์ž
props์—๋Š” animate, transition ๋“ฑ์ด ์žˆ๋‹ค.

prop๋“ค์„ ์ž‘์„ฑํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ์ž๋™์™„์„ฑ์œผ๋กœ ์šฐ๋ฆฌ๊ฐ€ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ๋“ค์ด ๋œฌ๋‹ค.

function App() {
  return (
    <Wrapper>
      <Box transition={{ delay:3 }} animate={{ borderRadius: "100px" }}/>
    </Wrapper>
  );
}

์ด๋ ‡๊ฒŒ ํ•ด์ฃผ๊ณ  ํ™•์ธํ•ด๋ณด๋ฉด

์ด๋ ‡๊ฒŒ ์ƒˆ๋กœ๊ณ ์นจ ํ›„ 3์ดˆ ํ›„์— borderRadius 100px๋ฅผ ๊ฐ€์ง„ ์›์œผ๋กœ ๋ฐ”๋€๋‹ค!
๊ทธ ์–ด๋–ค css ์ฝ”๋“œ๋„ ์ž‘์„ฑํ•˜์ง€ ์•Š๊ณ  ๋งŒ๋“ค์–ด ๋‚ธ ๊ฒƒ์ด๋‹ค. ๋งค์šฐ ๊ฐ„๋‹จ





+) props๋“ค ์•ˆ์—๋Š” ๋ชจ๋“  css ์‚ฌ์šฉ ๊ฐ€๋Šฅ
๊ฑ ์šฐ๋ฆฌ๊ฐ€ ์•„๋Š” css๋“ค์„ ๋„ฃ์–ด์„œ ์‚ฌ์šฉํ•˜๋ฉด ๋จ

๋ฉˆ์ถœ ๋•Œ ์‚ด์ง ํŠ•๊ธฐ๋Š”๊ฒŒ ์žˆ๋Š”๋ฐ ์ด๋Š” transition type์˜ ๊ธฐ๋ณธ ์„ค์ •์ด spring์ด๋ผ์„œ ๊ทธ๋Ÿฐ๊ฑฐ๊ณ  tween์œผ๋กœ ์ง€์ •ํ•ด์ฃผ๋ฉด ํ•ด๊ฒฐ.
(๊ทผ๋ฐ ๋ณดํ†ต spring ์“ด๋‹ค๊ณ  ํ•จใ…‹)





๐Ÿ• Animation


๐Ÿงฉ initial

animation์ด ์‹œ์ž‘๋˜๋Š” ์ง€์ ์—์„œ์˜ ์ƒํƒœ๋ฅผ ์ง€์ •ํ•ด์ฃผ๋Š” prop. ์ฆ‰, element์˜ ์ดˆ๊ธฐ ์ƒํƒœ

function App() {
  return (
    <Wrapper>
      <Box 
        initial={{ scale:0 }}/>
    </Wrapper>
  );
}


๐Ÿงฉ stiffness

๋ฌผ๋ฆฌ ํ˜„์ƒ ์‹œ๋ฎฌ๋ ˆ์ดํŠธ ํšจ๊ณผ๋ฅผ ์คŒ
โ†’ ๋ปฃ๋ปฃํ•˜๊ฒŒ ๋งŒ๋“ค์–ด์คŒ

function App() {
  return (
    <Wrapper>
      <Box 
        transition={{type:"spring", stiffness:10 }}
        initial={{ scale:0 }} 
        animate={{scale:1, rotateZ:360 }}/>
    </Wrapper>
  );
}


๐Ÿงฉ damping

๋ฌผ๋ฆฌํ˜„์ƒ ์‹œ๋ฎฌ๋ ˆ์ดํŠธ ํšจ๊ณผ๋ฅผ ์คŒ
โ†’ ๋ฐ˜๋™๋ ฅ

  • 0์œผ๋กœ ์„ค์ •ํ•˜๋ฉด ๋ฌด๊ธฐํ•œ ์ง„๋™

function App() {
  return (
    <Wrapper>
      <Box 
        transition={{type:"spring", damping:1}}
        initial={{ scale:0 }} 
        animate={{scale:1, rotateZ:360 }}/>
    </Wrapper>
  );
}


๐Ÿงฉ mass

๋ฌด๊ฑฐ์šด ์ •๋„๋ฅผ ์กฐ์ ˆ ๊ฐ€๋Šฅ

  • ๊ธฐ๋ณธ์„ค์ •๊ฐ’ = 1
function App() {
  return (
    <Wrapper>
      <Box 
        transition={{type:"spring", mass: 5}}
        initial={{ scale:0 }} 
        animate={{scale:1, rotateZ:360 }}/>
    </Wrapper>
  );
}


๐Ÿงฉ bounce

ํŠ•๊ธฐ๋Š” ์ •๋„ ์กฐ์ ˆ (0๊ณผ 1 ์‚ฌ์ด์—ฌ์•ผ ํ•จ)

  • 0์€ ํŠ•๊ธฐ์ง€ X, 1์€ ์—„์ฒญ ํŠ•๊น€
  • stiffness, damping, mass๊ฐ€ ์„ค์ •๋˜์—ˆ๋‹ค๋ฉด bounce๋Š” ๋ฎ์–ด์”Œ์›Œ์ง
  • ๊ธฐ๋ณธ๊ฐ’ 0.25
function App() {
  return (
    <Wrapper>
      <Box 
        transition={{type:"spring", bounce:0.8}}
        initial={{ scale:0 }} 
        animate={{scale:1, rotateZ:360 }}/>
    </Wrapper>
  );
}


๊ณต์‹ํŽ˜์ด์ง€์— ๊ฐ€๋ณด๋ฉด ์ด ์™ธ์—๋„ ๋งŽ์€ ํšจ๊ณผ ์‚ฌ์šฉ ๊ฐ€๋Šฅ





๐Ÿ•๐Ÿ• Variants


์• ๋‹ˆ๋ฉ”์ด์…˜์˜ stage ์—ญํ• .
์ปดํฌ๋„ŒํŠธ๊ฐ€ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋Š” ๋ฏธ๋ฆฌ ์ •์˜๋œ ์‹œ๊ฐ์  state

  1. ์ฝ”๋“œ๋ฅผ ๊น”๋”ํ•˜๊ฒŒ ํ•ด์คŒ
  2. ๋ถ€๋ชจ์ปดํฌ๋„ŒํŠธ์—์„œ ๋ฐœ์ƒํ•˜๋Š” animation์„ ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ์ž์‹์ปดํฌ๋„ŒํŠธ์—๋„ ๋ฐœ์ƒ์‹œํ‚ด
  3. ๋งŽ์€ ์• ๋‹ˆ๋ฉ”์ด์…˜๋“ค์„ ํ•˜๋‚˜๋กœ ์—ฐ๊ฒฐ์‹œ์ผœ์คŒ
  1. ์šฐ๋ฆฌ๊ฐ€ ์ด์ „์— ์œ„์™€ ๊ฐ™์ด ์ •์˜ํ–ˆ๋˜ ๊ฒƒ์„
const myVars = {
  start: { scale: 0 },
  end: { scale: 1, rotateZ: 360, transition: {type: "spring", delay: 0.5} }
};


function App() {
  return (
    <Wrapper>
      <Box variants={myVars} initial="start" animate="end" />
    </Wrapper>
  );
}

์ด๋Ÿฐ ์‹์œผ๋กœ ๋ฐ”๊ฟ”์ค„ ์ˆ˜ ์žˆ์Œ



  • โญ ๋ถ€๋ชจ์ปดํฌ๋„ŒํŠธ์—์„œ ๋ฐœ์ƒํ•˜๋Š” animation์„ variants๋Š” ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ์ž์‹์ปดํฌ๋„ŒํŠธ์—๋„ ๋ฐœ์ƒ์‹œํ‚ด
    โ†’ ์ •ํ™•ํžˆ๋Š” initial="~~ animate="~~" ๋ถ€๋ถ„์„ ๋ณต์‚ฌํ•ด์„œ ์ž์‹์—๊ฒŒ ์ „๋‹ฌํ•œ๋‹ค.


    ๋งŒ์•ฝ ์šฐ๋ฆฌ๊ฐ€ ์ž์‹์ปดํฌ๋„ŒํŠธ์—๋Š” ๋‹ค๋ฅธ ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ์ ์šฉํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด, ๋ถ€๋ชจ์ปดํฌ๋„ŒํŠธ animation์˜ props๋“ค ์ด๋ฆ„๊ณผ ๊ฐ™๊ฒŒ ์„ค์ •ํ•ด์ฃผ๋ฉด ๋œ๋‹ค.




  1. ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ variation์—์„œ ๋ชจ๋“  ์ž์‹์—๊ฒŒ ํšจ๊ณผ๋ฅผ ๋ถ€์—ฌํ•  ์ˆ˜ ์žˆ๋‹ค. (๋ถ€๋ชจ๊ฐ€ ์ž์‹ ์ปจํŠธ๋กค ๊ฐ€๋Šฅ)
  • delayChildren: ๋ชจ๋“  ์ž์‹๋“ค์—๊ฒŒ ์„ค์ •ํ•ด์ค€๋งŒํผ์˜ ์‹œ๊ฐ„์„ ์ง€์—ฐ์‹œ์ผœ์คŒ

  • staggerChildren: ๋ชจ๋“  ์ž์‹๋“ค์—๊ฒŒ ์„ค์ •ํ•ด์ค€๋งŒํผ์˜ ์‹œ๊ฐ„์„ ์ˆœ์ฐจ์ ์œผ๋กœ ์ง€์—ฐ์‹œ์ผœ์คŒ

const boxVariants = {
  start:{
    opacity:0,
    scale:0.5,
  },
  end:{
    scale:1,
    opacity:1,
    transition:{
      type:"spring",
      duration:0.5,
      bounce: 0.5,
      delayChildren: 0.5,
      staggerChildren: 0.2,
    }
  }
}

const circleVariants = {
  start:{
    opacity:0,
    y: 10 //y์ขŒํ‘œ ์ˆ˜์ •ํ•˜๊ณ  ์‹ถ์„ ๋•Œ ์‚ฌ์šฉ
  },
  end:{
    opacity:1,
    y: 0
  },
}

function App() {
  return (
    <Wrapper>
      <Box variants={boxVariants} initial="start" animate="end">
        <Circle variants={circleVariants}/>
        <Circle variants={circleVariants}/>
        <Circle variants={circleVariants}/>
        <Circle variants={circleVariants}/>
      </Box>
    </Wrapper>
  );
}





๐Ÿ•๐Ÿ•๐Ÿ• Gestures (1)



๐Ÿงฉ whileHover

ํ˜ธ๋ฒ„ ์ œ์Šค์ฒ˜๊ฐ€ ์ธ์‹๋˜๋Š” ๋™์•ˆ ์• ๋‹ˆ๋ฉ”์ด์…˜ํ•  ์†์„ฑ ๋˜๋Š” ๋ณ€ํ˜• ๋ ˆ์ด๋ธ”

function App() {
  return (
    <Wrapper>
      <Box whileHover={{scale:2}}/>
    </Wrapper>
  );
}




๐Ÿงฉ whileTap

์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ˆ„๋ฅด๊ณ  ์žˆ๋Š” ๋™์•ˆ ์• ๋‹ˆ๋ฉ”์ด์…˜ํ•  ์†์„ฑ ๋˜๋Š” ๋ณ€ํ˜• ๋ ˆ์ด๋ธ”

function App() {
  return (
    <Wrapper>
      <Box 
        whileHover={{scale:1.5, rotateZ:90 }} 
        whileTap={{scale:1, borderRadius: "100px"}}
      />
    </Wrapper>
  );
}



๋ฌผ๋ก  variants๋กœ ์ •๋ฆฌ ๊ฐ€๋Šฅํ•˜๋‹ค.

const boxVariants = {
  hover:{scale:1.5, rotateZ:90 },
  click:{scale:1, borderRadius: "100px"},
}

function App() {
  return (
    <Wrapper>
      <Box 
        variants={boxVariants}
        whileHover="hover"
        whileTap="click"
      />
    </Wrapper>
  );
}



์กฐ๊ฑด๋ฌธ์ด ํ•„์š”ํ•  ๋•Œ๊ฐ€ ์žˆ๊ฒ ์ง€? ๊ทธ๋Ÿฌ๋ฉด

function App() {
  return (
    <Wrapper>
      <Box 
        variants={boxVariants}
        whileHover={condition ? "hover" : "other"} 
		//condition์—๋Š” ํ•ด๋‹น ์กฐ๊ฑด ๋„ฃ๊ณ  "other"์—๋Š” ๋‹ค๋ฅธ ์†์„ฑ ์ด๋ฆ„ ๋„ฃ๊ธฐ
        whileTap="click"
      />
    </Wrapper>
  );
}

์ด๋Ÿฐ ์‹์œผ๋กœ ํ•ด์ฃผ๋ฉด ๋œ๋‹ค.



๐Ÿงฉ whileDrag

๋“œ๋ž˜๊ทธ ์ œ์Šค์ฒ˜๊ฐ€ ์ธ์‹๋˜๋Š” ๋™์•ˆ ์• ๋‹ˆ๋ฉ”์ด์…˜ํ•  ์†์„ฑ ๋˜๋Š” ๋ณ€ํ˜• ๋ ˆ์ด๋ธ”


์ผ๋‹จ drag๋ฅผ ํ™œ์„ฑ์‹œ์ผœ์ค˜์•ผ๊ฒ ์ง€?
๋†€๋ž๊ฒŒ๋„ ๊ทธ๋ƒฅ drag ๋‹จ์–ด๋งŒ ์ถ”๊ฐ€ํ•ด์ฃผ๋ฉด ๋œ๋‹ค.
drag๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด ์–ด๋””๋“ ์ง€ ์šฐ๋ฆฌ๊ฐ€ ์›ํ•˜๋Š” ๊ณณ์œผ๋กœ ๋“œ๋ž˜๊ทธํ•  ์ˆ˜ ์žˆ๋‹ค.

function App() {
  return (
    <Wrapper>
      <Box
        drag //์ด๊ฒƒ๋งŒ ํ•ด์ฃผ๋ฉด ๋จ!
        variants={boxVariants}
        whileHover="hover"
        whileTap="click"
      />
    </Wrapper>
  );
}

์ž์นซํ•˜๋ฉด ํ™”๋ฉด ๋ฐ–์œผ๋กœ ๋‚ ์•„๊ฐ€๋ฒ„๋ฆผใ…Ž

์ด์ œ whileDrag๋ฅผ ์‚ฌ์šฉํ•ด๋ณด์ž. ์ƒ‰์ƒ์„ ๋ฐ”๊พผ๋‹ค๊ณ  ํ•˜๋ฉด,
whileDrag={{backgroundColor:"blue"}} ์ด๋Ÿฐ์‹์œผ๋กœ ๋„ฃ์œผ๋ฉด ์•ˆ๋˜๊ณ  rgba ๊ฐ’์œผ๋กœ ๋ณ€ํ™˜ํ•ด์„œ ๊ทธ ๊ฐ’์„ ๋„ฃ์–ด์ค˜์•ผํ•œ๋‹ค.
(์ฐธ๊ณ : https://flatuicolors.com/palette/defo)

๊ทธ๋ž˜์•ผ ์• ๋‹ˆ๋ฉ”์ด์…˜์ด ์ž˜ ์ ์šฉ๋จโœ”๏ธโœ”๏ธ

function App() {
  return (
    <Wrapper>
      <Box
        drag
        variants={boxVariants}
        whileDrag={{backgroundColor:"rgb(46,204,113)"}} //์—๋ฉ”๋ž„๋“œ์ƒ‰
        whileHover="hover"
        whileTap="click"
      />
    </Wrapper>
  );
}

์‹ค์ œ๋กœ ์ฝ˜์†”์ฐฝ์„ ์—ด์–ด์„œ ํ™•์ธํ•ด๋ณด๋ฉด

์›€์ง์ผ ๋•Œ๋งˆ๋‹ค ๊ฐ’์ด ์—…๋ฐ์ดํŠธ ๋˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

+) ์ถ”๊ฐ€๋กœ drag="x"๋ฅผ ํ•˜๋ฉด x์ถ• ๋‚ด์—์„œ๋งŒ ๋“œ๋ž˜๊ทธํ•  ์ˆ˜ ์žˆ๊ณ ,
drag="y"๋ฅผ ํ•˜๋ฉด y์ถ• ๋‚ด์—์„œ๋งŒ ๋“œ๋ž˜๊ทธํ•  ์ˆ˜ ์žˆ๋‹ค.



๐Ÿ•x4 Gestures (2)


๐Ÿงฉ dragConstraints

๋“œ๋ž˜๊น…์ด ํ—ˆ์šฉ๋  ์ˆ˜ ์žˆ๋Š” ์˜์—ญ์œผ๋กœ ํ—ˆ์šฉ๋œ ๋“œ๋ž˜๊ทธ ๊ฐ€๋Šฅ ์˜์—ญ์— ์ œ์•ฝ ์กฐ๊ฑด์„ ์ ์šฉ.
๋“œ๋ž˜๊ทธ ๊ฐ€๋Šฅํ•œ ์ปดํฌ๋„ŒํŠธ์˜ ๊ฐ€์žฅ์ž๋ฆฌ ๊ฑฐ๋ฆฌ๋ฅผ ์ •์˜. (๋“œ๋ž˜๊ทธ ๊ฐ€๋Šฅํ•œ ์˜์—ญ์— ๊ฐ€์žฅ์ž๋ฆฌ์—์„œ ์–ผ๋งˆ๋งŒํผ๊นŒ์ง€ ํ—ˆ์šฉํ•  ๊ฒƒ์ธ์ง€ ์ง€์ •)

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


๋ณด๋‹ค์‹œํ”ผ dragConstraints์— ์˜ํ•ด ๋“œ๋ž˜๊ทธ์˜์—ญ์ด ์ œํ•œ๋œ๋‹ค.

๐Ÿงฉ dragConstraint โžก๏ธ ref ์ด์šฉ

function App() {
  const biggerBoxRef = useRef<HTMLDivElement>(null); //typescript์—๊ฒŒ HTML ์š”์†Œ์ž„์„ ์•Œ๋ฆผ
  return (
    <Wrapper>
      <BiggerBox ref={biggerBoxRef}>
        <Box
          drag
          dragConstraints={biggerBoxRef}
          variants={boxVariants}
          whileDrag="drag"
          whileHover="hover"
          whileTap="click"
        />
      </BiggerBox>
    </Wrapper>
  );
}

๋ณด๋‹ค์‹œํ”ผ ref ์„ค์ •ํ•œ ๋ถ€๋ถ„์— ์ œ์•ฝ์ด ๊ฑธ๋ฆฐ๋‹ค.





๐Ÿงฉ dragSnapToOrigin

๋“œ๋ž˜๊ทธ ๊ฐ€๋Šฅํ•œ ์š”์†Œ๋Š” ๋“œ๋ž˜๊ทธ๋ฅผ ๋†“์„ ๋•Œ, ์›์ ์œผ๋กœ ๋˜๋Œ์•„๊ฐ

function App() {
  const biggerBoxRef = useRef<HTMLDivElement>(null);
  return (
    <Wrapper>
      <BiggerBox ref={biggerBoxRef}>
        <Box
          drag
          dragSnapToOrigin //์—ฌ๊ธฐ๋งŒ ์ถ”๊ฐ€ํ•ด์ฃผ๋ฉด๋จ
          dragConstraints={biggerBoxRef}
          variants={boxVariants}
          whileDrag="drag"
          whileHover="hover"
          whileTap="click"
        />
      </BiggerBox>
    </Wrapper>
  );
}





๐Ÿงฉ dragElastic

์™ธ๋ถ€ ์ œ์•ฝ ์กฐ๊ฑด์—์„œ ํ—ˆ์šฉ๋˜๋Š” ์ด๋™ ์ •๋„
0 = ์›€์ง์ž„ ์—†์Œ, 1 = ์ „์ฒด ์›€์ง์ž„. ๊ธฐ๋ณธ๊ฐ’ 0.5

function App() {
  const biggerBoxRef = useRef<HTMLDivElement>(null);
  return (
    <Wrapper>
      <BiggerBox ref={biggerBoxRef}>
        <Box
          drag
          dragSnapToOrigin
          dragElastic={0.5} //๋Œ€์‹  BiggerBox์˜ overflow:hidden์€ ์ง€์›Œ์ฃผ์ž
          dragConstraints={biggerBoxRef}
          variants={boxVariants}
          whileDrag="drag"
          whileHover="hover"
          whileTap="click"
        />
      </BiggerBox>
    </Wrapper>
  );
}
profile
๊ฐ•์˜์ˆ˜๊ฐ•๊ธฐ๋ก์šฉ

0๊ฐœ์˜ ๋Œ“๊ธ€