1

I have two images. When I click the image container, a state is changed, and another image is revealed, while the other one disappears - like this:

const Image= ({image1, image2}) => {

    const [image, setImageState] = useState(true);

    return (

        <div className="image-container" onClick={ () => setImageState(!image)}>
           <img src={image ? "/images/" + image1 : "/images/" + image2} alt="" />
        </div>
    )
}

So this works as intended. When I click, the state changes, and so does the image. However, I would like there to be a fade in/out effect when the state changes. How is this achieved ?

Rosen Dimov
  • 1,055
  • 12
  • 32
Denver Dang
  • 2,433
  • 3
  • 38
  • 68

2 Answers2

0

I'm not sure if it's possible to animate via CSS the src attribute of an image element (I personally prefer to do it via CSS if possible). However you can animate its opacity property. And you'll need two elements for that - one for the fade-out effect and one for the fade-in. Here's a sandbox. The situation is very similar to this question, there you can see how to put images on top of each other (the one hidden).

Some things to note:

  • I've pre-set the two images' src attributes and don't set them to nulls or some falsy values so that we don't see broken image icon while animating (could occur if you have your state separated among multiple useState hooks). In my case I batch changes at once to have only a single render and avoid any flashes of broken image icon.
  • Browser will do the animation upon class change and of course if the property in this class can be animated. opacity is a CSS property which can be animated.
  • For your case you'll probably need to set the src dynamically in your handler so I'd recommend you make sure you don't cause multiple renders/paints to avoid visual inconsistencies, so I think you should batch your state updates at once.
  • In my case the images are next to each other, but if you want to first fade-out the first image and then fade-in the second, you'll need to synchronize animation with transition-delay property.
Rosen Dimov
  • 1,055
  • 12
  • 32
0

You could some Animation library like GSAP and accomplish this, as this is difficult to accomplish by css alone. https://codepen.io/rohinikumar4073/pen/mdVYbrm?editors=1111

function toggleImage() {
  let tween = TweenLite.to(".img", 2, {
    opacity: 0,
    onComplete: function() {
      let image = document.querySelector(".img")
      if (image.src === "https://via.placeholder.com/350") {
        image.src = "https://via.placeholder.com/150";
      } else {
        image.src = "https://via.placeholder.com/350";

      }
      let tween2 = TweenLite.to(".img", 2, {
        opacity: 2
      });
    }
  });
}
<script src=https://cdnjs.cloudflare.com/ajax/libs/gsap/3.4.2/gsap.min.js"></script>
<div onclick="toggleImage()">


  <img class="img" id="img1" src="https://via.placeholder.com/150" />

</div>
vishnu sandhireddy
  • 1,148
  • 1
  • 7
  • 12