Jump to content
Search Community

GSAP Flip, re-triggering animation on same image cancels the display none, but doing it on other image doesn't?

artyor test
Moderator Tag

Go to solution Solved by Rodrigo,

Recommended Posts

Hello all,

It's sorry for title confusion, not sure how to explain.

If you click on image in the grid, it will be animated to the right, and animation includes display block of grey wrapper on the right, when you click on it again, the image will go back to orginal place and also put display none to grey wrapper on the right (i added display none with onComplete prop).

 

If you click on image 1, then click again to cancel ani and bring it back, and before it finishes you click it again to go on the right side (so basically clicking 3 times same image) animation will work.

But if you click on image 1 once, and then you click again to bring it back, and while back animation is still goin on, you click on image 2, to show it on the right, it will start animation but it will disappear because display none will be added to wrapper duo to image 1 back animation.

Why doesnt that also happen when clicking 3 times on same image?

See the Pen MWzOBJW?editors=0010 by artyor (@artyor) on CodePen

Link to comment
Share on other sites

Hi,

 

I'm not completely sure I follow exactly what the problem is here, but the behaviour you are describing is exactly what should happen based on the code you have right now.

 

This is the order of operation you have implemented:

  1. Click on an image. Get the state with Flip.getState(). Set the display of the full size container to block. Reparent the image. Run the animation using Flip.from().
  2. Click on the full size container. Get the state of the image. Reparent the image. Animate with Flip.from(), once that is completed set the display of the full size container to none.

It makes perfect sense that if you click on another image, while you have an image that is going back the grid the full size container should disappear. The display is set to none after the Flip animation that takes the image back to the grid is completed.

 

If you want to prevent that I can think of two options:

  1. Create a boolean to indicate if an image is actually in full size state or going to full size state, in order to prevent any other image from going there. Also you can use your currentImg variable that you  have now:
    images.forEach((image) => {
      image.addEventListener("click", () => {
        if (currentImg) return;
        let dataImg = image.getAttribute("data-img");
        currentImg = dataImg;
        let state = Flip.getState(image.querySelector("img"));
        fsInner.style.display = "block";
        gsap.to(fsInner, {
          opacity: 1,
          duration: 0.3
        });
        fsInner.appendChild(image.querySelector("img"));
        Flip.from(state, {
          duration: 1.5,
          ease: "power3.out",
          absolute: true,
          scale: true
        });
      });
    });
    
    fsInner.addEventListener("click", () => {
      if (!currentImg) return;
      let target = document.querySelector(`.img-wrapper[data-img="${currentImg}"]`);
      let img = fsInner.querySelector("img");
      console.log(currentImg);
      let state = Flip.getState(img);
    
      target.appendChild(img);
      Flip.from(state, {
        duration: 1.5,
        ease: "power3.out",
        absolute: true,
        scale: true,
        zIndex: 99,
        onComplete: () => {
          fsInner.style.display = "none";
          currentImg = undefined;
        }
      });
    });
  2. Create a more convoluted approach if you want to have more than one image in the full size container, like adding/removing images from an array (you'll have to find a way to do that, but it shouldn't be too complicated). If the array length is bigger than zero, then don't set the display of the container to none:
    const imagesArray = [];
    
    // When you click an image on the grid add it to the array
    
    fsInner.addEventListener("click", () => {
      if (!currentImg) return;
      let target = document.querySelector(`.img-wrapper[data-img="${currentImg}"]`);
      let img = fsInner.querySelector("img");
      console.log(currentImg);
      let state = Flip.getState(img);
      
      // Now remove the image being send back to the grid from the array
    
      target.appendChild(img);
      Flip.from(state, {
        duration: 1.5,
        ease: "power3.out",
        absolute: true,
        scale: true,
        zIndex: 99,
        onComplete: () => {
          if (imagesArray.length > 0) return;
          // If there is an image in the array the display won't be set to none
          fsInner.style.display = "none";
        }
      });
    });

Personally  I would go with the first option. Seems clearer from a UX stand point.

 

Hopefully this helps.

Happy Tweening!

Link to comment
Share on other sites

3 minutes ago, Rodrigo said:

It makes perfect sense that if you click on another image, while you have an image that is going back the grid the full size container should disappear. The display is set to none after the Flip animation that takes the image back to the grid is completed.

Hi Rodrigo, thanks for commenting.

Yes that was intended, however, if you click on same image 1 while it's in animation of going back to initial parent (canceling the back animation), and animating it to full size again, onComplete of back animation won't trigger (Which is good, because if it did trigger, it wouldnt show image in full size).

However if you click image 1 to go full size, then click on it again to go back to initial parent, and while animation of going back to initial parent is happening, you really fast click on image 2, and then full size will actually go to display none and hide image 2 in full size (Because onComplete animation triggered). Now, I know how to solve it, but my question is:

Why does image 1 animation break/interrupt onComplete, but if we click on image 2, or any other image, it wont interrupt onComplete?

Link to comment
Share on other sites

  • Solution
Just now, artyor said:

Why does image 1 animation break/interrupt onComplete, but if we click on image 2, or any other image, it wont interrupt onComplete?

Ahh, super simple. GSAP automatically sees that you are creating an animation on the same target that will animate the same properties, so it overwrites the previous animation, which gets killed. That's why that onComplete is not called.

 

Hopefully this clear things up. Let us know if you have more questions.

Happy Tweening!

  • Thanks 1
Link to comment
Share on other sites

9 hours ago, Rodrigo said:

Ahh, super simple. GSAP automatically sees that you are creating an animation on the same target that will animate the same properties, so it overwrites the previous animation, which gets killed. That's why that onComplete is not called.


Thank you! I was confused why it's acting differently, thanks for clearing that up.

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