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.