ScrollMagic теряет функциональность после сборки Gatsby

Проблема: я пытался реализовать ScrollMagic через NPM в Gatsby. В то время как во время разработки (gatsby develop) ScrollMagic работает, после gatsby build и gatsby serve ScrollMagic либо показывает ошибку, либо теряет свою функциональность (оба шага описаны ниже).

Чего я хочу достичь? Работа ScrollMagic после сборки Gatsby.

Буду благодарен всем вашим советам!


1. Шаг, который я сделал: когда вы попытаетесь собрать проект Gatsby со ScrollMagic внутри, он покажет вам ошибку:

  36 |  // TODO: temporary workaround for chrome's scroll jitter bug
> 37 |  window.addEventListener("mousewheel", function () {});
     | ^
  38 | 
  39 |  // global const
  40 |  var PIN_SPACER_ATTRIBUTE = "data-scrollmagic-pin-spacer";


  WebpackError: ReferenceError: window is not defined

Очевидно, это происходит потому, что Gatsby использует среду Node для создания сборки со статическими файлами, а объект window недоступен в Node.

Таким образом, сборка не завершена и не создана. В документации Gatsby есть совет по этой конкретной «проблеме с не определенным окном» ( шаг 2).


2. шаг, который я сделал: я скопировал код с веб-сайта Gatsby и вставил его в свой gatsby-node.js:

exports.onCreateWebpackConfig = ({ stage, loaders, actions }) => {
    if (stage === "build-html") {
        actions.setWebpackConfig({
            module: {
                rules: [
                    {
                        test: /scrollmagic/,
                        use: loaders.null(),
                    }
                ],
            },
        })
    }
}

Сделав это и написав gatsby build и gatsby serve, Гэтсби успешно построил Интернет. Но после того, как я перейду на подстраницу, где должен быть включен ScrollMagic, он просто не работает и ScrollMagic теряет свою функциональность.


мои пакеты GSAP и ScrollMagic:

"scrollmagic": "^2.0.5",
"gsap": "^3.2.4"

Мой файл Gatsby, в котором ScrollMagic должен творить чудеса:

import React from "react"
import { graphql, Link } from "gatsby"
import SEO from "../components/SEO"
import Layout from '../layouts/Layout'
import SubpageHeader from '../components/SubpageHeader'
import SubpageItem from '../components/SubpageItem'
import styled from "styled-components"
import { gsap } from "gsap";
import ScrollMagic from 'scrollmagic';

export const query = graphql`
{
    prismic {
        allAbouts {
            edges {
                node {
                short_footer_text
                }
            }
        }
        allProjectssubpages {
            edges {
                node {
                    intro_text_to_projects
                    ordered_projects {
                        link_to_project {
                            ... on PRISMIC_Project {
                                _meta{
                                    uid
                                }
                                project_title
                                project_description
                                photos {
                                    photo
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
`

const MainContainer = styled.div`
    margin: 6rem 15vw 0;
    display: flex;
`

const ItemsContrainer = styled.div`
    width: 45vw;
`

const LinksContainer = styled.div`
    width: 25vw;
`

const LinksInnerContainer = styled.div`
    display: flex;
    flex-direction: column;
`
const LinkTag = styled(Link)`
    text-decoration: none;
    font-size: 16px;
    color: #000;
    margin-bottom: 15px;
    letter-spacing: 2px;
    opacity: 0.5;
`

class projects extends React.Component {
    constructor(props) {
        super(props);
    }

    componentDidMount = () => {
        const projectssubpageData = this.props.data.prismic.allProjectssubpages.edges.slice(0, 1).pop()
        const orderedProjects = projectssubpageData.node.ordered_projects;

        if (typeof window !== 'undefined') {
            let controller = new ScrollMagic.Controller();
            const itemsContainerHeight = document.querySelector('#items-container').clientHeight;
            const linksContainerHeight = document.querySelector('#links-inner-container').clientHeight;
            const height = itemsContainerHeight - linksContainerHeight;

            let scene = new ScrollMagic.Scene({ triggerElement: "#main-container", triggerHook: 0.25, duration: height })
                .setPin("#links-container")
                .addTo(controller);

            orderedProjects.forEach(project => {
                let uidOfProject = project.link_to_project._meta.uid;
                let projectDivHeight = document.querySelector(`.${uidOfProject}`).clientHeight;

                let scene = new ScrollMagic.Scene({ triggerElement: `.${uidOfProject}`, triggerHook: 0.4, duration: projectDivHeight })
                    .setClassToggle(`#${uidOfProject}`, "active")
                    .addTo(controller);
            });
        }
    }

