2
votes

I have three background images that I want to fade in and out at interval of 5 seconds. I also make use of the native bootstrap carousel component to slide text in and out at an interval of 5 seconds to match and coincide with the changing and fading background image.

Scenario

  • Problem 1: The first background image will be the default background image on page load. After 5 seconds, the second background image fades which also coincides with the same time the carousel slides to the second text. After another 5 seconds, the third background image fades in and the carousel slides to the next text.

  • Problem 2: The bootstrap carousel components has an indicator which when clicked, switches and slides it to the text in that carousel part. I want the background image to change when the carousel indicator is clicked. That is, if carousel indicator 1 is clicked, the background image should fade to the first background image. This should apply for the second and third carousel indicator and their respective background images. The background image should NOT change and fade to the clicked one if it is presently the active carousel item and background image.

Present Situation

  • I have been able to achieve the background image with the fading effect using jquery with a solution I also got here in stackoverflow. I have also done the text carousel using bootstrap carousel component with option (data-interval="5000") which sets the switching time to 5 seconds to match the same time interval with which the background image fades in and out but there is still a noticeable little delay. How can the noticeable delay be removed?

  • The image sometimes flash before fading. Is there a better and more appropriate way to achieve the fading effect without the image flashing?

  • Clicking the carousel indicator doesn't switch and fade the background image to the next even when I ran the function on click. How can it be achieved the right way?

Here is what I have tried:

var bgImageArray = ["1_ozdgvm.jpg", "2_vjtjfy.jpg", "3_oxpdx2.jpg"],
  base = "https://res.cloudinary.com/iolamide/image/upload/v1604569872/home_banner_",
  secs = 5;
bgImageArray.forEach(function(img) {
  new Image().src = base + img;
  // caches images, avoiding white flash between background replacements
});

function backgroundSequence() {
  window.clearTimeout();
  var k = 0;
  for (i = 0; i < bgImageArray.length; i++) {
    setTimeout(function() {
      document.getElementById('animated-bg').style.backgroundImage = "url(" + base + bgImageArray[k] + ")";
      // document.getElementById('animated-bg').style.backgroundSize ="cover";
      if ((k + 1) === bgImageArray.length) {
        setTimeout(function() {
          backgroundSequence()
        }, (secs * 1000))
      } else {
        k++;
      }
    }, (secs * 1000) * i)
  }
}

backgroundSequence();


$('.carousel-item').click(function() {
  backgroundSequence();
})
*,
*::before,
*::after {
  margin: 0;
  padding: 0;
}

html {
  box-sizing: border-box;
}

body {
  box-sizing: inherit;
  color: #fff !important;
}

.animated-bg {
  background-image: url("https://res.cloudinary.com/iolamide/image/upload/v1604569872/home_banner_1_ozdgvm.jpg");
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  transition: background 1s;
  height: 694px;
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

.animated-bg:before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
}

.container {
  padding: 3rem;
  border-radius: 20px;
  width: 700px;
  background: rgba(0, 0, 0, 0.3);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
}

.text-top p {
  width: 400px;
  margin: 30px auto;
  text-align: center;
}

h1 {
  margin-top: 0;
  text-align: center;
  font-weight: 600;
}

.carousel-item p {
  width: 330px;
  text-align: center;
}

.carousel-indicators {
  bottom: -50px !important;
}

@media only screen and (max-width: 800px) {
  .container {
    padding: 2rem;
    width: 90%;
  }
}

@media only screen and (max-width: 500px) {
  .text-top p {
    width: 80%;
  }
}
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>

<div class="animated-bg" id="animated-bg">
  <div class="container">
    <div class="text-top" id="texttop">
      <h1>Crossfade and Text Carousel</h1>
      <p>Fade background image and swipe text at the same time. Also fade the background image to the one that matches the carousel's text when the carousel's indicator is clicked</p>
    </div>
    <div id="carouselExampleIndicators" class="carousel slide" data-ride="carousel" data-interval="5000">
      <ol class="carousel-indicators">
        <li data-target="#carouselExampleIndicators" data-slide-to="0" class="active"></li>
        <li data-target="#carouselExampleIndicators" data-slide-to="1"></li>
        <li data-target="#carouselExampleIndicators" data-slide-to="2"></li>
      </ol>
      <div class="carousel-inner">
        <div class="carousel-item active">
          <p>
            Carousel Text One
          </p>
        </div>
        <div class="carousel-item">
          <p>Carousel Text Two</p>
        </div>
        <div class="carousel-item">
          <p>Carousel Text Three</p>
        </div>
      </div>
    </div>
  </div>
</div>
1

1 Answers

2
votes

You don't need all the logic of witching the images by yourself. You can listen to slide change with the carousel api on('slide.bs.carousel') and switch the image accordingly.

const bgImageArray = ["1_ozdgvm.jpg", "2_vjtjfy.jpg", "3_oxpdx2.jpg"],
  base = "https://res.cloudinary.com/iolamide/image/upload/v1604569872/home_banner_";
  
bgImageArray.forEach(function(img) {
  new Image().src = base + img;
  // caches images, avoiding white flash between background replacements
});
  
$('.carousel'). on('slide.bs.carousel', function(e) {
  $('.animated-bg').css({
    backgroundImage: `url(${base}${bgImageArray[e.to]})`
  });
});
*,
*::before,
*::after {
  margin: 0;
  padding: 0;
}

html {
  box-sizing: border-box;
}

body {
  box-sizing: inherit;
  color: #fff !important;
}

.animated-bg {
  background-image: url("https://res.cloudinary.com/iolamide/image/upload/v1604569872/home_banner_1_ozdgvm.jpg");
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  transition: background 1s;
  height: 694px;
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

.animated-bg:before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
}

.container {
  padding: 3rem;
  border-radius: 20px;
  width: 700px;
  background: rgba(0, 0, 0, 0.3);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
}

.text-top p {
  width: 400px;
  margin: 30px auto;
  text-align: center;
}

h1 {
  margin-top: 0;
  text-align: center;
  font-weight: 600;
}

.carousel-item p {
  width: 330px;
  text-align: center;
}

.carousel-indicators {
  bottom: -50px !important;
}

@media only screen and (max-width: 800px) {
  .container {
    padding: 2rem;
    width: 90%;
  }
}

@media only screen and (max-width: 500px) {
  .text-top p {
    width: 80%;
  }
}
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>

<div class="animated-bg" id="animated-bg">
  <div class="container">
    <div class="text-top" id="texttop">
      <h1>Crossfade and Text Carousel</h1>
      <p>Fade background image and swipe text at the same time. Also fade the background image to the one that matches the carousel's text when the carousel's indicator is clicked</p>
    </div>
    <div id="carouselExampleIndicators" class="carousel slide" data-ride="carousel" data-interval="5000">
      <ol class="carousel-indicators">
        <li data-target="#carouselExampleIndicators" data-slide-to="0" class="active"></li>
        <li data-target="#carouselExampleIndicators" data-slide-to="1"></li>
        <li data-target="#carouselExampleIndicators" data-slide-to="2"></li>
      </ol>
      <div class="carousel-inner">
        <div class="carousel-item active">
          <p>
            Carousel Text One
          </p>
        </div>
        <div class="carousel-item">
          <p>Carousel Text Two</p>
        </div>
        <div class="carousel-item">
          <p>Carousel Text Three</p>
        </div>
      </div>
    </div>
  </div>
</div>

https://jsbin.com/mewiwuv/edit?js,output