ํ๋ก๊ทธ๋๋ฐ ์ธ๊ณ๋ฅผ ํ๊ตฌํฉ์๋ค.
react Framer-motion ๋ฆฌ์กํธ ํ๋ ์ด๋จธ ๋ชจ์ ํ์ฉํ๊ธฐ
React Framer Motion์ ์ฃผ๋ก ๋ค์๊ณผ ๊ฐ์ ์ญํ ์ ํฉ๋๋ค:
์ ๋๋ฉ์ด์
์ ์ด: ์ฌ์ฉ์๊ฐ ์ ์ํ ์ปดํฌ๋ํธ๋ DOM ์์๋ฅผ ์ ๋๋ฉ์ด์
ํํ ์ ์์ต๋๋ค. ์์ง์, ํฌ๊ธฐ ์กฐ์ , ํ์ ๋ฑ ๋ค์ํ ์ ๋๋ฉ์ด์
ํจ๊ณผ๋ฅผ ๊ตฌํํ ์ ์์ต๋๋ค.
์ ์ค์ฒ ์ฒ๋ฆฌ: ํฐ์น, ํด๋ฆญ ๋ฑ์ ์ ์ค์ฒ ์ด๋ฒคํธ๋ฅผ ๊ฐ์งํ๊ณ ์ด์ ๋ฐ๋ฅธ ์ ๋๋ฉ์ด์
์ ์ฝ๊ฒ ์ถ๊ฐํ ์ ์์ต๋๋ค.
์ปดํฌ๋ํธ ๊ฐ ํต์ : ๋ค์ํ ์ปดํฌ๋ํธ ๊ฐ์ ํต์ ์ ์ด์งํ๋ฉฐ, ์ ๋๋ฉ์ด์
์ ํตํ ์ฌ์ฉ์ ๊ฒฝํ ํฅ์์ ๊ธฐ์ฌํฉ๋๋ค.
react Framer-motion ๋ฆฌ์กํธ ํ๋ ์ด๋จธ ๋ชจ์ ๊ตฌํ ์์
๊ตฌํ ์์ ํ๋ฉด์ ๋๋ค.
๋ฐ์ค ํจ๊ณผ, ๋ง์ฐ์ค hover ์ box๊ฐ ์ปค์ง๋ ํจ๊ณผ, ๋ฒํผ์ด ๋ํ๋๋ ํจ๊ณผ๋ฅผ ์ฌ์ฉํ์ต๋๋ค.
react Framer-motion ๋ฆฌ์กํธ ํ๋ ์ด๋จธ ๋ชจ์ ํ์ฉ ๋ฐฉ๋ฒ
1. ๊ณต์ ์ฌ์ดํธ
๋ค์ํ ํจ๊ณผ์ ์ฌ์ดํธ๋ ์๋ ์ฌ์ดํธ ์ฐธ๊ณ ๋ฐ๋๋๋ค.
https://www.framer.com/motion/
1. ์ ์ค์ฒ ์ด๋ฒคํธ์ ํธ๋์ง์ : whileHover, whileTap ๋ฑ์ ์ ์ค์ฒ ๊ด๋ จ ์ด๋ฒคํธ๋ฅผ ํตํด ์ฌ์ฉ์ ์ํธ ์์ฉ์ ๋ฐ์ํ๋ฉฐ ๋ถ๋๋ฌ์ด ํธ๋์ง์ ์ ์ ๊ณตํฉ๋๋ค.
2. ํ๋ ์-๋ณ ์ ๋๋ฉ์ด์ : animate ์์ฑ์ ํตํด ํน์ ํ๋ ์์์์ ์์ฑ์ ์ง์ ํ๊ณ , ๋ถ๋๋ฝ๊ฒ ์ ํํ ์ ์์ต๋๋ค.
2. ์ค์น
์๋ ๋ช ๋ น์ด๋ฅผ ์ ๋ ฅํ๋ฉด ์ค์นํ ์ ์์ต๋๋ค.
npm install framer-motion
3. ์ฌ์ฉ ๋ฐฉ๋ฒ
motion์ ์ํฌํธํ๊ณ motion.div๋ฅผ ์์ฑํ์ฌ ์ฌ์ฉํ ์ ์์ต๋๋ค.
import { motion } from 'framer-motion'
<motion.div animate={{ scale: 0.7 }} />
4. ์์ฑ ์ฝ๋
์์ ํ๋ฉด์ ๋ํ ์์ฑ ์ฝ๋์ ๋๋ค.
import style from './Main.module.css';
import { motion } from "framer-motion";
import { Link } from 'react-router-dom';
import { useState } from 'react';
function Main() {
// ๋ฒํผ ์ด๋ฏธ์ง์ ์ ๋๋ฉ์ด์
์ํ๋ฅผ ์ ์ดํ๊ธฐ ์ํ state
const [isHovered, setIsHovered] = useState(false);
// ๋ฒํผ ๋ฐ์ค์ ์ ๋๋ฉ์ด์
์ํ๋ฅผ ์ ์ํฉ๋๋ค.
const buttonBoxVariants = {
hover: { scale: 1.1 },
tap: { scale: 0.9 }
};
// ๋ฒํผ ์ด๋ฏธ์ง์ ์ ๋๋ฉ์ด์
์ํ๋ฅผ ์ ์ํฉ๋๋ค.
const buttonIconVariants = {
hidden: { x: -30, opacity: 0 }, // ์ผ์ชฝ์ ์จ๊ฒจ์ง ์ํ
visible: { x: 0, opacity: 1 } // ์๋ ์์น์ ๋ํ๋ ์ํ
};
return (
<div className={style.mainpage}>
<div className={style.main}>
<div className={style.main_text}>
<h1 className={style.main_text1}><span className={style.highlight1}>๋ง</span>์ง,</h1>
<h1 className={style.main_text2}><span className={style.highlight2}>๋ฑ์ฐ</span>๋ก,</h1>
<h1 className={style.main_text2}><span className={style.highlight1}>์ฐ์
๊ธฐ์์ ๋ณด</span>๋ฅผ</h1>
<h1 className={style.main_text3}>
<span>ํ ๋ฒ์ ๊ฒ์์ผ๋ก ํ์ธํ์ธ์.</span>
<motion.span
className={style.underline}
initial={{ width: 0 }}
animate={{ width: "100%" }}
transition={{
repeat: Infinity,
repeatType: "reverse",
duration: 3
}}
/>
</h1>
</div>
<div className={style.main_box}>
<Link className={style.main_map} to="/map">
<motion.div
className={style.box}
variants={buttonBoxVariants}
whileHover="hover"
whileTap="tap"
onHoverStart={() => setIsHovered(true)}
onHoverEnd={() => setIsHovered(false)}
>
<div className={style.main_mapimg}>
<img src={`${process.env.PUBLIC_URL}/img/mapimg.png`} alt="mapimg" className={style.mapimg} />
</div>
{/* ํ
์คํธ ๋ถ๋ถ */}
<div className={style.box_text1}>
๋ฑ์ฐ ์ ๋ณด ๊ฒ์ํ๋ฌ ๊ฐ๊ธฐ
</div>
{/* ์ด๋ฏธ์ง ๋ถ๋ถ */}
<motion.img
src={`${process.env.PUBLIC_URL}/img/button.svg`}
alt="๋ฒํผ"
className={style.buttonIcon}
variants={buttonIconVariants}
initial="hidden"
animate={isHovered ? "visible" : "hidden"}
transition={{ duration: 0.3 }}
/>
</motion.div>
</Link>
</div>
</div>
</div>
);
}
export default Main;
์์ ๊ฐ์ ๋ฐฉ์์ผ๋ก react์์ framer-motion์ ์ฌ์ฉํ์ฌ ์ ๋๋ฉ์ด์ ์ ํจ๊ณผ์ ์ผ๋ก ๊ตฌํํ ์ ์์ต๋๋ค.