Jump to content
GreenSock

fernandofas

Animation on images using intersection observer

Go to solution Solved by Cassie,

Recommended Posts

Hi all,

 

I'm not sure if this topic has been on here already as I didn't find anything in the terms.

 

I have a website https://disobey.design and on this website I have intersection observer targeting the images.

 

So, my code looks like this:

 

const allViews = document.querySelectorAll("[data-src]");

function preloadImage(img) {
    const src = img.getAttribute("data-src");
    if (!src) {
        return;
    }
    img.src = src;
}
const options = {
    root: null,
    threshold: 0,
    rootMargin: "0px"
};

const callback = function (entries) {
   // console.log(entries);
}

const observer = new IntersectionObserver((entries, observer) => {
    entries.forEach(entry => {
        if (!entry.isIntersecting) {
            return;
        } else {
            //console.log(entry.target);
            preloadImage(entry.target);
            observer.unobserve(entry.target);
        }
    });
}, options);

allViews.forEach(image => {
    observer.observe(image);
})

 

I would like to use this function to not just make the image appears on the screen, but appears animating like using:

.staggerFrom ("img", {y: 50, opacity: 0, duration: 0.5});

If someone could help me in this case, that will be awesome as I can't find a way to do it.

 

I already enqueue the gsap cdn scripts, so it's ready to be used.

 

The website is built using Wordpress.

 

Kind regards,

Fernando

 

 

Link to comment
Share on other sites

 

Hey there fernandofas!

 

Why not use ScrollTrigger? It would certainly make your life easier ☺️

Link to comment
Share on other sites

If I use the ScrollTrigger the images will load first or just on the animation trigger?

 

Also, how that could be implemented in a single timeline for the images on the whole site?

Link to comment
Share on other sites

If I understand your question correctly, you can do this in one line of code with ScrollTrigger: 

gsap.utils.toArray("[data-src]").forEach(el => ScrollTrigger.create({once: true, onEnter: () => el.src = el.getAttribute("data-src")}));

You don't need to use any timelines or animations. Just a simple ScrollTrigger. 

 

Another way of doing it is with batch(). Same concept: 

ScrollTrigger.batch("[data-src]", {
  onEnter: targets => targets.forEach(el => el.src = el.getAttribute("data-src")),
  once: true
});

I think you'll find ScrollTrigger much easier to work with than IntersectionObserver. And of course it has waaay more features and is more compatible :)

  • Like 2
Link to comment
Share on other sites

Still not working, not sure if I can make it to work.

Link to comment
Share on other sites

I'm not sure if a minimal demo would do it, but I manage to use Jack's code and make it to work.

gsap.registerPlugin(ScrollTrigger);

ScrollTrigger.batch("[data-src]", {
  onEnter: (targets) =>
   targets.forEach((el) => (el.src = el.getAttribute("data-src"))),
  once: true,
});

Also, I had to enqueue the ScrollTrigger.min.js.

 

At this point everything is working fine. You can check at https://disobey.design.

 

Is there a way where instead of just the images appear on the screen after entering the viewport, allow about 50px and then make the images staggerFrom y:50?

 

I know how to set up animations, but never done it this way.

 

So, I have the following at the moment:

gsap.registerPlugin(ScrollTrigger);

ScrollTrigger.batch("[data-src]", {
  interval: 0.5,
  batchMax: 4,

  onEnter: (targets) =>
    targets.forEach(
      (el) => (el.src = el.getAttribute("data-src")),

      gsap.to(targets, {
        // once: true,
        stagger: 0.5,
        duration: 0.5,
        opacity: 1,
        ease: "power4.out",
      })
    ),
});

 

 

Link to comment
Share on other sites

  • Solution

Sure - I think you'll be looking for something like this. Again - It's easier with minimal demos as we can actually check the code we're suggesting.

 

ScrollTrigger.batch("[data-src]", {
  interval: 0.5,
  batchMax: 4,
  start: 'top bottom-=50px',

  onEnter: (targets) =>
    targets.forEach(
      (el) => (el.src = el.getAttribute("data-src")),

      gsap.from(targets, {
        stagger: 0.5,
        duration: 0.5,
        opacity: 0,
        y: 50,
        ease: "power4.out",
      })
    ),
});

 

  • Like 3
Link to comment
Share on other sites

yes, that's wonderful.

 

Thank you Cassie and Jack for helping me out on this challenge. ;)

  • Like 1
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.
×