Next.js (React) & ScrollMagic

空扰寡人 提交于 2019-12-22 03:36:46

问题


I would like to implement an animation to fade sections, like in this example, into my application. Therefore I've had a look at fullPage.js.

However, since I need to integrate it into a Next.js React app with server-side rendering I can't use it since it relays on jQuery, which doesn't support SSR. Therefore I've tried my luck with ScrollMagic, which doesn't relay on jQuery. But it also doesn't support SSR (needs window), therefore I've initialized it in the componentDidMount() method and even loaded it there (like it's recommended here).

It currently works initially, but as soon as you change the page and an AJAX request is done and Next.js replaces the page, an error will be thrown (see below):

Node was not found

I've tried to destroy ScrollMagic before the AJAX request in componentWillUnmount(), but with no luck. I can't figure out what's wrong and unfortunately, I couldn't find any documentation about ScrollMagic with React or Next.js.

This is my entire component:

import React from 'react';
import PropTypes from 'prop-types';

class VerticalSlider extends React.Component {
  constructor(props) {
    super(props);
    this.ScrollMagic = null;
    this.controller = null;
    this.scenes = [];
    this.container = React.createRef();
  }

  componentDidMount() {
    if (this.container.current) {
      // Why "require" here?
      // https://github.com/zeit/next.js/issues/219#issuecomment-393939863
      // We can't render the component server-side, but we will still render
      // the HTML
      // eslint-disable-next-line global-require
      this.ScrollMagic = require('scrollmagic');
      this.initScroller();
    }
  }

  componentWillUnmount() {
    this.scenes.forEach(scene => {
      scene.destroy();
    });
    this.controller.destroy();
    this.scenes = [];
    this.controller = null;
  }

  initScroller() {
    try {
      this.controller = new this.ScrollMagic.Controller();
      if (this.container.current !== null && this.container.current.children) {
        [...this.container.current.children].forEach(children => {
          const scene = new this.ScrollMagic.Scene({
            triggerElement: children,
            duration: window.innerHeight * 1.5,
            triggerHook: 0,
            reverse: true
          });
          scene.setPin(children);
          this.scenes.push(scene);
        });
        this.controller.addScene(this.scenes);
      }
    } catch (e) {
      console.log(e);
    }
  }

  render() {
    return (
      <div ref={this.container}>
        {this.props.sections}
      </div>
    );
  }
}

VerticalSlider.propTypes = {
  sections: PropTypes.arrayOf(PropTypes.node).isRequired
};

export default VerticalSlider;

回答1:


Would fullpage.js not be more in line with what you need?

You should be able to map your routes and then build each slide as a placeholder for the page using the app.js

Else i have a working example of scroll magic, i will lookup my repo and repost it here once i found it.




回答2:


Although in some other venues people suggested using next/dynamic and importing the ScrollMagic library with the option 'ssr:false', I did not have success with this tactic. The ScrollMagic object was not returned correctly.

What ended up working for me was to use a modified version of the ScrollMagic library (modified by Jan Fischer: https://github.com/bitworking) in which the whole ScrollMagic library is wrapped "in a self invoking function so that I can mock the window and document object." I copied this modified ScrollMagic to my next.js project and referenced it instead of including the package as a node module.

Here is the modified file: https://raw.githubusercontent.com/bitworking/react-scrollmagic/master/src/lib/scrollmagic.js



来源:https://stackoverflow.com/questions/50680766/next-js-react-scrollmagic

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!