    render() {
        const footerData = this.props.data.prismic.allAbouts.edges.slice(0, 1).pop()
        const projectssubpageData = this.props.data.prismic.allProjectssubpages.edges.slice(0, 1).pop()
        if (!projectssubpageData || !footerData) return null

        return (
            <>
                <SEO title="Projects" />
                <Layout
                    footerShortText={footerData.node.short_footer_text[0].text}
                    footerLinksArray={[
                        {
                            name: 'All Events',
                            URL: '/events'
                        },
                        {
                            name: 'Diary',
                            URL: '/diary'
                        },
                        {
                            name: 'Home',
                            URL: '/'
                        }
                    ]}>
                    {/* Subpage header */}
                    <SubpageHeader headline={"PROJECTS"} introText={projectssubpageData.node.intro_text_to_projects[0].text}></SubpageHeader>

                    <MainContainer id="main-container">
                        {/* Links to the projects */}
                        <LinksContainer id="links-container">
                            <LinksInnerContainer id="links-inner-container">
                                {projectssubpageData.node.ordered_projects.map(project => (
                                    <LinkTag
                                        to={"projects/" + project.link_to_project._meta.uid}
                                        key={project.link_to_project._meta.uid}
                                        id={project.link_to_project._meta.uid}>
                                        {project.link_to_project.project_title[0].text}
                                    </LinkTag>
                                ))}
                            </LinksInnerContainer>
                        </LinksContainer>

                        {/* All projects */}
                        <ItemsContrainer id="items-container">
                            {projectssubpageData.node.ordered_projects.map(project => (
                                <SubpageItem
                                    itemURL={"projects/" + project.link_to_project._meta.uid}
                                    photoURL={project.link_to_project.photos[0].photo.url}
                                    photoAlt={project.link_to_project.photos[0].photo.alt}
                                    title={project.link_to_project.project_title[0].text}
                                    description={project.link_to_project.project_description[0].text}
                                    divClass={project.link_to_project._meta.uid}
                                    key={project.link_to_project._meta.uid}>
                                </SubpageItem>
                            ))}
                        </ItemsContrainer>
                    </MainContainer>
                </Layout>
            </>
        )
    }
}

export default projects

person Michal Moravik    schedule 13.03.2020    source источник
comment
Зачем использовать ScrollMagic? Вы можете создать тот же эффект и без него.   -  person Zach Saucier    schedule 13.03.2020
comment
Привет, @ZachSaucier, наверное, потому что он был создан для этого. Думаю, в следующий раз я не буду так сильно полагаться на модули. Если у вас есть какие-либо хорошие ссылки, как сделать некоторые магические эффекты прокрутки без него, я был бы благодарен за это. Я использую pin и setClassToggle конкретно.   -  person Michal Moravik    schedule 13.03.2020
comment
Вот способ привязать прогресс анимации к положению прокрутки   -  person Zach Saucier    schedule 13.03.2020
comment
Спасибо @ZachSaucier. К сожалению, после целого дня мне не удалось воспроизвести свою анимацию ScrollMagic. Мне определенно нужно дополнительное обучение с GSAP. Я нашел одно обходное решение и разместил его ниже.   -  person Michal Moravik    schedule 14.03.2020


Ответы (1)


Я сделал один обходной путь, который, кажется, работает, поэтому я публикую его здесь. Вместо реализации scrollmagic в начале документа я реализую его позже, после вызова componentDidMount и после того, как я могу быть на 100% уверен, что объект окна существует.

Ну вот:

componentDidMount = () => {
        if (typeof window !== 'undefined') {
            import('scrollmagic').then((ScrollMagic) => {
                 // your scrollmagic code here
                 let controller = new ScrollMagic.Controller();
                 // ....
            });
        }
    }

Таким образом, ошибка исчезнет, ​​и, следовательно, шаг 2 (шаг 2 из вопроса) не нужен.

person Michal Moravik    schedule 13.03.2020