React+Fullpage.js集成Framer-motion动画失效问题求助
问题描述
我尝试用Framer Motion、React.js搭配Fullpage.js实现切换section时触发动画,但目前切换section动画未触发,需要实现每次切换section都能触发动画的方案。
当前代码
React fullpage wrapper
'use client' import './globals.css' import { Poppins } from 'next/font/google' import ReactFullpage from "@fullpage/react-fullpage"; import React from 'react'; const poppins = Poppins({weight: "400", subsets: ["latin"] }); export default function RootLayout({ children, }: { children: React.ReactNode }) { return ( <html lang="en"> <body className={poppins.className}> <ReactFullpage navigation showActiveTooltip scrollOverflow={true} verticalCentered={true} anchors={['11', '22', '33', '44', '55']} onLeave={(origin, destination, direction) => { console.log("onLeave event", { origin, destination, direction }); console.log(destination.anchor); }} render={({ state, fullpageApi, origin, destination, direction }) => { return ( <> {children} </> ); }} /> </body> </html> ); }
Sections 组件(即{children})
"use client"; import * as React from "react"; import { motion, AnimatePresence } from "framer-motion"; export default function Sections() { return ( <AnimatePresence> <div className="section"> <motion.h1 initial={{ opacity: 0, y: -50 }} animate={{ opacity: 1, y: 0 }} exit={{ opacity: 0, y: -50 }} > 111111111111111111111111111111111111111111111 </motion.h1> </div> <div className="section"> <motion.h1 initial={{ opacity: 0, y: -50 }} animate={{ opacity: 1, y: 0 }} exit={{ opacity: 0, y: -50 }} > 22222222222222222222222222222222222222222222222 </motion.h1> </div> <div className="section"> <motion.h1 initial={{ opacity: 0, y: -50 }} animate={{ opacity: 1, y: 0 }} exit={{ opacity: 0, y: -50 }} > 3333333333333333333333333333333333333333333 </motion.h1> </div> <div className="section"> <motion.h1 initial={{ opacity: 0, y: -50 }} animate={{ opacity: 1, y: 0 }} exit={{ opacity: 0, y: -50 }} > 444444444444444444444444444444444444444444444 </motion.h1> </div> <div className="section"> <motion.h1 initial={{ opacity: 0, y: -50 }} animate={{ opacity: 1, y: 0 }} exit={{ opacity: 0, y: -50 }} > 55555555555555555555555555555555555555 </motion.h1> </div> </AnimatePresence> ); }
问题原因
- Fullpage.js默认会把所有section渲染在DOM中,仅通过CSS控制显示/隐藏,不会触发组件的挂载/卸载,而Framer Motion的
AnimatePresence需要检测组件的挂载/卸载才能触发initial和exit动画。 - 当前代码没有利用Fullpage.js的切换事件来控制动画的触发状态。
解决方案
修改RootLayout,维护当前激活的section锚点状态
'use client' import './globals.css' import { Poppins } from 'next/font/google' import ReactFullpage from "@fullpage/react-fullpage"; import React, { useState } from 'react'; const poppins = Poppins({weight: "400", subsets: ["latin"] }); export default function RootLayout({ children, }: { children: React.ReactNode }) { // 维护当前激活的section锚点 const [activeAnchor, setActiveAnchor] = useState('11'); return ( <html lang="en"> <body className={poppins.className}> <ReactFullpage navigation showActiveTooltip scrollOverflow={true} verticalCentered={true} anchors={['11', '22', '33', '44', '55']} // 切换完成后更新激活锚点 afterLoad={(origin, destination) => { setActiveAnchor(destination.anchor); }} render={({ fullpageApi }) => { // 把激活锚点传递给Sections组件 return ( <> {React.cloneElement(children, { activeAnchor })} </> ); }} /> </body> </html> ); }
修改Sections组件,仅渲染当前激活的section
"use client"; import * as React from "react"; import { motion, AnimatePresence } from "framer-motion"; // 抽离section数据,方便维护 const sectionData = [ { anchor: '11', text: '111111111111111111111111111111111111111111111' }, { anchor: '22', text: '22222222222222222222222222222222222222222222222' }, { anchor: '33', text: '3333333333333333333333333333333333333333333' }, { anchor: '44', text: '444444444444444444444444444444444444444444444' }, { anchor: '55', text: '55555555555555555555555555555555555555' }, ]; export default function Sections({ activeAnchor }) { return ( // mode="wait" 确保退出动画完成后再执行进入动画 <AnimatePresence mode="wait"> {sectionData.map((section) => { // 只渲染当前激活的section if (section.anchor !== activeAnchor) return null; return ( // 用锚点作为唯一key,让React识别组件变化 <div key={section.anchor} className="section"> <motion.h1 initial={{ opacity: 0, y: -50 }} animate={{ opacity: 1, y: 0 }} exit={{ opacity: 0, y: -50 }} transition={{ duration: 0.5 }} > {section.text} </motion.h1> </div> ); })} </AnimatePresence> ); }
说明
- 通过Fullpage.js的
afterLoad事件同步当前激活的section锚点,确保状态和视图一致。 - 仅渲染当前激活的section,让
AnimatePresence能检测到组件的挂载/卸载,从而触发initial和exit动画。 - 给每个section设置唯一
key,确保React正确识别组件的变化,保证动画触发正常。
内容的提问来源于stack exchange,提问作者SpicyyRiice
相关产品推荐
相关产品推荐

