Jump to content
Search Community

How to rewrite it on React?

anecko test
Moderator Tag

Recommended Posts

Hi,

 

Indeed it would be a very nice example to have in React and other frameworks, but unfortunately we don't have the time resources to create custom examples for our users.

 

I'd start by checking the resources in this page:

 

And then take it one step at a time. We can offer some guidance during the process if you get stuck and have any GSAP related question, but the code shouldn't be too different from what you see there.

 

Hopefully this is enough to get you started.

Happy Tweening!

Link to comment
Share on other sites

here's what I got but it doesn't work (

@Rodrigo


import React from 'react';

import { gsap } from 'gsap';
import ScrollTrigger from 'gsap/dist/ScrollTrigger';
 
if (typeof window !== 'undefined') {
  gsap.registerPlugin(ScrollTrigger);
}
 
function getCurrentFrame(index) {
  return `assets/frames/process_0${index.toString().padStart(4, '0')}.jpg`;
}
 
export const CanvasScroll = ({ scrollHeight, numFrames, width, height, svgRef }) => {
  const canvasRef = React.useRef(null);
  const [images, setImages] = React.useState([]);
  const [frameIndex, setFrameIndex] = React.useState(0);
 
  function preloadImages() {
    for (let i = 1; i <= numFrames; i++) {
      const img = new Image(100, 100);
      const imgSrc = getCurrentFrame(i);
      img.src = imgSrc;
      setImages((prevImages) => [...prevImages, img]);
    }
  }
 
  const handleScroll = () => {
    const scrollFraction = window.scrollY / (scrollHeight - window.innerHeight);
    const index = Math.min(numFrames - 1, Math.ceil(scrollFraction * numFrames));
 
    if (index <= 0 || index > numFrames) {
      return;
    }
    setFrameIndex(index);
  };
 
  const renderCanvas = () => {
    const context = canvasRef.current.getContext('2d');
    context.canvas.width = width;
    context.canvas.height = height;
  };
 
  React.useEffect(() => {
    preloadImages();
    renderCanvas();
 
    window.addEventListener('scroll', handleScroll);
    return () => window.removeEventListener('scroll', handleScroll);
  }, []);
 
  React.useEffect(() => {
    if (!canvasRef.current || images.length < 1) {
      return;
    }
 
    const context = canvasRef.current.getContext('2d');
    let requestId;
 
    const render = () => {
      context.drawImage(images[frameIndex], 0, 0);
      requestId = requestAnimationFrame(render);
    };
 
    render();
 
    return () => cancelAnimationFrame(requestId);
  }, [frameIndex, images]);
 
  React.useEffect(() => {
    const t = gsap.to('.canvas', {
      scrollTrigger: {
        trigger: svgRef.current,
        start: 'top top',
        end: '+=' + numFrames * scrollHeight,
      },
    });
 
    return () => {
      t.kill();
      ScrollTrigger.getAll().forEach((e) => e.kill());
    };
  }, []);
 
  return (
    <div className="canvas">
      <canvas ref={canvasRef} />
    </div>
  );
};
Link to comment
Share on other sites

If you'd like some help, please provide a minimal demoPlease don't include your whole project. Just some colored <div> elements and the GSAP code is best (avoid frameworks if possible). See if you can recreate the issue with as few dependancies as possible. If not, incrementally add code bit by bit until it breaks. Usually people solve their own issues during this process! If not, then at least we have a reduced test case which greatly increases your chances of getting a relevant answer.

 

Here's a React starter template you can fork.

 

Once we see an isolated demo, we'll do our best to jump in and help with your GSAP-specific questions. 

Link to comment
Share on other sites

Hi,

 

The approach you're following is quite odd IMHO. I don't see the need for this:

React.useEffect(() => {
  preloadImages();
  renderCanvas();

  window.addEventListener('scroll', handleScroll);
  return () => window.removeEventListener('scroll', handleScroll);
}, []);

If you have ScrollTrigger in the mix, it just doesn't make sense to listen for the scroll event. If you want to do stuff based on the scroll event, then you could use the Observer Plugin (also available in ScrollTrigger as ScrollTrigger.observe())

https://greensock.com/docs/v3/Plugins/Observer

https://greensock.com/docs/v3/Plugins/ScrollTrigger/static.observe()

 

Also this looks odd as well:

React.useEffect(() => {
  if (!canvasRef.current || images.length < 1) {
    return;
  }

  const img = new Image(100, 100);
  const context = canvasRef.current.getContext('2d');
  let requestId;

  const render = () => {
    img.onload = function () {
      context.drawImage(images[frameIndex], 0, 0);
    };
    requestId = requestAnimationFrame(render);
  };

  render();

  return () => cancelAnimationFrame(requestId);
}, [frameIndex, images]);

Finally you have this for getting the images:

function getCurrentFrame(index) {
  return `assets/frames/process_0${index.toString().padStart(4, '0')}.jpg`;
}

But there is no assets folder in your example, so there are no images to work with.

 

I strongly recommend you to try to learn more about react and study Blake's codepen in order to try to emulate it as it is right now on React, before start creating and adding your own sequence of images. Unfortunately we don't have the time resources to build that for you right now, but it shouldn't be too complicated. You should forget about ScrollTrigger and just get the sequence working first, then add ScrollTrigger to the mix.

 

Happy Tweening!

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.
×
×
  • Create New...