Share Posted May 4, 2021 When my page loads, the animation for "textRef2" and "animeRef3" (text and picture at the bottom of the page) start immediately, instead of on the specified start point. On my PC browser, I'm noticing that when I refresh the page, I see the "start" marker appear above "scroller-start" marker for 1 second before going to it's proper place below it. I believe this glitch is causing my animation to start immediately on page load, rather than on the scroll start. I have no idea why this is happening. Here is a sandbox of my project. Please click on "open in new window" to fully see the issue. On this sandbox, however, the "start" button doesn't flicker, but appears above the "scroller-start" marker by default. https://codesandbox.io/s/silly-payne-w69cg?file=/src/App.js Why doesn't the "start" marker simply load where it's supposed to be consistently every time? Code snippet useEffect(() => { gsap.from( textRef.current, { opacity:0, x: -80, duration: 3 }, ), gsap.from( animeRef1.current, { duration: 1.2, opacity: 0, y: -30 } ), gsap.from( animeRef2.current, { duration: 1.5, opacity: 0, y: -20 } ), gsap.from( textRef2.current, { opacity:0, x: -80, duration: 3, scrollTrigger: { trigger: textRef2.current, start: "top center" } }), gsap.from( animeRef3.current, { duration: 1.5, opacity: 0, y: -20, scrollTrigger: { trigger: animeRef3.current, start: "top center", markers: true } } ); }, []); Full code for context import React, { useState, useEffect, useRef } from 'react'; import './../App.css'; import {Grid, Typography, Paper, useMediaQuery, useTheme, Container, CardMedia, Button} from '@material-ui/core'; import {makeStyles} from '@material-ui/core/styles'; import gsap from 'gsap'; import { ScrollTrigger } from 'gsap/ScrollTrigger'; gsap.registerPlugin(ScrollTrigger); const useStyles = makeStyles((theme) => ({ holderText: { left: '200px', textAlign: 'left', paddingTop: '50px' }, holderImg: { flexGrow: '1', marginLeft: '20px' }, containerStyle:{ marginTop: '30px' }, containerStyleSecond:{ marginTop: '100px', marginBottom: '100px' }, buttonFont: { fontSize: 12 } })) function Homepage() { const classes = useStyles(); const textRef = useRef() const textRef2 = useRef() const animeRef1 = useRef() const animeRef2 = useRef() const animeRef3 = useRef() useEffect(() => { gsap.from( textRef.current, { opacity:0, x: -80, duration: 3 }, ), gsap.from( animeRef1.current, { duration: 1.2, opacity: 0, y: -30 } ), gsap.from( animeRef2.current, { duration: 1.5, opacity: 0, y: -20 } ), gsap.from( textRef2.current, { opacity:0, x: -80, duration: 3, scrollTrigger: { trigger: textRef2.current, start: "top center" } }), gsap.from( animeRef3.current, { duration: 1.5, opacity: 0, y: -20, scrollTrigger: { trigger: animeRef3.current, start: "top center", markers: true } } ); }, []); return ( <div> <section> <Container maxWidth={false} className={classes.containerStyle}> <Grid item xs={12} container > <Grid item xs={1} /> <Grid item xs={3} > <div className={"classes.holderText"}> <Typography ref={textRef}> <h1> Lorem ipsum dolor sit amet. </h1> <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. </p> <Button to={'/shop'} className={classes.buttonFont}> Enter </Button> </Typography> </div> </Grid> <Grid item xs={4} > <div className={classes.holderImg} > <div className="first"> <div className="firstP"> <Paper ref={animeRef1}> <CardMedia component="img" image={require(`../images/LA_night_car.jpg`)} /> </Paper> </div> </div> </div> </Grid> <Grid item xs={2}> <Paper className={classes.holderImg} ref={animeRef2}> <CardMedia component="img" image={require(`../images/skater.jpg`)} /> </Paper> </Grid> <Grid item xs={4} /> </Grid> </Container> </section> <section > <Container maxWidth={false} className={classes.containerStyleSecond} > <Grid item xs={12} container > <Grid item xs={1} /> <Grid item xs={4}> <div className={classes.holderText}> <Typography ref={textRef2}> <h1 > Lorem ipsum dolor. </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> </Typography> </div> </Grid> <Grid item xs={4} > <div className={classes.holderImg}> <Paper ref={animeRef3}> <CardMedia component="img" image={require(`../images/diner_portrait.jpg`)} /> </Paper> </div> </Grid> <Grid item xs={3} /> </Grid> </Container> </section> </div> ); } export default Homepage; Link to comment Share on other sites More sharing options...
Share Posted May 4, 2021 If I understand your question correctly, try setting immediateRender: false on your tweens. gsap.from() tweens render immediately by default, and you've got "y" values set, thus their position is being affected. Link to comment Share on other sites More sharing options...
Author Share Posted May 4, 2021 11 hours ago, GreenSock said: If I understand your question correctly, try setting immediateRender: false on your tweens. gsap.from() tweens render immediately by default, and you've got "y" values set, thus their position is being affected. I tried adding "immediateRender: false" but the issue persists. Below is a video of what I'm seeing. Notice on the far right that the "start" marker seems to momentarily flash ahead of the "scroller-start" which I believe is causing the animation to start immediately on page load, rather than on scrollTrigger. Does this help provide more context? Do you know what's going on here? Link to comment Share on other sites More sharing options...
Share Posted May 5, 2021 Oh, yes, that's because you haven't defined any "height" for the elements, so your HTML loads but your images haven't loaded, so the elements are much much higher on the page when you create your ScrollTriggers...and then later your images load and push things way down on the page, but by that time the ScrollTrigger animations have already fired. You could either define the height values so that your layout doesn't shift, or you could just not create your animations/ScrollTriggers until everything has finished loading. Like: window.addEventListener("load", function() { // do stuff here. }); 2 Link to comment Share on other sites More sharing options...
Share Posted May 5, 2021 As Jack mentions the culprit here is layout shifting, something I really don't enjoy as a user, so the trick of setting heights to your elements is a good way to avoid that. Another alternative could be to use the useLayoutEffect hook and see of that helps: https://reactjs.org/docs/hooks-reference.html#uselayouteffect Happy Tweening!!! 2 Link to comment Share on other sites More sharing options...
Author Share Posted May 6, 2021 Thank you! Adding "height" totally solved my issue. I also tested using "addEventListener" which worked. I didn't get "uselayouteffect" to work, so I may need to research that more. 1 Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now