skip to Main Content

I want to change images every 2 seconds automatically with fade in animation, but my problem is when the next image is shown, the previous image disappears before the next image is displayed, so with the code that I have each image disappears completely showing the background of the page before showing the next one.

My goal is to keep the previous image a short time before the next one appears to avoid showing the background of the page.



function hero() {

  const images = [
    '/public/Hero-image-1.jpg',
    '/public/Hero-image-2.jpg',
    '/public/Hero-image-3.jpg'
  ];

  const [currentIndexImage, setcurrentIndexImage] = React.useState(0);
  const [fade, setFade] = React.useState(false);

  React.useEffect(() => {

    const interval = setInterval(() => {

      setFade(false);


      setTimeout(() => {
        setcurrentIndexImage((prevIndex) => (prevIndex + 1) % images.length);
        setFade(true); 
        
      }, 1000);

    }, 2000);
  
    // Cleanup the interval on component unmount
    return () => clearInterval(interval);
  }, []);
  
  return (
    <>

          <div className="hero-img-container">

            <div className="hero-imgs">

            <img src={images[currentIndexImage]}  className={fade ? 'fade' : 'fade-out'}/>
              


            </div>
    </>


.fade {
    opacity: 1;
    transition: opacity 0.5s ease-in-out;
}
  
  .fade-out {
    opacity: 0;
    transition: opacity 0.5s ease-in-out;
  }
  

3

Answers


  1. I got it where you are facing problem . so think of it like that suppose one image is disappearing other should start appearing same time.

    so why not we positon another image just above it and then one starts fading out at the same time other starts fading in.

    to achieve this we have to keep track of next image using states.

    i have provided the code below i hope it will help.

    
    import React, { useState, useEffect } from "react";
    import "./App.css";
    
    function App() {
      const images = [
        'https://buffer.com/library/content/images/size/w1200/2023/10/free-images.jpg',
        'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT8k3sU7sIYgSOfu9rcTFvOsNc6JYcAzZRc2ptUA0iIJT4cBOI4sypyuiIVA8ChpwXWqJc&usqp=CAU',
     'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT8k3sU7sIYgSOfu9rcTFvOsNc6JYcAzZRc2ptUA0iIJT4cBOI4sypyuiIVA8ChpwXWqJc&usqp=CAU'
    
      ];
    
      const [currentIndexImage, setCurrentIndexImage] = useState(0);
      const [nextIndexImage, setNextIndexImage] = useState(1);
      const [fade, setFade] = useState(false);
    
      useEffect(() => {
        const interval = setInterval(() => {
          setFade(false);
    
          setTimeout(() => {
            setCurrentIndexImage((prevIndex) => (prevIndex + 1) % images.length);
            setNextIndexImage((prevIndex) => (prevIndex + 2) % images.length);
            setFade(true);
          }, 500); 
    
        }, 2000);
    
     
        return () => clearInterval(interval);
      }, []);
    
      return (
        <>
          <div className="hero-img-container">
            <div className="hero-imgs">
              <img src={images[currentIndexImage]} className={fade ? 'fade-in' : 'fade-out'} />
              <img src={images[nextIndexImage]} className={fade ? 'fade-out' : 'fade-in'} style={{ position: 'absolute', top: 0, left: 0 }} />
            </div>
          </div>
        </>
      );
    }
    
    export default App;
    
    
    
    Login or Signup to reply.
  2. I faced the same problem and and came by the following solution which was using backgroundImage in a div instead of using img tag.

    import { useState, useEffect } from "react";
    
    function App() {
      const images = [
        "https://picsum.photos/400/400",
        "https://picsum.photos/400/401",
        "https://picsum.photos/400/402",
      ];
    
      const [currentIndexImage, setCurrentIndexImage] = useState(0);
    
      useEffect(() => {
        const interval = setInterval(() => {
          setTimeout(() => {
            setCurrentIndexImage((prevIndex) => (prevIndex + 1) % images.length);
          }, 500);
        }, 2000);
    
        return () => clearInterval(interval);
      }, []);
    
      return (
        <>
          <div className="hero-img-container">
            <div className="hero-imgs">
              {/* to cache the images  */}
              {images.map((image, _index) => (
                <img src={image} key={image} style={{ display: "none" }} />
              ))}
              <div
                style={{
                  width: 200,
                  height: 200,
                  backgroundImage: `url('${images[currentIndexImage]}')`,
                  backgroundPosition: "center",
                  backgroundSize: "contain",
                  backgroundRepeat: "no-repeat",
                  transition: "all 0.5s ease-in-out",
                }}
              />
            </div>
          </div>
        </>
      );
    }
    
    export default App;
    
    
    Login or Signup to reply.
  3. I understand your issue. One solution is to position another image above the disappearing image and gradually fade out the first image while simultaneously fading in the second image. This can be achieved by keeping track of the next image using states. Below is the code that can help you implement this.

    import React from 'react';
    
    function Hero() {
      const images = [
        '/public/Hero-image-1.jpg',
        '/public/Hero-image-2.jpg',
        '/public/Hero-image-3.jpg'
      ];
    
      const [currentIndexImage, setCurrentIndexImage] = React.useState(0);
      const [nextIndexImage, setNextIndexImage] = React.useState(1);
      const [fade, setFade] = React.useState(false);
    
      React.useEffect(() => {
        const interval = setInterval(() => {
          setFade(true);
    
          setTimeout(() => {
            setFade(false);
            setCurrentIndexImage((prevIndex) => {
              const newIndex = (prevIndex + 1) % images.length;
              setNextIndexImage((newIndex + 1) % images.length);
              return newIndex;
            });
          }, 1000);
    
        }, 3000); // 3 seconds to give time for fading
    
        return () => clearInterval(interval);
      }, []);
    
      return (
        <div className="hero-img-container">
          <div className="hero-imgs">
            <img
              src={images[currentIndexImage]}
              className={fade ? 'fade-out' : 'fade-in'}
              alt="current"
            />
            <img
              src={images[nextIndexImage]}
              className={fade ? 'fade-in' : 'fade-out'}
              alt="next"
            />
          </div>
        </div>
      );
    }
    
    export default Hero;
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search