Jump to content

Search In
  • More options...
Find results that contain...
Find results in...

Search the Community

Showing results for tags 'gatsby'.

  • Search By Tags

    Type tags separated by commas.
  • Search By Author

Content Type


  • GreenSock Forums
    • GSAP
    • Banner Animation
    • Jobs & Freelance
  • Flash / ActionScript Archive
    • GSAP (Flash)
    • Loading (Flash)
    • TransformManager (Flash)

Product Groups

  • Club GreenSock
  • TransformManager
  • Supercharge


There are no results to display.

Find results in...

Find results that contain...

Date Created

  • Start


Last Updated

  • Start


Filter by number of...


  • Start



Personal Website



Company Website



Found 19 results

  1. I've been having this weird bug/ issue in combination with ScrollTrigger and routing between different pages in Gatsby. When routing to a different page while clicking on a link the animation starts before the trigger is met. So when I scroll down and expect to see blocks animate in I see blocks already in their end state. **Note: This only happens when routing to a page. If you open a page and/or refresh this doesn't happen (the normal behaviour with ScrollTrigger happens). I've made a simple example for you guys to have a look at in CodeSandbox: https://codesandbox.io/s/gatsby-gsap-scrolltrigger-issue-q19r6?file=/src/pages/index.js
  2. Hi guys! I come humbly in front of you with few drops of hope left, after 5 full days of switching between possible solutions to get a consistent ScrollTrigger behavior on a Gatsby site. Getting directly to you is my last resort, as every google and gsap forum link regarding ScrollTrigger and Gatsby is already visited. 😒 I cannot get a CodePen reproducing the exact issue so I'll try my best to describe it here. Shortly, the problem seems to be, as I suspect, that the ScrollTrigger does not refresh itself when Javascript pops into the browser on top of the SSR-ed html/css bundle. Here's what i did. I created several projects with different versions for dependencies, but i will stick to the simplest one with all dependencies up to date.It's a gatsby with material-ui plugin added, who's exact structure can be found here: https://github.com/mui-org/material-ui/tree/master/examples/gatsby There are no other plugins added, nor any other configs/plugins changed. I rendered the component that will contain the ScrollTrigger (AboutBlock) in the AboutPage page: about.js const AboutPage = () => { return ( <AboutBlock /> ) } export default AboutPage This is the component where i try to animate some elements on reveal when scrolled into view: aboutBlock.js import gsap from "gsap"; import ScrollTrigger from 'gsap/ScrollTrigger'; import animateReveal from "./gs_reveal"; export default function AboutBlock() { gsap.registerPlugin(ScrollTrigger) const revealRefs = useRef([]) revealRefs.current = [] useLayoutEffect(() => { let scrollTriggers = [] scrollTriggers = animateReveal(revealRefs.current) return () => { scrollTriggers.forEach(t => t.kill(true)) } }, []); const addToRevealRefs = el => { if (el && !revealRefs.current.includes(el)) { revealRefs.current.push(el); } }; return ( <Grid container> <Grid item width={{ xs: '100%', sm: '80%', md: '35%' }} pl={{ xs: 0, md: '2.5%' }} mt={{ xs: 60, sm: 0 }}> <Grid container direction="column" alignItems={{ xs: "flex-start", sm: "flex-end" }}> <Grid item mt={{ xs: 0, md: '10vh' }} id="acum"> <Typography variant="h5" textAlign={{ xs: "left", sm: "right" }} ref={addToRevealRefs} className='gs_reveal_fromRight'> NOW WE ARE IN </Typography> </Grid> <Grid item> <Typography variant="h6" textAlign={{ xs: "left", sm: "right" }} ref={addToRevealRefs} className='gs_reveal_fromRight'> LOCATION </Typography> </Grid> <Grid item mt="10vh" id="hi"> <Typography variant="h5" textAlign={{ xs: "left", sm: "right" }} ref={addToRevealRefs} className='gs_reveal_fromRight'> SAY HI </Typography> </Grid> <Grid item className='toughts'> <Typography variant="h6" textAlign={{ xs: "left", sm: "right" }} ref={addToRevealRefs} className='gs_reveal_fromRight'> TELL US YOUR THOUGHTS </Typography> </Grid> </Grid> </Grid> </Grid> } HTML is longer and crowded, I left a part to get the idea of the structure and styling approach (MUI's sx - emotion). And finally, this is the animateReveal function: gs_reveal.js import ScrollTrigger from 'gsap/ScrollTrigger'; import gsap from 'gsap'; export default function animateReveal(elements) { const triggers = [] elements.forEach(function (elem) { hide(elem) let tr = ScrollTrigger.create({ trigger: elem, id: elem.id, end: 'bottom top', markers: true, onEnter: function () { animateFrom(elem) }, onEnterBack: function () { animateFrom(elem, -1) }, onLeave: function () { hide(elem) } }); triggers.push(tr) }); return triggers; } function animateFrom(elem, direction) { direction = direction || 1; let x = 0, y = direction * 100; if (elem.classList.contains("gs_reveal_fromLeft")) { x = -100; y = 0; } else if (elem.classList.contains("gs_reveal_fromRight")) { x = 100; y = 0; } else if (elem.classList.contains("gs_reveal_fromBelow")) { y = -100 } elem.style.transform = "translate(" + x + "px, " + y + "px)"; elem.style.opacity = "0"; gsap.fromTo(elem, { x: x, y: y, autoAlpha: 0 }, { duration: 1.25, x: 0, y: 0, autoAlpha: 1, ease: "expo", overwrite: "auto", delay: elem.classList.contains("gs_delay") ? 0.3 : 0, }); } function hide(elem) { gsap.set(elem, { autoAlpha: 0 }); } The ScrollTrigger markers are misplaced when page loads, and might move (get more misplaced) on hard reloading page, depending on the current scroll position in the moment of reloading, even though the scroll position is not preserved on reload (always is scrolled on top). - The markers are placed on the correct position on resizing, as expected. I followed gsap official docs on react and react-advanced and tried: grabbing the html elements to animate on scroll inside animateReveal() by let elements = gsap.utils.toArray(".gs_reveal"); Assigning to each element a useRef() and use the .current value for each in animateReveal() grabbing html elements using gsap's selector utility gsap.utils.selector changing to simpler animation on scroll, like just a fade refreshing ScrollTrigger in different moments useLayoutEffect(() => { ScrollTrigger.refresh(true) // or ScrollTrigger.refresh() ... }, []); 6. Lifting ScrollTrigger logic to parent about.js page 7. Assigning scrollTrigger to a timeline triggered by the to-be-reveal element 8. Use useEffect() instead of useLayoutEffect() (recommended anyway for ScrollTrigger) 7. Other who-knows-what unsuccessful twists. I suspected a rehydration error, when the static generated code does not match the client side one. But the only JS that could cause a mismatch is the gsap related one, and it does not seem an SSR issue. I checked if the CSS and HTML elements are being properly SSR-ed, by preventing JS from running in the browser. All looking fine. This is both a SSR issue (gatsby build) and a development issue (no SSR). As i said on point 5, setting a ScrollTrigger.refresh() when component is mounted does not work, but delaying this with a 1-2 seconds in a setTimeout successfully solves the issue useLayoutEffect(() => { setTimeout(() => { ScrollTrigger.refresh(true) }, 2000); }, []); This is hard to be accepted as a solution, since i cannot rely on a fixed value to 'guess' when DOM is properly rendered in the eyes of the ScrollTrigger, not to mention the glitches that might occur. So, the question is 'WHY?', why animating with ScrollTrigger from within useLayoutEffect, which is not triggered on the server anyway and should mark the 'component is successfully mounted' moment, seems to not wait for the DOM being completely painted, even though nothing is generated dynamically! There are quite of threads on this forum regarding gatsby, and none seemed to have a clear cause-outcome-solution. Is this battle lost, should i move on? Do you have any suggestions? Thanks so much for your time reading this, it means so much to me!
  3. Hi there, I'm new to Gsap and looking for a way to animate a slider that I've created using react. Now, my Slider.js component is sourcing data from contentful via Graphql so I've took a different approach to build the slider as you can see below. Slider.js import React from "react" import { graphql, useStaticQuery } from "gatsby" const query = graphql` { allContentfulExperience(filter: {node_locale: {eq: "en-US"}} ) { nodes { id slug title excerpt { excerpt } image { fluid { ...GatsbyContentfulFluid_withWebp } } } } } ` const Slider = () => { const data = useStaticQuery(query) const { allContentfulExperience: { nodes: products }, } = data const [index, setIndex] = React.useState(0); React.useEffect(() => { const lastIndex = products.length - 1; if (index < 0) { setIndex(lastIndex) } if (index > lastIndex) { setIndex(0) } }, [index, products]) return <Wrapper> <div className="section-center"> {products.map((product, productIndex) => { let position = "nextSlide" if (productIndex === index) { position = "activeSlide" } if (productIndex === index - 1 || (index === 0 && productIndex === product.length - 1)) { position = "lastSlide" } return ( <article className={position} key={productIndex}> <Image fluid={product.image.fluid} alt={product.title} className="img"></Image> <div className="info"> <h3>{product.title}</h3> <p>{product.excerpt.excerpt}</p> <StyledLinks message="View more »" linkes={product.slug} /> </div> </article> ) })} <FormPrevious className="prev" onClick={() => setIndex(index - 1)} color="white" size="large" /> <FormNext className="next" onClick={() => setIndex(index + 1)} color="white" size="large" /> </div> </Wrapper> } export default Slider I was wondering now, if I can use Gsap to animate my slider. For example, If I click the ''next button'' I want the content to animate in (I hope you get my idea.. ). Is something like that possible with the Slider that I've built? What would be the Gsap plugins that I need? I know react pretty well but not really Gsap.. Thanks in advance!
  4. I am using Gatsby JS and initializing smooth-scrollbar within a layout component and I've also configured the scroller proxy. Within a child component, I'm trying to setup an animation using scroll trigger but I'm not sure how to configure this. Also, the config does work after HMR fires but not after page refresh. I removed most of the markup from the page as I know the animation works - I think the issue is with syncing the scrollers. layout.js: import React, { useRef, useEffect } from "react" import Navbar from "./navbar" import { gsap } from "gsap"; import { ScrollTrigger } from "gsap/ScrollTrigger"; import Scrollbar from 'smooth-scrollbar' // import "../styles/locomotive-scroll.css" const Layout = ({ children, location }) => { const scrollerRef = useRef() useEffect(() => { gsap.registerPlugin(ScrollTrigger) const scroller = scrollerRef.current const bodyScrollBar = Scrollbar.init(scrollerRef.current, { damping: 0.1, delegateTo: document, alwaysShowTracks: true }) window.bodyScrollBar = bodyScrollBar ScrollTrigger.scrollerProxy(scrollerRef.current, { scrollTop(value) { if (arguments.length) { bodyScrollBar.scrollTop = value } return bodyScrollBar.scrollTop } }) window.scroller = scrollerRef.current bodyScrollBar.addListener(ScrollTrigger.update) ScrollTrigger.defaults({ scroller: scroller }) // ScrollTrigger.refresh() return () => { if (bodyScrollBar) bodyScrollBar.destroy() bodyScrollBar.removeListener(ScrollTrigger.update) } }, [location]) return ( <div className="global-wrapper scroller h-screen overflow-hidden" ref={scrollerRef}> <header className="global-header animate__animated animate__fadeIn"> <Navbar /> </header> <main>{children}</main> <footer> {/* © {new Date().getFullYear()}, Built with */} {` `} {/* <a href="https://www.gatsbyjs.com">Gatsby</a> */} </footer> </div> ) } export default Layout index.js: import React, { useEffect, useRef } from "react" import { gsap } from "gsap"; import { ScrollTrigger } from "gsap/ScrollTrigger"; function Index() { const outroRef = useRef() const outroContentRef = useRef() useEffect(() => { gsap.registerPlugin(ScrollTrigger) gsap.fromTo(outroContentRef.current, { yPercent: "-50" }, { yPercent: "0", scrollTrigger: { scroller: window.scroller, trigger: outroRef.current, end: "bottom bottom", scrub: true, markers: true }, ease: "none" }) }, []); return ( <> {/* Page content */} </> ) } export default Index
  5. My goal is update a Three JS scene (colors, camera position, material properties, etc.) based on state properties set by the timeline. My scene is rendered inside of the BlobScene component which accepts an intensity prop. In the sample below, I'd like to update the intensity as the timeline is scrubbed which then updates the light intensity of my scene. In the pinned section, there are two columns: the left column contains text that will be translated into view and the right column contains the BlobScene. My ultimate goal is to change the color of the blob for each corresponding text section. So when the user scrolls from the red section to the green section, for example, the blob mesh would smoothly transition it's material color from red to green. Am I going about this the wrong way? I can create a minimal demo if needed. import React, { useState, useEffect } from "react" import { gsap } from "gsap"; import { ScrollTrigger } from "gsap/ScrollTrigger"; import BlobScene from '../components/blob-scene' function Index() { let [intensity, setIntensity] = useState({value: 1.5}) useEffect(() => { gsap.registerPlugin(ScrollTrigger) // Verticals Pinned Section Story const tl = gsap.timeline() tl.from(".red", {y: "100%"}) .from(".green", {y: "100%"}) .from(".blue", {y: "100%"}); // PROBLEM LINE tl.to(intensity, { value: setIntensity(0.5) }) ScrollTrigger.create({ animation: tl, trigger: "#verticals", scroller: "#___gatsby", start: "top top", end: "+=4000", scrub: true, pin: true, anticipatePin: 1 }); // each time the window updates, we should refresh ScrollTrigger and then update LocomotiveScroll. ScrollTrigger.addEventListener('refresh', () => window.scroll.update()) ScrollTrigger.refresh() }, [intensity]); return ( <React.Fragment> <div className="page"> <section id="verticals" className="h-screen flex items-center relative w-full overflow-hidden"> <div className="grid grid-cols-2 gap-6 h-full w-full"> {/* Grid Column 1 */} <div className="flex items-center"> <div className="relative w-full overflow-hidden h-80"> <div className="panel absolute h-full w-full red bg-red-500 text-black"> <h2>Panel 1</h2> </div> <div className="panel absolute h-full w-full green bg-green-500"> <h2>Panel 2</h2> </div> <div className="panel absolute h-full w-full blue bg-blue-500"> <h2>Panel 3</h2> </div> </div> </div> {/* Grid Column 2 */} <div className="flex items-center"> <BlobScene intensity={intensity.value}></BlobScene> </div> </div> </section> </div> </React.Fragment> ) } export default Index
  6. We have a react application that makes heavy use of GSAP & Scrolltrigger which is showing some inconsistent behavior and we need to fix it within a short timeframe. Payment is project-based with clear set of tasks -- the priority is for the Scrolltrigger issues, although it would be great to get assistance more generally. We have no idea how long this will take, we do have a project budget, so please give us a flat bid for just fixing the Scrolltrigger/React issue or for general help. We can also share the code with you, nothing fancy, if that is helpful before you determine your bid. Thanks! A very similar site: https://astraeafoundation.org/microsites/ar2019/ Our site in progress: http://tappingbones.works/icfj/Background:Our application consists of react components to apply various animation effects to content, trigger animations, etc, each component containing it's own triggering logic, and used multiple times throughout the project. Unfortunately their triggers don't appear where they should. We've refined this substantially, but have a few last details to fix for responsiveness, on window resize, and perhaps other needs to reset the animations. Could be a memory allocation issue? How the triggers are instantiated in react appears to be the solution with resetting or killing the instances of the trigger at the right points in the react lifecycle. We have a Tuesday demo of this (48 hours from now) and then need to deliver a week later. This site will have a wide audience, so it would be good for someone with solid experience shipping these sorts of animated websites to give it a once over to tighten the timing, optimize performance etc. Beyond this project, we will have similar needs in the future and will be looking for a goto developer for these kinds of frontend consulting projects as well as specific functionalities, plugins etc.Technology used in this project:ReactGsap 3ScrolltriggerGatsbyEmotionbodymovinreact-lottiegatsby image
  7. I'm having some really frustrating issues with getting the production build version of a scrollTrigger component to work correctly. I'm hoping that I'm just misunderstanding something fundamental but reading through the comments here none of the fixes have worked. It works as expected in the dev build, but when pushing to netlify for the staging build it jumps at the start of the pin, and then there is a bunch of empty margin space at the bottom and it overshoots. Here is the basic code. It's a simple side nav bar that is supposed to simply pin and scrub to the bottom. I would love to just use position:sticky for this but we have overflow issues that are making it not work and can't be changed. useEffect(() => { const oneVW = 16.8 const oneVWM = 4.14 const topBound = `top ${(oneVW * 9.5).toFixed(1)}px` const bottomBound = `bottom -${(oneVW * 15).toFixed(1)}px` const bottomBoundM = `bottom -${(oneVWM * 300).toFixed(1)}px` gsap.registerPlugin(ScrollTrigger) const tl = gsap.timeline({ scrollTrigger: { trigger: wrapperRef.current, pin: policyNavRef.current, start: topBound, endTrigger: navRef.current, end: bottomBound, scrub: 1, }, }) tl.play() }, []) I've also registered the plugin outside of the component, and in the gatsby-browser.js file just to be safe. It's definitely using it, but it just isn't correct. import gsap from 'gsap' import { ScrollToPlugin } from 'gsap/ScrollToPlugin' import { ScrollTrigger } from 'gsap/ScrollTrigger' These are the three styled-components in question: I've attempted it with and without height added. const Wrapper = styled.div` position: relative; background: ${Colors.lightSage}; padding: 0 5.7vw 14.3vw; height: 911.6vw; ${media.tablet} { padding-top: 45vw; height: 5924.7vw; } ` const PolicyNavWrapper = styled.div` display: flex; flex-direction: column; width: 13.6vw; height: 26.5vw; position: absolute; ${media.tablet} { background: ${Colors.lightSage}; width: 100vw; height: 43.7vw; top: 0; z-index: 2; left: 5.7vw; } ` const PolicyPapersWrapper = styled.div` position: relative; width: 62.9vw; margin-left: 24.4vw; /* height: 100vh; */ background-color: ${Colors.white}; ${media.tablet} { position: relative; width: 87.9vw; margin-left: 0; } ` I also think the bounds are kind of strange and not exactly working as they should. Any suggestions or ideas would be appreciated.
  8. Hello, I have made replica of my code to show the issue that I am having. https://codesandbox.io/s/strange-firefly-5mtce?file=/src/App.js Do not mind the mask not being in the center for that is not the problem.. When resizing the window from desktop TO mobile, the `<a>TESTING</a>` does not appear. when i inspect it with the dev tools it shows `opacity: 0;` I am trying to disable all scrollTriggers and timelines when mobile. Any help would be gladly appreciated. THANKS
  9. Hi, i am just getting to know gsap and i have a little problem :/. I am writting a page in gatsby and made a mobile side menu with gsap but i noticed that when the menu is opened for the first time and closed, after resizing the window, the menu doesn't change its position on the x-axis and starts sticking out. const Header = () => { const [isOpen, setIsOpen] = useState(false) const menuRef = useRef(null) const menuBtn = useRef(null) const tl = useRef() const toggleOpen = () => { setIsOpen(!isOpen) } useEffect(() => { const nav = menuRef.current const mainMenuLists = [...nav.querySelectorAll("ul:nth-of-type(1) li")] const socialLists = [...nav.querySelectorAll("ul:nth-of-type(2) li")] const btn = menuBtn.current const upLine = btn.querySelector("span:nth-of-type(1)") const centerLine = btn.querySelector("span:nth-of-type(2)") const downLine = btn.querySelector("span:nth-of-type(3)") tl.current = gsap .timeline() .to([upLine, downLine], { y: "-50%", duration: 0.3 }) .to(upLine, { duration: 0.1, rotation: 45 }, 0.2) .to(downLine, { duration: 0.1, rotation: -45 }, 0.2) .to(centerLine, { duration: 0.1, autoAlpha: 0 }, 0.2) .to(nav, { x: "0", duration: 0.5, autoAlpha: 1 }) .staggerFromTo( mainMenuLists, 1, { x: "-=15px", autoAlpha: 0 }, { x: "0", autoAlpha: 1 }, 0.2 ) .staggerFromTo( socialLists, 0.5, { y: "+=3px", autoAlpha: 0 }, { y: "0", autoAlpha: 1 }, 0.1 ) .reverse() }, []) useEffect(() => { tl.current.reversed(!isOpen) }, [isOpen]) return ( <HeaderComponent> <Logo> <AniLink path="/" hex="#333"> <LogoImg /> </AniLink> </Logo> <OpenMenuBtn ref={menuBtn} onClick={toggleOpen}> <span /> <span /> <span /> </OpenMenuBtn> <Nav menuRef={menuRef} setIsOpen={setIsOpen} /> </HeaderComponent> ) } const Nav = styled.nav` position: fixed; top: 0; left: 0; bottom: 0; right: 0; transform: translateX(100%); background-color: #ccc; z-index: 99; ` const Navigation = ({ setIsOpen, menuRef}) => { return ( <Nav ref={menuRef} onClick={() => setIsOpen(false)}> ... </Nav> ) } I think i know what the problem is. Timeline is created when the component is mounted and the first time the menu is opened it pops up getting translate (0). When I close the menu, the animation returns back and gsap assigns to the translate (x), value from the start of the animation. because the animation is set to reverse (I know it's obvious) . I wonder if there is any possibility to change the value of position x only when the animation returns?(Because I can't/ i don't know how do this animation differently: D) https://ibb.co/f8Y0Tg5 short demo
  10. Recently, I created gatsby project and I wanted to implement show animation to a card component. The problem comes when my 'react-intersection-observer' detects when a card appears on a screen. Then gsap gives me warning with content: 'Invalid property autoAlpha set to 0 Missing plugin? gsap.registerPlugin()' instead of animating my card component. I've already read many topics about this issue. I've tried to use 'gsap.registerPlugin()' function or to put 'CSSPlugin' to 'const plugins' but they don't solve the issue. I see the same issue when I use properties like: 'opacity' instead of 'autoAlpha'. I hope you'll point what is an issue here! There is code of my card component: export default function Card({ number, title, text, fixed, ...props }) { const [ref, inView] = useInView({ threshold: 0.2, triggerOnce: true }) function show() { gsap.registerPlugin(CSSPlugin) const tl = gsap.timeline() tl.set(ref, { autoAlpha: 0 }).to(ref, { duration: 1, autoAlpha: 1 }) } useEffect(() => { if (!inView) return show() }, [inView]) return ( <StyledCard ref={ref} {...props}> <ImageWithMask as={Img} fixed={fixed} brightValue={0.5} /> <StyledContent> <StyledSmall>{number}</StyledSmall> <Heading style={{ textAlign: "right" }}>{title}</Heading> <Paragraph className="paragraph" color={paragraphColor.grey}> {text} </Paragraph> </StyledContent> </StyledCard> ) }
  11. Hi. I'm quite new to GSAP and Gatsby (first time using gatsby and second time with GSAP), GSAP is quite buggy with me. Sometimes animations trigger, sometimes not. I followed the NPM usage guide you put on this site, except this step, which might or might not be the problem but I want to exhaust all options before I ask for further help: I'm sorry if this is not GSAP specific. I just want to understand the above code segment so I can know how to translate it properly in Gatsby's config. Transpilers, Bundlers, Webpack, Babel still confuse the heck out of me since I'm a newbie developer still. 😅 Gatsby's and Webpack's docs don't show an option like this so I'm not sure how to approach this. Can someone tell me how to do that in Gatsby? Thank you for this amazing library it's been a joy to use (outside Gatsby at least!).
  12. I'm trying to build and deploy my project in Gatsby but can't figure out how to solve this problem. Error seems to be made by ScrollTrigger. I tried to fire animation in if (window) statement as well as if (document) but it also generates error. Does anyone know what should I fix?
  13. Hi, I am trying to get my website to work smoothly with Scroll Trigger. But the address bar is continuously hiding and showing when I am scrolling through the page which destroys the user experience. I tried searching for solutions but to no avail - might be my lack of knowledge of css. Here is my website (try it on mobile to understand what I mean): https://tbdalen.github.io/ And here is my repo: https://github.com/tbdalen/tbdalen.github.io Here is my inspiration for this site and they managed to prevent hiding the address bar. They have used hammerjs here though: https://dpotferstudio.com/
  14. Hi, I am trying to get the Scroll Trigger to work on my gatsby website. I am a beginner at both Gatsby/React and GSAP so forgive my ignorance. I created a sandbox of how I did this in Gatsby. It works on development build like here on this sandbox but not when I try to go production build. I get this error "failed Building static HTML for pages". Does anyone know what I am doing wrong? Thanks! https://codesandbox.io/s/unruffled-cannon-v5wh4?file=/src/App.js
  15. kempo

    React Gatsby

    I'm trying to get GSAP working in my React Gatsby project. I've made a simple test following @Rodrigo guide https://greensock.com/react Here is my component - no animation and no errors either import { TweenLite } from "gsap/TweenLite"; class Messages extends React.Component { constructor(props) { super(props); this.myElement = null; this.myTween = null; } componentDidMount() { this.myTween = TweenLite.to(this.myElement, 1, { x: 100, y: 100 }); } render() { return ( <div ref={div => (this.myElement = div)}> <img src={require("../images/logo.png")} width="50" /> </div> ); } } export default Messages;
  16. Hi everyone, I've successfully built with GSAP and Gatsby before, but not with the DrawSVGPlugin. It's throwing this error: This seems to be a Gatsby build problem as it works fine with React. Any ideas? Any suggestions would be hugely appreciated. I've referenced the plugins like so: const gsapPlugins = [DrawSVG, CSSPlugin, TweenLite] Thanks, Matt
  17. I've been a long time user of GSAP and have used the SplitText plugin on many projects. I've been learning React and more specifically the Gatsby library and have run into an issue I cannot solve. I setup this SplitText in my Gatsby project and it worked fine - then all of a sudden today it broke giving me a Type Error. I've downloaded the most recent GSAP library and Gatsby/ React is up to date as well. TypeError: null is not an object (evaluating 'parent.insertBefore') (I know this code below is partial - I ripped out a lot of excess code) import React, { Component } from "react" import { TweenMax } from "gsap/TweenMax"; import SplitText from "../utils/gsap/SplitText" export default class IndexPage extends Component { componentDidMount() { const split = new SplitText( 'h1, p', { type: "lines", linesClass: "ts-line" } ) TweenMax.staggerFrom( '.ts-line', 1, { y: "125%", opacity: 0, }, 0.25, ); } render() { return ( <Layout> <h1>Heading Text</h1> <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. </p> </Layout> ) } } Here is the error I'm getting: × TypeError: null is not an object (evaluating 'parent.insertBefore') _splitRawText src/utils/gsap/SplitText.js:428 425 | container = _doc.createElement("div"), 426 | parent = element.parentNode; 427 | > 428 | parent.insertBefore(container, element); 429 | container.textContent = element.nodeValue; 430 | parent.removeChild(element); 431 | element = container; View compiled _split src/utils/gsap/SplitText.js:505 502 | element._isSplit = true; 503 | return; 504 | } > 505 | _splitRawText(element, vars, wordStart, charStart); 506 | 507 | }, 508 | p = SplitText.prototype; View compiled _split src/utils/gsap/SplitText.js:498 495 | child.style.position = "relative"; 496 | } 497 | child._isSplit = true; > 498 | _split(child, vars, wordStart, charStart); //don't split lines on child elements 499 | } 500 | } 501 | vars.absolute = absolute; View compiled split src/utils/gsap/SplitText.js:527 524 | this._originals[i] = e.innerHTML; 525 | origHeight = e.clientHeight; 526 | origWidth = e.clientWidth; > 527 | _split(e, vars, wordStart, charStart); 528 | _setPositionsAfterSplit(e, vars, this.chars, this.words, this.lines, origWidth, origHeight); 529 | } 530 | this.chars.reverse(); View compiled SplitText src/utils/gsap/SplitText.js:132 129 | this.lines = []; 130 | this._originals = []; 131 | this.vars = vars || {}; > 132 | this.split(vars); 133 | }, 134 | _swapText = function(element, oldText, newText) { 135 | var type = element.nodeType; View compiled componentDidMount src/pages/index.js:41 38 | export default class IndexPage extends Component { 39 | componentDidMount() { 40 | > 41 | const split = new SplitText( 42 | 'h1, p', 43 | { 44 | type: "lines", View compiled ▶ 18 stack frames were collapsed. (anonymous function) /Users/leecampbell/Projects/Portfolio/Development/.cache/app.js:56 53 | const preferDefault = m => (m && m.default) || m 54 | let Root = preferDefault(require(`./root`)) 55 | domReady(() => { > 56 | renderer(<Root />, rootElement, () => { 57 | postInitialRenderWork() 58 | apiRunner(`onInitialClientRender`) 59 | }) View compiled This screen is visible only in development. It will not appear if the app crashes in production. Open your browser’s developer console to further inspect this error. Does anyone have an idea why this would be happening?
  18. Hi there, First post here! I'm working on a React/Gatsby app which references this tutorial. I've solved most of the issues except for the following error: TypeError: Cannot read property 'easeOut' of undefined I've tried a bunch of variations of imports destructuring etc but Quad is never defined. My code is as follows: import React, { Component } from "react" import Layout from "../components/layout" import SEO from "../components/seo" import { TweenMax, Quad, Sine, Back } from "gsap/TweenMax" const prettyLetter = require( 'pretty-letters' ) export default class IndexPage extends Component { componentDidMount() { var options = { groupClass: 'char-group-', groupTag: 'span' } prettyLetter('a', options) const lineEq = (y2, y1, x2, x1, currentVal) => { // y = mx + b var m = (y2 - y1) / (x2 - x1), b = y1 - m * x1 return m * currentVal + b } const lerp = (a,b,n) => (1 - n) * a + n * b const distance = (x1,x2,y1,y2) => { var a = x1 - x2 var b = y1 - y2 return Math.hypot(a,b) } const getMousePos = (e) => { let posx = 0 let posy = 0 if (!e) e = window.event if (e.pageX || e.pageY) { posx = e.pageX posy = e.pageY } else if (e.clientX || e.clientY) { posx = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft posy = e.clientY + document.body.scrollTop + document.documentElement.scrollTop } return { x : posx, y : posy } } let winsize; const calcWinsize = () => winsize = {width: window.innerWidth, height: window.innerHeight} calcWinsize() window.addEventListener('resize', calcWinsize) // The feDisplacementMap element const feDisplacementMapEl = document.querySelector('feDisplacementMap') class Menu { constructor() { this.DOM = { svg: document.querySelector('svg.distort'), menu: document.querySelector('nav.menu') } // The images (one per menu link) this.DOM.imgs = Array.from(Object.assign.apply(Object, [this.DOM.svg.querySelectorAll('g > image')])) // The menu links this.DOM.menuLinks = Array.from(Object.assign.apply(Object, [this.DOM.menu.querySelectorAll('.menu__link')])) // Mouse position this.mousePos = {x: winsize.width/2, y: winsize.height/2} // Last mouse positions (one to consider for the image translation movement, another for the scale value of the feDisplacementMap element) this.lastMousePos = { translation: {x: winsize.width/2, y: winsize.height/2}, displacement: {x: 0, y: 0} } // feDisplacementMap scale value this.dmScale = 0 // Current menu link position this.current = -1 this.initEvents() requestAnimationFrame(() => this.render()) } initEvents() { // Update mouse position window.addEventListener('mousemove', ev => this.mousePos = getMousePos(ev)) this.DOM.menuLinks.forEach((item, pos) => { const letters = Array.from(Object.assign.apply(Object, [item.querySelectorAll('span')])) const mouseenterFn = () => { // Hide the previous menu image if (this.current !== -1) { TweenMax.set(this.DOM.imgs[this.current], { opacity: 0 }); } // Update current this.current = pos // Now fade in the new image if we are entering the menu or just set the new image's opacity to 1 if switching between menu items if (this.fade) { TweenMax.to(this.DOM.imgs[this.current], 0.5, { ease: Quad.easeOut, opacity: 1 }) this.fade = false } else { TweenMax.set(this.DOM.imgs[this.current], { opacity: 1 }) } // Letters effect TweenMax.staggerTo(letters, 0.2, { ease: Sine.easeInOut, y: this.lastMousePos.translation.y < this.mousePos.y ? 30 : -30, startAt: {opacity: 1, y: 0}, opacity: 0, yoyo: true, yoyoEase: Back.easeOut, repeat: 1, stagger: { grid: [1,letters.length-1], from: 'center', amount: 0.12 } }) } item.addEventListener('mouseenter', mouseenterFn) }) const mousemenuenterFn = () => this.fade = true const mousemenuleaveFn = () => TweenMax.to(this.DOM.imgs[this.current], .2, { ease: Quad.easeOut, opacity: 0 }) this.DOM.menu.addEventListener('mouseenter', mousemenuenterFn) this.DOM.menu.addEventListener('mouseleave', mousemenuleaveFn) } render() { // Translate the image on mousemove this.lastMousePos.translation.x = lerp(this.lastMousePos.translation.x, this.mousePos.x, 0.2) this.lastMousePos.translation.y = lerp(this.lastMousePos.translation.y, this.mousePos.y, 0.2) this.DOM.svg.style.transform = `translateX(${(this.lastMousePos.translation.x-winsize.width/2)}px) translateY(${this.lastMousePos.translation.y-winsize.height/2}px)` // Scale goes from 0 to 50 for mouseDistance values between 0 to 140 this.lastMousePos.displacement.x = lerp(this.lastMousePos.displacement.x, this.mousePos.x, 0.1) this.lastMousePos.displacement.y = lerp(this.lastMousePos.displacement.y, this.mousePos.y, 0.1) const mouseDistance = distance(this.lastMousePos.displacement.x, this.mousePos.x, this.lastMousePos.displacement.y, this.mousePos.y) this.dmScale = Math.min(lineEq(50, 0, 140, 0, mouseDistance), 50) feDisplacementMapEl.scale.baseVal = this.dmScale requestAnimationFrame(() => this.render()) } } new Menu() } render() { return ( <Layout> <SEO title="Home" keywords={[`Artist`, `Brisbane-based`, `drawing`, `painting`, `watercolour`, `sculpture`, `installation`, `video`, `embroidery`]} /> <div style={{ paddingBottom: 100 }}> <svg className="distort" width="350" height="450" viewBox="0 0 350 450"> <filter id="distortionFilter"> <feTurbulence type="turbulence" baseFrequency="0.07 0.01" numOctaves="5" seed="2" stitchTiles="stitch" x="0%" y="0%" width="100%" height="100%" result="noise"/> <feDisplacementMap in="SourceGraphic" in2="noise" scale="0" xChannelSelector="R" yChannelSelector="B" x="0%" y="0%" width="100%" height="100%" filterUnits="userSpaceOnUse"/> </filter> <g filter="url(#distortionFilter)"> <image className="distort__img" x="50" y="50" xlinkHref={require('../images/1.jpg')} height="350" width="250"/> <image className="distort__img" x="50" y="50" xlinkHref={require('../images/2.jpg')} height="350" width="250"/> </g> </svg> <nav className="menu"> <a href="#" className="menu__link">Shanghai</a> <a href="#" className="menu__link">Taipei</a> <a href="#" className="menu__link">Bangkok</a> <a href="#" className="menu__link">Kyoto</a> </nav> </div> </Layout> ) } }
  19. Hello The People of Greensock, I've been working with a static site generator for react lately - Gatsby.js. One of the components has a menu animation attached. In development the animation works just fine, but when deployed it just doesn't trigger. Code is bundled and minified with webpack. The weird thing is, GSAP loads up properly, the console is clear, no errors. It's hard to investigate more since code after minification and bundling is hard to read in chrome dev tools. :/ I'm not sure if this is related to my GSAP setup, but if anyone could take a look at the code, it would be awesome. This is the navAnimation itself: import { TimelineLite, CSSPlugin, Power2, Power3 } from 'gsap'; import * as CSSRulePlugin from 'gsap/CSSRulePlugin'; const slideDownTl = new TimelineLite({ paused: true, initialRender: true }); const slideUpTl = new TimelineLite({ paused: true, initialRender: true }); // Document-object-aware variables let menuBtn, menuList, shutter, shutterBf, shutterAft, menuSpans, menuSpansAfts; if (typeof window !== 'undefined' && typeof document !== 'undefined') { document.addEventListener('DOMContentLoaded', function() { // Menu Button menuBtn = document.querySelector('.menu-btn'); // Menu List menuList = document.querySelector('.list-nav'); // Shutter Variables shutter = document.querySelector('.shutter'); shutterBf = CSSRulePlugin.getRule('.shutter:before'); shutterAft = CSSRulePlugin.getRule('.shutter:after'); // Menu Span Variables menuSpans = document.querySelectorAll('.menu-span'); menuSpansAfts = CSSRulePlugin.getRule( '.list-nav ul li .menu-link a .menu-span:after' ); console.log('we passed window+document check!'); // slideDown Animation Timeline slideDownTl .set([shutterBf, shutterAft], { cssRule: { y: '-120%' } }) .set(menuBtn, { pointerEvents: `none` }) .set([menuList, shutter], { visibility: 'visible' }) .set(menuSpans, { y: '-200%' }) .timeScale(1.2) .staggerTo( [shutterBf, shutterAft], 1, { cssRule: { y: '0%' }, force3D: true, rotation: 0.01, ease: Power3.easeOut }, 0.3 ) .staggerTo( menuSpans, 0.5, { y: '0%', ease: Power2.easeInOut }, 0.1, '-=0.7' ) .set(menuBtn, { pointerEvents: `all` }); // slideUp Animation Timeline slideUpTl .set(menuBtn, { pointerEvents: `none` }) .staggerTo(menuSpans, 0.5, { y: '-200%', ease: Power2.easeIn }, 0.1) .staggerTo( [shutterAft, shutterBf], 0.75, { cssRule: { y: '-120%' }, force3D: true, rotation: 0.01, ease: Power2.easeIn }, 0.25, '-=0.4' ) .set([menuList, shutter], { visibility: 'hidden' }) .set(menuBtn, { pointerEvents: `all` }); }); // end DOMContentLoaded } // end if window !== undefined export const slideDown = () => { slideDownTl.play(0); }; export const slideUp = () => { slideUpTl.play(0); }; I check for window and document !== undefined, because Gatsby requires it on build. This is Header component which has navAnimation included: import React from 'react'; import Link from 'gatsby-link'; import './navigation.scss'; import * as navAnimation from '../../static/navAnimation.js'; class Header extends React.Component { constructor(props) { super(props); this.state = { isOpened: false }; this.menuToggle = this.menuToggle.bind(this); this.handleClickOutside = this.handleClickOutside.bind(this); } handleClickOutside(e) { let clickInHeader = false; if (e.path) { clickInHeader = e.path.find(node => node.localName === 'header'); } !clickInHeader && this.menuToggle(); } menuToggle(e) { if (this.state.isOpened) { navAnimation.slideUp(); document.removeEventListener('click', this.handleClickOutside, true); } else { navAnimation.slideDown(); document.addEventListener('click', this.handleClickOutside, true); } this.setState(prevState => { return { isOpened: !prevState.isOpened }; }); } render() { return ( <header> <h1> <div className="logo"> <Link to="/" onClick={this.state.isOpened && this.menuToggle}> <span>Seba</span> <span>Hewelt</span> </Link> </div> </h1> <div id="menu-btn-wrapper"> <button className={this.state.isOpened ? 'menu-btn open' : 'menu-btn'} onClick={this.menuToggle}> <svg className="stick" viewBox="0 0 70 32"> <path d="M 5 5 H70 L 5 21" /> <path d="M 5 15 H70 L 5 31" /> </svg> </button> </div> <div className="shutter" /> <nav className="list-nav"> <ul> <li> <div className="menu-link" onClick={this.menuToggle}> <Link to="/my-work"> <span className="menu-span">my work</span> </Link> </div> </li> <li> <div className="menu-link"> <Link to="/blog" onClick={this.menuToggle}> <span className="menu-span">blog</span> </Link> </div> </li> <li> <div className="menu-link"> <Link to="/#contact" onClick={this.menuToggle}> <span className="menu-span">contact</span> </Link> </div> </li> </ul> </nav> </header> ); } } export default Header;