Next.js中ScrollMagic与GSAP集成及animation.gsap.js加载问题
Got it, let's fix that ScrollMagic + GSAP loading issue in your Next.js project once and for all. The problem stems from a mix of SSR restrictions, GSAP 3 compatibility, and incorrect plugin loading timing. Here's the step-by-step solution using scrollmagic-plugin-gsap (the fix you landed on) to ensure everything loads correctly:
1. Install the Right Dependencies
First, swap out the manual plugin import for the official GSAP 3-compatible plugin package. Uninstall any old plugin files if you added them manually, then run:
npm install scrollmagic scrollmagic-plugin-gsap gsap # Or with yarn yarn add scrollmagic scrollmagic-plugin-gsap gsap
2. Rewrite the TextFade Component
We'll clean up the component to use the new plugin, handle SSR properly, and add cleanup to avoid memory leaks:
import React, { PureComponent } from "react"; import gsap from "gsap"; import ScrollMagic from "scrollmagic"; import { ScrollMagicPluginGsap } from "scrollmagic-plugin-gsap"; // Register the GSAP plugin with ScrollMagic FIRST ScrollMagicPluginGsap(ScrollMagic, gsap); export default class TextFade extends PureComponent { constructor(props) { super(props); this.myRef = React.createRef(); this.controller = null; } componentDidMount() { // Initialize ScrollMagic controller only on the client this.controller = new ScrollMagic.Controller(); // Build your GSAP timeline (using GSAP 3's syntax) const tl = gsap.timeline() .from(this.myRef.current, 0.5, { opacity: 0 }) .to(this.myRef.current, 0.5, { opacity: 0 }, 0.5); // Create and attach the ScrollMagic scene new ScrollMagic.Scene({ triggerElement: this.myRef.current, triggerHook: 0.3, duration: "100%" }) .setPin(this.myRef.current) .setTween(tl) // .addIndicators() // Uncomment for debugging (requires scrollmagic-plugin-indicators) .addTo(this.controller); } componentWillUnmount() { // Clean up the controller when the component unmounts if (this.controller) { this.controller.destroy(true); } } render() { return ( <div ref={this.myRef} className="bg-gray0 padding-top-6 padding-bottom-6"> <div id="TextBlock"> <h1>Heading to animation</h1> <p>Also with text too</p> </div> </div> ); } }
3. Dynamically Import the Component in Your Page
Since ScrollMagic depends on window, we need to disable SSR for this component using Next.js's dynamic import:
import dynamic from "next/dynamic"; // Import TextFade without SSR const TextFade = dynamic(() => import("../components/TextFade"), { ssr: false, loading: () => <div>Loading animation...</div> // Optional loading placeholder }); export default function Home() { return ( <div className="page-container"> <TextFade /> </div> ); }
Why Your Original Approach Failed
- SSR Window Restriction: Next.js runs code on the server first, where
windowdoesn't exist. Directly importing ScrollMagic at the top of your component caused errors until you switched to no-SSR loading, but the plugin timing was still off. - GSAP 3 Incompatibility: The old
animation.gsap.min.jsplugin is built for GSAP 2.x. GSAP 3 changed its API, so that plugin couldn't hook into it properly.scrollmagic-plugin-gsapis maintained to work with GSAP 3+. - Dynamic Loading Timing: Using
requireinsidecomponentDidMountmeant ScrollMagic might initialize before the plugin was loaded, leading to missingsetTweenfunctionality. Registering the plugin upfront (after importing) fixes this.
Extra Tips
- For debugging scene triggers, install
scrollmagic-plugin-gsap's sibling packagescrollmagic-plugin-indicatorsand uncomment the.addIndicators()line. - Always destroy the ScrollMagic controller in
componentWillUnmountto prevent memory leaks in single-page apps.
内容的提问来源于stack exchange,提问作者Niverhawk

