Reputation: 1124
I have four DIVs with different background-images. I am trying to get the DIVs to shuffle through randomly selected background-images every 2 seconds but only one DIV at a time.
I have put together this vanilla javascript with the help of others while searching for a solution, but I am running into the following problems:
Here is the code I have so far, any help is very much appreciated.
var urls = [
'url(https://placekitten.com/g/350/150)',
'url(https://placekitten.com/g/200/600)',
'url(https://placekitten.com/g/550/250)',
'url(https://placekitten.com/g/700/300)',
'url(https://placekitten.com/g/300/550)',
'url(https://placekitten.com/g/400/200)',
'url(https://placekitten.com/g/350/750)'
];
var active = Math.floor(Math.random() * (urls.length));
setInterval(function() {
let rand = Math.floor(Math.random() * 4);
if (rand <= 2 && rand == document.getElementsByClassName('image')[0].getAttribute("data-changed")) {
rand = rand + 1;
} else if (rand == 2 && rand == document.getElementsByClassName('image')[0].getAttribute("data-changed")) {
rand = rand - 1;
}
document.getElementsByClassName('image')[rand].style.backgroundImage = urls[active];
document.getElementsByClassName('image')[0].setAttribute("data-changed", rand);
active++;
if (active == urls.length) active = 0;
//})
}, 2000);
.image {
background-size: cover;
display: inline-block;
width: 200px;
height: 200px;
border: 1px solid red;
}
.one {
background-image: url(https://placekitten.com/g/350/150);
}
.two {
background-image: url(https://placekitten.com/g/300/550);
}
.three {
background-image: url(https://placekitten.com/g/400/200);
}
.four {
background-image: url(https://placekitten.com/g/350/750);
}
<div class="image one"></div>
<div class="image two"></div>
<div class="image three"></div>
<div class="image four"></div>
And here is the code on jsFiddle.
Upvotes: 0
Views: 975
Reputation: 1979
I modified your code just a bit to make this new version, that use Fade out / Fade In functions from here, using visibility CSS attribute. This will just make the image disappear, the background will be visible a moment, and then the new image will appear. There are many ways of doing a Fade effect, and this is one of them. You could want something else (for example, the image becomes black and then the new image appears). If you want to try another types of Fade, you can search through CSS filters list.
var urls = [
'url(https://placekitten.com/g/350/150)',
'url(https://placekitten.com/g/200/600)',
'url(https://placekitten.com/g/550/250)',
'url(https://placekitten.com/g/700/300)',
'url(https://placekitten.com/g/300/550)',
'url(https://placekitten.com/g/400/200)',
'url(https://placekitten.com/g/350/750)'
];
var active = Math.floor(Math.random() * (urls.length));
setInterval(function() {
let rand = Math.floor(Math.random() * 4);
if (rand <= 2 && rand == document.getElementsByClassName('image')[0].getAttribute("data-changed")) {
rand = rand + 1;
} else if (rand == 2 && rand == document.getElementsByClassName('image')[0].getAttribute("data-changed")) {
rand = rand - 1;
}
document.getElementsByClassName('image')[rand].classList.remove("visible");
document.getElementsByClassName('image')[rand].classList.add("hidden");
setTimeout(function(){
document.getElementsByClassName('image')[rand].style.backgroundImage = urls[active];
document.getElementsByClassName('image')[0].setAttribute("data-changed", rand);
document.getElementsByClassName('image')[rand].classList.remove("hidden");
document.getElementsByClassName('image')[rand].classList.add("visible");
},400); // 400 ms because animation duration is 0.4s
active++;
if (active == urls.length) active = 0;
//})
}, 2000);
.image {
background-size: cover;
display: inline-block;
width: 200px;
height: 200px;
border: 1px solid red;
}
.one {
background-image: url(https://placekitten.com/g/350/150);
}
.two {
background-image: url(https://placekitten.com/g/300/550);
}
.three {
background-image: url(https://placekitten.com/g/400/200);
}
.four {
background-image: url(https://placekitten.com/g/350/750);
}
.visible {
opacity: 1;
transition: opacity 0.4s ease;
}
.hidden {
opacity: 0;
transition: opacity 0.4s ease;
}
<div class="image visible one"></div>
<div class="image visible two"></div>
<div class="image visible three"></div>
<div class="image visible four"></div>
However, this is not the best way of doing it. So I modified the code, and added some JQuery stuff.
var urls = [
'url(https://placekitten.com/g/350/150)',
'url(https://placekitten.com/g/200/600)',
'url(https://placekitten.com/g/550/250)',
'url(https://placekitten.com/g/700/300)',
'url(https://placekitten.com/g/300/550)',
'url(https://placekitten.com/g/400/200)',
'url(https://placekitten.com/g/350/750)'
];
// Select the next image, may be one of the actual displayed images
var active = Math.floor(Math.random() * (urls.length));
setInterval(function() {
// Select randomnly the next div to change
var rand = Math.floor(Math.random() * 4);
// Store this list, so that we only make one call to the page
// equiv : document.getElementsByClassName('image')
let images = $('.image');
// equiv : images[0].getAttribute("data-changed")
let datachanged = images.attr("data-changed");
// This conditions work, but their is a better way of doing it. See comment below the snippet
if (rand <= 2 && rand == datachanged ) {
rand += 1;
} else if (rand >= 2 && rand == datachanged ) {
rand -= 1;
}
// Jquery selector for the targetted div
let current = $('.image:nth-child('+(rand+1)+')');
// Now we can use JQuery methods, such as toggleClass
current.toggleClass("visible hidden");
// The fade effect takes 0.4ms, or 400ms
// So we use a setTimeout to change the bg in 400ms and not immediatly
// Once the background is changed, the "visible" class we be added
// If you want to change the duration, remember to also change it in the CSS
setTimeout(function(){
// equiv : images[rand].style.backgroundImage = urls[active];
current.css('background-image', urls[active]);
images[0].setAttribute("data-changed", rand);
current.toggleClass("hidden visible");
},400); // 400 ms because CSS animation duration is 0.4s
// Change active value so that the background will not be same next time
active++;
// Faster way to write if(...) { active = 0 }
active = (active == urls.length) ? 0 : active ;
}, 2000);
.image {
background-size: cover;
display: inline-block;
width: 200px;
height: 200px;
border: 1px solid red;
transition: opacity 0.4s ease;
}
.one {
background-image: url(https://placekitten.com/g/350/150);
}
.two {
background-image: url(https://placekitten.com/g/300/550);
}
.three {
background-image: url(https://placekitten.com/g/400/200);
}
.four {
background-image: url(https://placekitten.com/g/350/750);
}
.visible {
opacity: 1;
}
.hidden {
opacity: 0;
}
<!-- JQuery 3.3.1 -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<div class="image one" data-changed="0"></div>
<div class="image two"></div>
<div class="image three"></div>
<div class="image four"></div>
</div>
Also, note that you could change
rand = Math.floor(Math.random() * 4);
if (rand <= 2 && rand == datachanged ) {
rand += 1;
} else if (rand >= 2 && rand == datachanged ) {
rand -= 1;
}
by
while(rand == datachanged)
rand = Math.floor(Math.random() * 4);
So that you have a better "random".
I put a lot of comment, I hope it helped.
Upvotes: 1
Reputation: 213
var urls = [
'url(https://placekitten.com/g/350/150)',
'url(https://placekitten.com/g/200/600)',
'url(https://placekitten.com/g/550/250)',
'url(https://placekitten.com/g/700/300)',
'url(https://placekitten.com/g/300/550)',
'url(https://placekitten.com/g/400/200)',
'url(https://placekitten.com/g/350/750)'
];
var active = Math.floor(Math.random() * (urls.length));
setInterval(function() {
let rand = Math.floor(Math.random() * 4);
if (rand <= 2 && rand == document.getElementsByClassName('image')[0].getAttribute("data-changed")) {
rand = rand + 1;
} else if (rand == 2 && rand == document.getElementsByClassName('image')[0].getAttribute("data-changed")) {
rand = rand - 1;
}
const imageElements = document.getElementsByClassName('image')
for(var i = 0; i < imageElements.length; i++){
imageElements[i].className = imageElements[i].className.replace('animate-fade-in','')
}
imageElements[rand].style.backgroundImage = urls[active];
imageElements[rand].className = "image animate-fade-in";
imageElements[0].setAttribute("data-changed", rand);
active++;
if (active == urls.length) active = 0;
//})
}, 2000);
.image {
background-size: cover;
display: inline-block;
width: 200px;
height: 200px;
border: 1px solid red;
}
.one {
background-image: url(https://placekitten.com/g/350/150);
}
.two {
background-image: url(https://placekitten.com/g/300/550);
}
.three {
background-image: url(https://placekitten.com/g/400/200);
}
.four {
background-image: url(https://placekitten.com/g/350/750);
}
.animate-fade-in {
animation: fadeIn 0.5s linear;
animation-fill-mode: both;
}
@keyframes fadeIn {
0% {
opacity: 0;
}
50% {
opacity: 0.5;
}
100% {
opacity: 1;
}
}
<div class="image one animate-fade-in"></div>
<div class="image two animate-fade-in"></div>
<div class="image three animate-fade-in"></div>
<div class="image four animate-fade-in"></div>
Upvotes: 0