Home > Enterprise >  trigger animation whenever the <img src={value} /> src value changes
trigger animation whenever the <img src={value} /> src value changes

Time:04-25

I'm using React to Create an img element that changes its src attribute after specific time with setInterval function based on an array that contains many images.

so the thing is i want to make an animation whenever the src attribute changes, i was thinking of using React.useEffect() hook to watch the src changes and add some animation but i couldn't go further logically.

my code :

import Canada from "../images/Canada.jpg"
import Tokyo from "../images/Tokyo.jpg"
import NewYork from "../images/NewYork.jpg"
import southKorea from "../images/southKorea.jpg"


function AboutMe() {

    const imgArray = [NewYork, Tokyo, Canada, southKorea]
     let i = 0;
    const maxImgArray = imgArray.length -1 ;
    const swap = function() {
        let image = imgArray[i];
        i = (i === maxImgArray) ? 0 :   i;
        const attr = document.getElementById("moving-image");
        attr.src=image;
    }
    setInterval(swap, 5000)
    return (
    <section className="About-me">
        <h1>About me</h1>
        <div className="container">
        <div className="cities-images">
            <img 
            src={Tokyo}
            alt="NewYork" id="moving-image"></img>
            <label >
              <input type="checkbox"/>
              <span ></span>
            </label>
        </div>
            <div className="info">
                
            </div>
        </div>
    </section>    
    )
}

CodePudding user response:

By using useState hook in react, we can re-render the component with updated value. So for src change, we can use useState to update the current src of the image.

By using useEffect hook we can do anything once src state change like set different animations.

Component State

  const [image, setImage] = useState(Usa);
  const [imageIndex, setImageIndex] = useState(0);
  const imgArray = [Usa, Japan, Canada, SouthKorea];

useEffect

useEffect(() => {
let interval = null;
if (i !== maxImgArray) {
  interval = setInterval(() => {
    let image = imgArray[imageIndex];
    const attr = document.getElementById("moving-image");
    attr.src = image;
    // update the img index to state
    setImageIndex((imageIndex) =>
      imageIndex === maxImgArray ? 0 : imageIndex   1
    );
    // update the src in state.
    setImage(attr.src);
  }, 3000);
}
// When our code runs and reruns for every render, useEffect also cleans up after itself using the cleanup function.
// Here we clear the interval to remove the effects that could happen with state change while interval.
return () => clearInterval(interval);
}, [image, imageIndex]); // when image, imageIndex gets change, useEffect will be triggered.

Component here I used framer-motion for animation.

<section className="Country-flag">
    <h1>Country Flag</h1>
    <div className="container">
      <motion.div
        key={image}
        animate={{ x: 100, opacity: 1 }}
        transition={{
          delay: 1,
          x: { type: "spring", stiffness: 100 },
          default: { duration: 2 }
        }}
      >
        {/* when state {image} value change, this component will re-render with new src */}
        <img alt="NewYork" src={image} id="moving-image"></img>
      </motion.div>
      <div className="info"></div>
    </div>
  </section>

Check this sample sandbox for produced code.

If you want different animations for each img, then add another state variable for animation and change the value inside the useEffect for each image state.

  • Related