Jump to content
GreenSock

bayti

Need help with triggering canvas animation by scroll of other div

Go to solution Solved by bayti,

Recommended Posts

This is probably really obvious, but i can't make it work.

Basically I adapted the code from the given codepen to my react project but I can't get it to work in the way I want.

What I'm trying to do is make use of image sequence animation triggered by scrolling while also snapping to full screen sections.

I've managed making these work individually but when I tried combining them is when I ran into trouble.

The conclusion I came to is: the way I have it setup now, for the scroll snapping to work is body overflow:hidden and everything is taking place in a container div configured for snapping which is scrolling. Now the canvas animation is not triggering because it is expecting for the window to scroll which is not actually happening it is the div that is. I think the solution should be me directing and giving the right scroller  to ScrollTrigger but I can't get it to work. I'm going to share the code below and I thank anyone in advance for any help provided.

 

index.css

Quote
body{
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
    'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
    sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow: hidden;/* Delete for canvas*/
}
 
#home-container {
  background: rgb(10, 10, 10);
  margin: 0;
  overflow-y: scroll; /* Delete for canvas*/
  height: 100vh; /* Delete for canvas*/
  scroll-snap-type: y mandatory; /* Delete for canvas*/
}
 
#home-section{
  height: 100vh;
  scroll-snap-align: center; /* Delete for canvas*/
  position: relative;
}
 
#hero-lightpass {
  position: fixed;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  max-width: 100vw;
  max-height: 100vh;
}

 

Home.js

Quote
import React,{ useEffect } from "react";
import "../index.css";
import { gsap } from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";
 
gsap.registerPlugin(ScrollTrigger);
 
function Home(){
 
  useEffect(() => {
 
    const canvas = document.getElementById("hero-lightpass");
    const context = canvas.getContext("2d");
 
    canvas.width = 1158;
    canvas.height = 770;
 
    const frameCount = 147;
    const currentFrame = index => (
      `https://www.apple.com/105/media/us/airpods-pro/2019/1299e2f5_9206_4470_b28e_08307a42f19b/anim/sequence/large/01-hero-lightpass/${(index + 1).toString().padStart(4, '0')}.jpg`
    );
 
    const images = []
    const airpods = {
      frame: 0
    };
 
    for (let i = 0; i < frameCount; i++) {
      const img = new Image();
      img.src = currentFrame(i);
      images.push(img);
    }
 
    gsap.to(airpods, {
      frame: frameCount - 1,
      snap: "frame",
      ease: "none",
      scrollTrigger: {
        scrub: 0.5
      },
      onUpdate: render
    });
 
    images[0].onload = render;
 
    function render() {
      context.clearRect(0, 0, canvas.width, canvas.height);
      context.drawImage(images[airpods.frame], 0, 0);
    }
 
  }, []);
 
  return(
     
      <div id="home-container" className="scroll-smooth left-0 right-0 z-1 w-full">
        <canvas id="hero-lightpass">Your browser does not support the canvas tag.</canvas>
        <div id="home-section" className="snap-center w-full p-0 m-0 bg-teal-900/30">
          <h1>1</h1>
        </div>
        <div id="home-section" className="snap-center w-full p-0 m-0 bg-red-900/30">
          <h1>2</h1>
        </div>
        <div id="home-section" className="snap-center w-full p-0 m-0 bg-teal-900/30">
          <h1>3</h1>
        </div>
        <div id="home-section" className="snap-center w-full p-0 m-0 bg-red-900/30">
          <h1>4</h1>
        </div>
        <div id="home-section" className="snap-center w-full p-0 m-0 bg-teal-900/30">
          <h1>5</h1>
        </div>
      </div>
 
    );
}
 
export default Home;

 

 

Solutions I tried are a combination of the code below:

Quote
const scroller = document.getElementById("home-container");
 
ScrollTrigger.defaults({
      scroller: scroller,
    });
 
    gsap.to(airpods, {
      frame: frameCount - 1,
      snap: "frame",
      ease: "none",
      ScrollTrigger:{
        trigger: scroller,
        scrub: true,
        scrub: 0.5
      },
      onUpdate: render
    });
 
    ScrollTrigger.scrollerProxy(scroller, {
      scrub: 0.5
    })

 

I should mention that using this code above made the animation play trough once upon refreshing the site but it would not respond to the scroller.

 

I'm sorry if the post is breaking any forum rules and if I didn't explain the problem quite as well as I could've.

See the Pen 2152a28cffe2c2c0cca8a3e47f7b21c6 by osublake (@osublake) on CodePen

Link to comment
Share on other sites

Hey there,

Welcome to the forums! We try to keep the questions in here focused on GSAP specific issues rather than assistance with framework hurdles - but maybe our guide will help? If not maybe someone else will jump in
 

 

  • Like 1
Link to comment
Share on other sites

  • Solution

I've managed to find the solution which was really simple, I'm going to post it here for anyone in the future trying the same thing and close the post.

All that was need was to add 

scroller: "#home-container",

under the scrollTrigger like so

gsap.to(airpods, {
      frame: frameCount - 1,
      snap: "frame",
      ease: "none",
      scrollTrigger: {
        scroller: "#home-container",
        scrub: 0.5
      },
      onUpdate: render
    });
Link to comment
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×