You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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>
  );
}

问题原因

  1. Fullpage.js默认会把所有section渲染在DOM中,仅通过CSS控制显示/隐藏,不会触发组件的挂载/卸载,而Framer Motion的AnimatePresence需要检测组件的挂载/卸载才能触发initial和exit动画。
  2. 当前代码没有利用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 14:05:56