Home > Net >  Changing Images from array in a hero section with SetInterval
Changing Images from array in a hero section with SetInterval

Time:11-10

I'm making a portfolio website and want to make a hero section with transitioning images using SetInterval every few seconds. I tried this:

Do note that I placed my background image in CSS instead, not as an img in HTML.

var images = [
'https://via.placeholder.com/728x90.png?text=slide1',
'https://via.placeholder.com/728x90.png?text=slide2',
'https://via.placeholder.com/728x90.png?text=slide3',
'https://via.placeholder.com/728x90.png?text=slide4',
];
var container = document.getElementById('hero');
var i = 0;
setInterval(function() {
  var newImg = "url('"   images[i]   "')"
//  console.log(newImg);
  container.style.background = newImg;
  i = i   1;
  if (i == images.length) {
    i = 0;
  }
}, 1000);
#hero {
  height: 100vh;
  width: 100%;
  background: linear-gradient(rgba(0, 0, 0, 0.342), rgba(0, 0, 0, 0.342)), url('https://via.placeholder.com/728x90.png?text=slide1') fixed no-repeat center / cover;
  color: #fff9ff;
  transition: opacity 1s;
  opacity: 1;
}
<section id="hero">
  <div class="heroContainer">
    <div id="info">
      <h1>Lorem Ipsum</h1>
      <h2>Lorem ipsum.</h2>
      <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Reiciendis nesciunt excepturi quos obcaecati incidunt voluptatem ipsam sunt ipsum, autem deleniti cupiditate molestias quis unde quae totam porro dicta</p>
      <a id="heroButton" href="#">Contact Me</a>
    </div>
  </div>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

The image didn't transition, and I got these error:

url('undefined')

main.js:70 Uncaught TypeError: Cannot set properties of undefined (setting 'background')

Anyone knows why? I would like to continue using SetInterval btw!

CodePudding user response:

As others have mentioned, you need to make sure that the JavaScript is executed after the DOM has loaded.

I'm updating a CSS variable instead of setting the style. I just think it's more convenient.

I also get rid of the i variable, and instead use Array.prototype.shift() (Remove from last position - returns the removed item), and Array.prototype.push() to just change the position of the images within the array.

As you can tell, it takes a while for the images to load. You can fix this by preloading the images, but I won't cover that here.

It would also be nicer if you had a smoother transition (two images changing opacity).

I also hope that you don't intend to have a one second interval. Perhaps instead change them every 30 seconds:

var images = [
  'https://via.placeholder.com/701x90',
  'https://via.placeholder.com/702x90',
  'https://via.placeholder.com/703x90',
  'https://via.placeholder.com/704x90'
];
var container = document.getElementById('hero');

window.addEventListener("load", startBackgroundTransition);

function startBackgroundTransition() {
  setInterval(function() {
    container.style.setProperty("--background-image", `url(${images[1]})`);
    images.push(images.shift());
  }, 1000);
}
#hero {
  --background-image: url(https://via.placeholder.com/701x90);
  height: 100vh;
  width: 100%;
  background: 
    linear-gradient(rgba(0, 0, 0, 0.342),
    rgba(0, 0, 0, 0.342)), 
    var(--background-image) fixed no-repeat center / cover;
  color: #fff9ff;
  /*transition: opacity 1s;
  opacity: 1;*/
}
<section id="hero">
  <div class="heroContainer">
    <div id="info">
      <h1>Lorem Ipsum</h1>
      <h2>Lorem ipsum.</h2>
      <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Reiciendis nesciunt excepturi quos obcaecati incidunt voluptatem ipsam sunt ipsum, autem deleniti cupiditate molestias quis unde quae totam porro dicta</p>
      <a id="heroButton" href="#">Contact Me</a>
    </div>
  </div>
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

Why are you using setInterval?

For loops can deal with this:

var images = [
'https://via.placeholder.com/728x90.png?text=slide1',
'https://via.placeholder.com/728x90.png?text=slide2',
'https://via.placeholder.com/728x90.png?text=slide3',
'https://via.placeholder.com/728x90.png?text=slide4' // < un-needed comma
];
var container = document.getElementById('hero'); // Make sure you call the script after the element

for (var i = 0; i < images.length; i  ) {

  // No need for quote marks in css "url()"

  var newImg = "url("   images[i]   ")";
  container.style.background = newImg;

  if (i >= images.length) {
    i = 0;
  }
}

Or while loops:

var images = [
'https://via.placeholder.com/728x90.png?text=slide1',
'https://via.placeholder.com/728x90.png?text=slide2',
'https://via.placeholder.com/728x90.png?text=slide3',
'https://via.placeholder.com/728x90.png?text=slide4' // < un-needed comma
];
var container = document.getElementById('hero'); // Make sure you call the script after the element
let i = 0;
do {
  // No need for quote marks in css "url()"
  var newImg = "url("   images[i]   ")";
  container.style.background = newImg;
  if (i >= images.length) {
    i = 0;
  }
} while (i < images.length);

jQuery:

var images = [
'https://via.placeholder.com/728x90.png?text=slide1',
'https://via.placeholder.com/728x90.png?text=slide2',
'https://via.placeholder.com/728x90.png?text=slide3',
'https://via.placeholder.com/728x90.png?text=slide4' // < un-needed comma
];
var container = $("#hero");

for (var i = 0; i < images.length; i  ) {
  var newImg = "url("   images[i]   ")";
  container.css("background", newImg);

  if (i >= images.length) {
    i = 0;
  }
}

jQuery while loop:

var images = [
'https://via.placeholder.com/728x90.png?text=slide1',
'https://via.placeholder.com/728x90.png?text=slide2',
'https://via.placeholder.com/728x90.png?text=slide3',
'https://via.placeholder.com/728x90.png?text=slide4' // < un-needed comma
];
var container = $("#hero"); // Make sure you call the script after the element
let i = 0;
do {
  var newImg = "url("   images[i]   ")";
  container.css("background", newImg);
  if (i >= images.length) {
    i = 0;
  }
} while (i < images.length);

You also had quotes around the css "url()" value.

You also shouldn't change i back to 0 after the process is done, because this will lead into an infinite loop.

  • Related