ขอแนะนำ Framer Motion
เผยแพร่แล้ว: 2022-03-10ในบทความนี้ เราจะมาดูรายละเอียดกันว่า Framer Motion ช่วยเราในการสร้างแอนิเมชั่นที่ยอดเยี่ยมได้อย่างไร เราจะเรียนรู้ว่าองค์ประกอบการเคลื่อนไหวทำงานอย่างไร และเรียนรู้วิธีเชื่อมโยงแอนิเมชั่นเข้าด้วยกัน เราจะมาดูวิธีการสร้างแอนิเมชั่นการสั่งการด้วยท่าทาง หมดเวลา และเลื่อนด้วย Framer Motion ระหว่างทาง เราจะใช้สิ่งที่เราเรียนรู้เพื่อสร้างแอปพลิเคชันสาธิตห้ารายการที่ฉันตั้งค่าเพื่อแสดงให้เราเห็นว่าเราจะผสานรวม Framer Motion เข้ากับแอปพลิเคชันในโลกแห่งความเป็นจริงได้อย่างไร
บทช่วยสอนนี้จะเป็นประโยชน์กับผู้อ่านที่สนใจในการรวมแอนิเมชั่นในแอปพลิเคชัน React ของพวกเขา
หมายเหตุ: บทความนี้ต้องการความเข้าใจพื้นฐานเกี่ยวกับ React และ CSS
Framer Motion คืออะไร?
Framer Motion เป็นไลบรารีแอนิเมชั่นที่ทำให้การสร้างแอนิเมชั่นเป็นเรื่องง่าย API แบบง่ายช่วยให้เราสรุปความซับซ้อนเบื้องหลังแอนิเมชั่น และช่วยให้เราสร้างแอนิเมชั่นได้อย่างง่ายดาย
ส่วนประกอบการเคลื่อนไหว
สิ่งเหล่านี้คือองค์ประกอบสำคัญของการเคลื่อนไหว Framer องค์ประกอบการเคลื่อนไหวถูกสร้างขึ้นโดยนำหน้า motion
ไปยังองค์ประกอบ HTML และ SVG ปกติของคุณ (เช่น motion.h1
) ส่วนประกอบการเคลื่อนไหวสามารถรับอุปกรณ์ประกอบฉากได้หลายแบบ โดยอุปกรณ์พื้นฐานคืออุปกรณ์ประกอบฉาก animate
อุปกรณ์ประกอบฉากนี้ใช้วัตถุที่เรากำหนดคุณสมบัติขององค์ประกอบนั้นที่เราต้องการให้เคลื่อนไหว คุณสมบัติที่เรากำหนดจะเคลื่อนไหวเมื่อส่วนประกอบเชื่อมต่อใน DOM
มาทำให้ข้อความ h1 เคลื่อนไหวโดยใช้ Framer Motion ขั้นแรก เราติดตั้งไลบรารี framer-motion และนำเข้า motion
npm i framer-motion import { motion } from 'framer-motion';
จากนั้นเราแปลง h1 เป็นองค์ประกอบการเคลื่อนไหว
<motion.h1 animate={{x: 20, y: -20}}> This is a motion component </motion.h1>
ซึ่งจะทำให้ h1
เลื่อนไปทางขวา 20px และเลื่อนขึ้น 20px เมื่อโหลดขึ้น เมื่อไม่ได้เพิ่มหน่วย การคำนวณจะทำโดยใช้พิกเซล อย่างไรก็ตาม คุณสามารถตั้งค่าหน่วยที่ต้องการให้คำนวณได้อย่างชัดเจน animate={{x: "20rem", y: "-20rem"}}>
โดยค่าเริ่มต้น ส่วนประกอบการเคลื่อนไหวจะเคลื่อนไหวจากสถานะที่กำหนดไว้ตั้งแต่สไตล์ไปจนถึงองค์ประกอบในพร็อพ animate
อย่างไรก็ตาม หากเราต้องการ เราสามารถจี้และกำหนดสถานะแอนิเมชั่นเริ่มต้นของส่วนประกอบโดยใช้อุปกรณ์ประกอบฉาก initial
แม้ว่าพร็อพ animate
จะใช้เพื่อกำหนดพฤติกรรมของส่วนประกอบเมื่อเชื่อมต่อ พร็อพ initial
จะกำหนดลักษณะการทำงานก่อนที่จะเมาต์
ถ้าเราต้องการให้ h1 เข้ามาทางซ้าย เราควบคุมมันโดยใช้เสาตั้งต้น
<motion.h1 initial={{x: -1000}} animate={{x: 20}}> This is a motion component </motion.h1>
ตอนนี้ เมื่อ h1
ขึ้น มันจะเลื่อนเข้ามาจากด้านซ้าย
เราไม่ได้จำกัดอยู่แค่แอนิเมชั่นเดียว เราสามารถกำหนดชุดของแอนิเมชั่นที่เรียกว่า keyframes
ในอาร์เรย์ของค่าต่างๆ แต่ละค่าจะได้รับภาพเคลื่อนไหวตามลำดับ
<motion.h1 initial={{x: -1000}} animate={{x: [20, 50, 0, -70, 40] }}> This is a motion component </motion.h1>
พร็อพ transition
ช่วยให้เราสามารถกำหนดว่าแอนิเมชั่นเกิดขึ้นได้อย่างไร ด้วยเหตุนี้ เราจึงกำหนดว่าค่าต่างๆ จะเคลื่อนไหวจากสถานะหนึ่งไปอีกสถานะหนึ่งอย่างไร เหนือสิ่งอื่นใด เราสามารถกำหนด duration
delay
และ type
ของแอนิเมชั่นโดยใช้อุปกรณ์ประกอบฉากนี้
<motion.h1 initial={{ x: -1000 }} animate={{ x: 0 }} transition={{ type: "tween", duration: "2", delay: "1" }}> This is a motion component </motion.h1>
สมมติว่าเราต้องทำให้องค์ประกอบการเคลื่อนไหวหลาย ๆ เคลื่อนไหวพร้อมๆ กัน เช่นในข้อมูลโค้ดด้านล่าง
<div className="App"> <motion.h1 initial={{ x: -1000 }} animate={{ x: 0 }} transition={{ type: "tween", duration: "2", delay: "1" }}> This is a motion h1 </motion.h1> <motion.h2 initial={{ y: -1000 }} animate={{ y: 0 }} transition={{ type: "tween", duration: "1", delay: ".4" }}>This is a motion h2 </motion.h2> <motion.h3 initial={{ x: 100, opacity: 0 }} animate={{ x: 0, opacity: 1 }}> This is a motion h3 </motion.h3> <motion.h4 initial={{ scale: 0.7 }} animate={{ scale: 1.7 }} transition={{ type: "tween", duration: "2", delay: "1" }}> This is a motion h4 </motion.h4> </div>
แม้ว่าจะใช้งานได้ แต่ variants
ประกอบใน Framer Motion ช่วยให้เราสามารถแยกคำจำกัดความของแอนิเมชั่นของเราออกเป็นอ็อบเจ็กต์ Variation variants
ไม่เพียงแต่ทำให้โค้ดของเราสะอาดขึ้น แต่ยังช่วยให้เราสร้างแอนิเมชั่นที่ทรงพลังและซับซ้อนยิ่งขึ้นอีกด้วย
การแยกคำจำกัดความของแอนิเมชั่นของเราออกเป็นอ็อบเจ็กต์ตัวแปร เรามีสิ่งนี้:
const H1Variants = { initial: { x: -1000 }, animate: { x: 0 }, transition: { type: "tween", duration: 2, delay: 1 } } const H2Variants = { initial: { y: -1000 }, animate: { y: 0 }, transition: { type: "tween", duration: 1, delay: .4 } } const H3Variants = { initial:{ x: 100, opacity: 0 }, animate:{ x: 0, opacity: 1 } } const H4Variants = { initial:{ scale: 0.7 }, animate:{ scale: 1.7 }, transition:{ type: "tween", duration: "2", delay: "1" } }
แทนที่จะส่งคำจำกัดความของแอนิเมชั่นไปยังอุปกรณ์ประกอบฉาก initial
และอุปกรณ์ animate
โดยตรงของคอมโพเนนต์ เราแยกคำจำกัดความเหล่านี้ออกเป็นออบเจ็กต์ตัวแปรแบบสแตนด์อโลน ในออบเจ็กต์ตัวแปร เรากำหนดชื่อตัวแปรที่อธิบายชื่อของแอนิเมชั่นแต่ละรายการเป็นรายละเอียดปลีกย่อย
<div className="App"> <motion.h1 variants={H1Variants} initial='initial' animate='animate' > This is a motion h1 </motion.h1> <motion.h2 variants={H2Variants} initial='initial' animate='animate' > This is a motion h2 </motion.h2> <motion.h3 variants={H3Variants} initial='initial' animate='animate' > This is a motion h3 </motion.h3> <motion.h4 variants={H4Variants} initial='initial' animate='animate' > This is a motion h4 </motion.h4> </div>
ในอุปกรณ์ประกอบฉาก variants
เราจะส่งต่อชื่อของวัตถุที่แปรผันสำหรับองค์ประกอบการเคลื่อนไหวแต่ละอย่าง จากนั้นจึงส่งต่อภาพเคลื่อนไหวไปยังอุปกรณ์ประกอบฉาก initial
และอุปกรณ์ประกอบฉากที่ animate
เราสามารถใช้การตั้งค่าปัจจุบันของเรากับตัวแปรเพิ่มเติมเพื่อลดการซ้ำซ้อน เมื่อใช้ตัวแปร เราสามารถเผยแพร่แอตทริบิวต์แอนิเมชันลงผ่าน DOM จากคอมโพเนนต์การเคลื่อนไหวหลัก เพื่อให้ใช้งานได้ เราสร้างตัวแปรสำหรับ parent motion.div
ที่มีชื่อแอนิเมชั่นที่คล้ายกันในออบเจ็กต์ตัวแปรเป็นลูก เมื่อทำเช่นนี้ เราจะไม่ต้องส่งชื่อแอนิเมชัน' ไปยังคอมโพเนนต์ย่อยแต่ละคอมโพเนนต์ เบื้องหลังองค์ประกอบหลักจัดการให้เรา
const ContainerVariants = { initial: {}, animate: {} }; const H1Variants = { initial: { x: -1000 }, animate: { x: 0 }, transition: { type: "tween", duration: 2, delay: 1 } }; //more variants below <motion.div className="App" variants={ContainerVariants} initial="initial" animate="animate" > <motion.h1 variants={H1Variants}>This is a motion h1</motion.h1> <motion.h2 variants={H2Variants}>This is a motion h2</motion.h2> <motion.h3 variants={H3Variants}>This is a motion h3</motion.h3> <motion.h4 variants={H4Variants}>This is a motion h4</motion.h4> </motion.div>
ตอนนี้เรามีรหัสที่สะอาดกว่าโดยไม่มีการซ้ำซ้อน เราเปลี่ยน div คอนเทนเนอร์เป็นองค์ประกอบการเคลื่อนไหวเพื่อให้เราสามารถส่งผ่านในอ็อบเจ็กต์ ContainerVariants
ที่เรากำหนดได้ เนื่องจากเราไม่ได้กำหนดแอนิเมชั่นใดๆ บนคอนเทนเนอร์ เราจึงส่งอ็อบเจ็กต์ว่างไปยัง initial
และ animate
ชื่อแอนิเมชั่นของคุณต้องเหมือนกันในทุกอ็อบเจ็กต์ตัวแปรเพื่อให้การขยายพันธุ์ทำงาน
ตอนนี้เราเข้าใจพื้นฐานของ Framer Motion แล้ว มาเริ่มสร้างแอปพลิเคชันสาธิต 5 แอปพลิเคชันกันเลย
ร้านไอคอน
เราสามารถสร้างแอนิเมชั่นแบบโต้ตอบตามท่าทางได้ ปัจจุบันคอมโพเนนต์การเคลื่อนไหวสามารถฟังการตรวจจับท่าทางสัมผัส การแตะ เลื่อน และลากได้ เราจะสร้างแอพ Icon Shop นี้โดยใช้ whileHover
prop
ส่วนประกอบ
-
App.js
: นี้เก็บข้อความหัวเรื่อง -
Card.jsx
: ที่นี่ เรากำหนดภาพเคลื่อนไหวสำหรับการ์ดไอคอน -
CardContainer.jsx
: เรานำเข้าและวนซ้ำไอคอนต่างๆ -
styles.js
: สร้าง จัดรูปแบบ และส่งออกส่วนประกอบการเคลื่อนไหว ฉันใช้ส่วนประกอบที่มีสไตล์เพื่อจัดสไตล์ส่วนประกอบ
มาเริ่มกันที่ App.js
import { H1, H2 } from "./Styles"; import CardContainer from "./CardContainer"; return ( <div> <H1 initial={{ y: -100 }} animate={{ y: 0, transition: { delay: 1 } }}> Icon Shop </H1> <H2 initial={{ x: -1000 }} animate={{ x: 0, transition: { delay: 1 } }}> Hover over the cards to see the motion magic </H2> <CardContainer /> </div> );
เรานำเข้าส่วนประกอบการเคลื่อนไหว H1
และ H2
ที่เราสร้างขึ้นในไฟล์ Styles.js
เนื่องจากเป็นส่วนประกอบในการเคลื่อนไหว เราจึงใช้อุปกรณ์ประกอบฉาก initial
และ animate
เพื่อกำหนดพฤติกรรมก่อนและเมื่อติดตั้ง ที่นี่ เรายังนำเข้าและแสดงองค์ประกอบ CardContiner
ตอนนี้ CardContainer.js
import { Container } from "./Styles"; import Card from "./Card"; import { ReactComponent as AddIcon } from "./assets/add.svg"; import { ReactComponent as AirplaneIcon } from "./assets/airplane.svg"; import { ReactComponent as AlarmIcon } from "./assets/alarm.svg"; //more svg imports below... const icons = [ <AddIcon />, <AirplaneIcon />, <AlarmIcon />, //more icons below ]; const CardContainer = () => { return ( <Container initial={{ x: -1000 }} animate={{ x: 0 }}> {icons.map((icon) => ( <Card icon={icon} /> ))} </Container> ); };
ที่นี่ เรานำเข้า SVG ส่วนประกอบการเคลื่อนไหวของ Container
และส่วนประกอบ Card
คล้ายกับ H1
และ H2
ใน App.js
เรากำหนดแอนิเมชั่นของ Container
โดยใช้อุปกรณ์ประกอบฉาก initial
และ animate
เมื่อโหลดมันจะสร้างเอฟเฟกต์เจ๋ง ๆ ของการเลื่อนเข้ามาจากด้านซ้ายของเบราว์เซอร์
ตอนนี้ Card.js
import { CardBox, IconBox } from "./Styles"; const CardVariants = { beforeHover: {}, onHover: { scale: 1.1 } }; const IconVariants = { beforeHover: { opacity: 0, y: -50 }, onHover: { opacity: 1, y: 0, scale: 1.5, transition: { type: "tween" } } }; const Card = ({ icon }) => { console.log(icon); return ( <CardBox variants={CardVariants} initial="beforeHover" whileHover="onHover"> <IconBox variants={IconVariants}>{icon}</IconBox> </CardBox> ); };
ที่นี่ เราสร้างอ็อบเจ็กต์ที่แตกต่างสองรายการด้วยแอนิเมชั่น beforeHover
และ onHover
ในอ็อบเจ็กต์ CardVariants
เราไม่ต้องการทำอะไรในตอนแรก ดังนั้น beforeHover
จึงเป็นอ็อบเจกต์ว่าง onHover
เราเพิ่มขนาดของกล่องการ์ด
ในอ็อบเจ็กต์ IconVariants
เรากำหนดสถานะเริ่มต้นของ IconBox
ใน beforeHover
เราตั้งค่าความทึบเป็น 0 และดันขึ้นไป 50px จากนั้นใน onHover
เราตั้งค่าความทึบกลับเป็น 1 ดันกลับไปที่ตำแหน่งเริ่มต้น และเปลี่ยนประเภทการเปลี่ยนเป็น tween
จากนั้นเราจะส่งต่อตัวแปรต่างๆ ไปยังส่วนประกอบการเคลื่อนไหวที่เกี่ยวข้อง เราใช้การขยายพันธุ์ ดังนั้นเราจึงไม่จำเป็นต้องตั้งค่า initial
และอุปกรณ์ประกอบฉาก animate
ไปยังองค์ประกอบ IconBox
อย่างชัดเจน
Navbar เคลื่อนไหว
เราจะสร้างองค์ประกอบการนำทางอย่างง่าย และเราจะดูว่าเราจะสร้างความสัมพันธ์ด้านเวลาระหว่างส่วนประกอบการเคลื่อนไหวของผู้ปกครองและเด็กได้อย่างไร
ส่วนประกอบ
-
App.js
: นี้เก็บข้อความหัวเรื่อง -
Styles.js
: สร้าง จัดรูปแบบ และส่งออกส่วนประกอบการเคลื่อนไหว ส่วนประกอบต่างๆ ถูกจัดรูปแบบโดยใช้ส่วนประกอบที่มีสไตล์
มาดูไฟล์ App.js
กัน
import { Header, Nav, Link, SvgBox } from "./Styles"; function App() { const [isOpen, setIsOpen] = useState(false); const iconVariants = { opened: { rotate: 135 }, closed: { rotate: 0 } }; const menuVariants = { opened: { top: 0, transition: { when: "beforeChildren", staggerChildren: 0.5 } }, closed: { top: "-90vh" } }; const linkVariants = { opened: { opacity: 1, y: 50 }, closed: { opacity: 0, y: 0 } };
เราสร้างสถานะ isOpen
ที่จะใช้ตรวจสอบว่า Navbar เปิดอยู่หรือไม่ เราสร้างอ็อบเจ็กต์ตัวแปร 3 รายการ, iconVariants
, menuVariants
และ linkVariants
ซึ่งเรากำหนดแอนิเมชั่นสำหรับคอมโพเนนต์การเคลื่อนไหว SvgBox
, Nav
และ Link
ตามลำดับ iconVariants
ใช้เพื่อหมุน SvgBox
135deg เมื่อวางเมาส์เหนือ เราไม่จำเป็นต้องเพิ่ม "deg" ให้กับค่า ใน menuVariants
เราควบคุมตำแหน่งบนสุดของ Nav
เช่นเดียวกับที่คุณใช้คุณสมบัติ position
ใน CSS เราสลับตำแหน่งบนสุดของการนำทางตาม isOpen
Nav
ด้วยตัวแปร เราสามารถสร้างความสัมพันธ์ด้านเวลาระหว่างส่วนประกอบการเคลื่อนไหวของผู้ปกครองและเด็ก เรากำหนดความสัมพันธ์ระหว่าง Nav
หลักและลูกของมัน Link
โดยใช้คุณสมบัติ when
ในออบเจกต์การเปลี่ยนแปลง ที่นี่ ตั้งค่าเป็น beforeChildren
ดังนั้นแอนิเมชั่นขององค์ประกอบหลักจะเสร็จสิ้นก่อนที่แอนิเมชั่นของเด็กจะเริ่มขึ้น
การใช้คุณสมบัติ staggerChildren
เราตั้งค่าลำดับเวลาสำหรับแต่ละลิงก์ แต่ละลิงก์จะใช้เวลา 0.5 วินาทีในการปรากฏขึ้นทีละรายการ สิ่งนี้จะสร้างสัญญาณภาพที่ดีเมื่อเปิด Nav
ทาง ใน linkVariants
เราทำให้ความทึบและตำแหน่งแนวตั้งของแต่ละลิงก์เคลื่อนไหว
<div className="App"> <Header> <SvgBox variants={iconVariants} animate={isOpen ? "opened" : "closed"} onClick={() => setIsOpen(!isOpen)} > <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="https://www.w3.org/2000/svg" > <path d="M12 4C11.4477 4 11 4.44772 11 5V11H5C4.44772 11 4 11.4477 4 12C4 12.5523 4.44772 13 5 13H11V19C11 19.5523 11.4477 20 12 20C12.5523 20 13 19.5523 13 19V13H19C19.5523 13 20 12.5523 20 12C20 11.4477 19.5523 11 19 11H13V5C13 4.44772 12.5523 4 12 4Z" fill="#fff" /> </svg> </SvgBox> </Header> <Nav initial={false} variants={menuVariants} animate={isOpen ? "opened" : "closed"} > <Link variants={linkVariants}>home</Link> <Link variants={linkVariants}>about</Link> <Link variants={linkVariants}>gallery</Link> </Nav> </div>
ในที่นี้ เราส่งต่อตัวแปรต่างๆ ไปยังส่วนประกอบที่เกี่ยวข้องกัน ใน SvgBox
เราสลับสถานะของ isOpen
ทุกครั้งที่มีการคลิก จากนั้นทำให้เคลื่อนไหวตามเงื่อนไขตามสถานะ เช่นเดียวกับ SvgBox
เราทำให้ Nav
และ Link
เคลื่อนไหวตามเงื่อนไขตามสถานะของ isOpen
โมดอลเคลื่อนไหว
เราจะสร้างองค์ประกอบโมดอลและเรียนรู้เกี่ยวกับ AnimatePresence
ของ Framer Motion และวิธีที่ช่วยให้เราสร้างองค์ประกอบเคลื่อนไหวเมื่อพวกเขาออกจาก DOM
ส่วนประกอบ:
-
App.js
: เราตั้งค่าสถานะshowModal
ที่นี่ -
Modal.jsx
: งานแอนิเมชั่นจริงเกิดขึ้นที่นี่ -
Styles.js
: สร้าง จัดรูปแบบ และส่งออกส่วนประกอบการเคลื่อนไหว ส่วนประกอบต่างๆ ถูกจัดรูปแบบโดยใช้ส่วนประกอบที่มีสไตล์
มาดู App.js
import { ToggleButton, Container } from "./Styles"; import Modal from "./Modal"; function App() { const [showModal, setShowModal] = useState(false); const toggleModal = () => { setShowModal(!showModal); }; return ( <Container> <ToggleButton initial={{ x: -700 }} animate={{ x: 0, transition: { duration: 0.5 } }} onClick={toggleModal} > Toggle Modal </ToggleButton> <Modal showModal={showModal} /> </Container> ); }
เราสร้างสถานะ showModal
ที่จะใช้เพื่อแสดงโมดอลตามเงื่อนไข ฟังก์ชัน toggleModal
จะสลับสถานะทุกครั้งที่มีการคลิก ToggleButton
ToggleButton
เป็นองค์ประกอบการเคลื่อนไหว ดังนั้นเราจึงสามารถกำหนดแอนิเมชั่นสำหรับมันได้ เมื่อติดตั้งแล้ว จะเลื่อนเข้าจากด้านซ้าย แอนิเมชั่นนี้ทำงานเป็นเวลา 0.5 วินาที นอกจากนี้เรายังส่งสถานะ showModal
ไปยัง Modal
ผ่านอุปกรณ์ประกอบฉาก
ตอนนี้ Modal.jsx
import { AnimatePresence } from "framer-motion"; import { ModalBox, ModalContent, Container } from "./Styles"; <Container> <AnimatePresence> {showModal && ( <ModalBox initial={{ opacity: 0, y: 60, scale: 0.3 }} animate={{ opacity: 1, y: 0, scale: 1, transition: { type: "spring", stiffness: 300 } }} exit={{ opacity: 0, scale: 0.5, transition: { duration: 0.6 } }} > <ModalContent initial={{ y: -30, opacity: 0 }} animate={{ y: 0, opacity: 1, transition: { delay: 1 } }} > Modal content!!!! </ModalContent> </ModalBox> )} </AnimatePresence> </Container>
เรานำเข้า AnimatePresence
จาก framer-motion
ช่วยให้เราสามารถตั้งค่าแอนิเมชั่นการออกสำหรับส่วนประกอบเมื่อออกจาก DOM เราแสดง Modal
ตามเงื่อนไขตามสถานะ showModal
เรากำหนดแอนิเมชั่นสำหรับ ModalBox
และ ModalContent
ผ่านอุปกรณ์ประกอบฉาก initial
และ animate
มีพร็อพใหม่อยู่ที่นี่ด้วย exit
การมี AnimatePresence
เป็น wrapper ช่วยให้เราสามารถเพิ่มแอนิเมชั่นการออกไปยัง ModalBox
ในอุปกรณ์ exit
เลื่อนนิเมชั่น
เราจะใช้ useAnimation
hook และ react-intersection-observer
ร่วมกันเพื่อสร้างแอนิเมชั่นที่เรียกด้วยการเลื่อน
ส่วนประกอบ
-
App.js
: เราตั้งค่าแอนิเมชั่นสำหรับองค์ประกอบBox
และแสดงผลในApp
-
Styles.js
: สร้าง จัดรูปแบบ และส่งออกส่วนประกอบการเคลื่อนไหว ส่วนประกอบต่างๆ ถูกจัดรูปแบบโดยใช้ส่วนประกอบที่มีสไตล์
import React, { useEffect } from "react"; import { useAnimation } from "framer-motion"; import { useInView } from "react-intersection-observer"; import { Container, H1,StyledBox } from "./Styles"; const BoxVariants = { visible: { opacity: 1, x: 0, transition: { duration: 1 } }, hidden: { opacity: 0, x: 300 }, }; const Box = () => { const controls = useAnimation(); const [ref, inView] = useInView(); useEffect(() => { if (inView) { controls.start("visible"); } }, [controls, inView]); return ( <StyledBox ref={ref} animate={controls} initial="hidden" variants={BoxVariants} /> ); };
useAnimation
hook ช่วยให้เราควบคุมลำดับที่แอนิเมชั่นของเราเกิดขึ้นได้ เรามีสิทธิ์เข้าถึงเมธอด controls.start
และ controls.stop
ที่เราสามารถใช้เพื่อเริ่มและหยุดแอนิเมชั่นของเราได้ด้วยตนเอง เราส่งแอนิเมชั่นที่ hidden
เริ่มต้นไปที่ StyledBox
เราส่งผ่านการควบคุมที่เรากำหนดด้วยวิธี start
ไปยัง StyledBox
เคลื่อนไหว prop
ตะขอ useInView
ของ react-intersection-observer
ช่วยให้เราติดตามเมื่อส่วนประกอบมองเห็นได้ในวิวพอร์ต useInView
hook ช่วยให้เราเข้าถึง ref
ซึ่งเราส่งผ่านไปยังส่วนประกอบที่เราต้องการดู และบูลีน inView
ที่จะบอกเราว่าองค์ประกอบนั้นเป็น inView
หรือไม่ เราใช้ useEffect
เพื่อเรียก controls.start
ทุกครั้งที่องค์ประกอบที่เรากำลังดูอยู่ StyledBox
อยู่ในมุมมอง เราส่งผ่าน controls
และ inView
เป็นการพึ่งพาของ useEffect
นอกจากนี้เรายังส่งต่อตัวแปรที่เรากำหนด BoxVariants
ไปยัง StyledBox
แอนิเมชั่นฮีโร่
เราจะสร้างแอนิเมชั่นแบนเนอร์ฮีโร่สุดเท่โดยใช้ useCycle
hook เราจะเข้าใจว่า useCycle
ช่วยให้เราหมุนเวียนภาพเคลื่อนไหวได้อย่างไร
import React, { useEffect } from "react"; import { useCycle } from "framer-motion"; import { Container, H1, HeroSection, Banner, TextBox } from "./Styles"; import { ReactComponent as BannerIllustration } from "./bighead.svg"; const H1Variants = { initial: { y: -200, opacity: 0 }, animate: { y: 0, opacity: 1, transition: { delay: 1 } }, }; const TextVariants = { initial: { x: 400 }, animate: { x: 0, transition: { duration: 0.5 } }, }; const BannerVariants = { animationOne: { x: -250, opacity: 1, transition: { duration: 0.5 } }, animationTwo: { y: [0, -20], opacity: 1, transition: { yoyo: Infinity, ease: "easeIn" }, }, };
เรากำหนด 3 ตัวแปร, H1Variants
, TextVariants
และ BannerVariants
อย่างไรก็ตาม จุดสนใจของเราคือ BannerVariants
เรากำหนด 2 แอนิเมชั่น, animationOne
หนึ่งและ animationTwo
สองใน BannerVariants
นี่คือแอนิเมชั่นที่เราส่งผ่านไปยัง useCycle
เพื่อหมุนเวียน
const [animation, cycleAnimation] = useCycle("animationOne", "animationTwo"); useEffect(() => { setTimeout(() => { cycleAnimation(); }, 2000); }, []);
useCycle
ทำงานคล้ายกับ useState
hook ในอาร์เรย์ที่ทำลายล้าง animation
แสดงถึงแอนิเมชั่นที่ทำงานอยู่ ไม่ว่าจะเป็น animationOne
หนึ่งหรือ animationTwo
สอง ฟังก์ชัน cylceAnimation
ที่วนไปมาระหว่างแอนิเมชั่นที่เรากำหนด เราส่งแอนิเมชั่นที่เราต้องการหมุนเวียนเข้าสู่ useCycle
และเรียก cylceAnimation
หลังจาก 2 วินาทีใน useEffect
<div className="App"> <Container> <H1 variants={H1Variants} initial="initial" animate="animate"> Cool Hero Section Anmiation </H1> <HeroSection> <TextBox variants={TextVariants} initial="initial" animate="animate"> Storage shed, troughs feed bale manure, is garden wheat oats at augers. Bulls at rose garden cucumbers mice sunflower wheat in pig. Chainsaw foal hay hook, herbs at combine harvester, children is mallet. Goat goose hen horse. Pick up truck livestock, pets and storage shed, troughs feed bale manure, is garden wheat oats at augers. Lamb. </TextBox> <Banner variants={BannerVariants} animate={animation}> <BannerIllustration /> </Banner> </HeroSection> </Container> </div>
ในตอนท้ายของทุกอย่าง เราจะส่งต่อตัวแปรต่างๆ ไปยังส่วนประกอบที่เกี่ยวข้องและเฝ้าดูความมหัศจรรย์เกิดขึ้น ด้วยวิธีนี้ Banner
จะเลื่อนเข้ามาจากด้านขวาในขั้นต้นตามแอนิเมชั่นที่เรากำหนดไว้ใน animationOne
หนึ่ง และหลังจากนั้น 2 วินาที ไซ cycleAnimation
แอนิเมชั่นจะถูกเรียกซึ่งจะทริกเกอร์ animationTwo
สอง
อย่างที่หมูผู้เฉลียวฉลาดเคยกล่าวไว้ว่า "ก็แค่นั้นแหละ"
บทสรุป
เราได้ศึกษาพื้นฐานของ Framer Motion แล้ว และได้เห็นโปรเจ็กต์ตัวอย่างบางโปรเจ็กต์ที่ให้ภาพรวมคร่าวๆ ของแอนิเมชั่นที่เราสามารถสร้างได้ อย่างไรก็ตาม คุณสามารถทำอะไรได้อีกมากมายกับมัน ฉันแนะนำให้คุณดำดิ่งลงไปในเอกสารและออกไปผจญภัย
ทรัพยากร
- เอกสาร Framer Motion Api, Framer Motion
- react-intersection-observer, npm
- Framer Motion สำหรับ React, NetNinja