Jump to content
Search Community

Gsap + React Gatsby Img animate

popland test
Moderator Tag

Recommended Posts

I have a gallery of recent work made in react/gatsby, using the gatsby-img Img component, basically every works got multiple image attached (got them from GraphQL, so i cant post a codepen), my goal is to display for every work its first image and the "randomly" fade to the second, to the third and so on

my code actually looks like:

 

<div id="worklist" className="w-100 flex flex-grow flex-wrap mt-10">
        {currPort && //currPort contains the latest work objects
          currPort.map((P, i) => {


            return (
              <div key={i} className="w-full md:w-1/2 lg:w-1/3 p-5 ">
                {P.image && ( //image is array of image objects, here using Img i only print the first image
                  <Img
                    fluid={P.image[0].childImageSharp.fluid}
                    className="test"
                    style={{ height'350px'width'100%' }}
                    imgStyle={{ objectFit'cover' }}
                  />
                )}
            );
          })}
      </div>

 

this code  for every Img reneder a wrapping div (with class test in this case) with a picture tag and inside it a img tag that have size, srcset and more

and no way to reference it from gsap, any workaraound suggestion?

 

Link to comment
Share on other sites

Welcome to the forums, @popland. This is definitely a React/Gatsby question and I'm not familiar with either. Sorry. We really try to keep these forums focused on GSAP-specific questions. @Rodrigo is pretty experienced with React, so maybe he'll have some input here, but let us know if you have any GSAP-specific questions and we'd be happy to help. 

  • Like 1
Link to comment
Share on other sites

Hi,

 

Gatsby image actually does gives you access to the <img /> in the DOM:

 

https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-image/src/index.js#L271-L327

https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-image/src/index.js#L364

 

All you have to do is pass a function to the ref={} prop in the Img component. That function gets called with an object (React instance) as the first parameter. Then as you can see in the codebase you can access the image reference as imageRef.current (reference created with React.createRef()). In that function you can add the ref of each image to an array (if you want to do something with each image of course) or add it to a specific ref of your own, it's a bit of an extra work, but at least the gatsby-image component gives you access to the DOM node.

 

Here is a super simple example of getting the image ref:
https://codesandbox.io/s/nifty-engelbart-0bd0y?file=/src/components/image.js

 

Be aware though that gatsby-image has it's own animations and transitions when the image has been loaded, so you have to be a bit careful, especially if you're planning on using .from() instances with GSAP. Be sure to apply GSAP after the image has been loaded in order to avoid any issues.

 

Finally I'm far from being an expert in Gatsby, I really prefer NextJS when it comes to a React tool for creating web apps with SSR, SEO, etc.

 

Happy Tweening!!!

  • Like 2
Link to comment
Share on other sites

Thank you for your exhaustive answer, i tried with the ref, but it seems if i have have an array of image the ref (even if created with a function) its always the same, so my animation is not working as expected (need to investigate more, maybe there is something im missing)

i used something like

 

 let picRef = useRef([]);

{content.image.map((simage, i) => {
                return (
                  <Img
                    ref={(el) => (picRef.current[i] = el)}
                    style={{
                      position: 'absolute',
                      transform: 'translate(-50%, 0)',
                      height: '100%',
                      width: '90%',
                      top: '30px',
                      left: '50%',
                      marginLeft: 'auto',
                      marginRight: 'auto',
                    }}
                    fluid={simage.childImageSharp.fluid}
                    imgStyle={{ objectFit: 'contain' }}
                    className="currimg"
                  />
                );
              })}
 

 

but when i try something like:

console.log('tes', picRef.current);
      for (let i = 0; i < picRef.current.length; i++) {
        console.log(picRef.current[i].imageRef.current);
      }

      gsap.fromTo(
        picRef.current,
        { opacity: 0 },
        {
          stagger: 2,
          duration: 1,
          opacity: 1,
          delay: 0,
          ease: 'power4.inOut',
          repeatDelay: 2,
          repeat: -1,
        }
      );

the reference to the image is logged properly to the console, but i really cant understand how to pass the reference to gsap

 

Link to comment
Share on other sites

Yeah, that is completely expected. Keep in mind that the element passed to the ref callback is a React component not a DOM element, so while GSAP is not going to complain about it (you're passing an object), it won't work. Don't use a ref callback, use a regular function passed to the component's ref:

 

const images = useRef([]);

// sometimes img can be null, so you'll get an error
const createGalleryRef = (img) => {
  if (img) {
    images.current.push(img.imageRef.current);
  }
};

return (
  <Img
    fluid={image.childImageSharp.fluid}
    ref={createGalleryRef}
  />
);

In the images array you will have a series of <img /> DOM elements ready to be used by GSAP.

 

Finally, if possible create a codesandbox live sample to see what could be the issue.

 

Happy Tweening!!!

  • Like 2
Link to comment
Share on other sites

At the moment i solved the image reference issue with the following:

 

for (let i = 0; i < picRef.current.length; i++) {
        console.log(picRef.current[i].imageRef.current);
        imgObj[i] = picRef.current[i].imageRef.current;
}

so i can pass imgObj to my timeline and animations

so now im working on having a list of object to pass (fade or swipe or zoom or any other anymation) from one to another in a seamless way, with no delay/animation on first  and animation when looping back to first, still with some "glitch", but hoping to solve it soon

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...