Reputation: 992
I have made an image grid using flexbox on a webpage that I am working on. There are 8 boxes in the grid, and I would like to randomly chose one and assign it one of 12 random images every 2 seconds. My approach is to have an array of urls to the images I would like to pick from, generate a random number to select which box with have its image changed, and then pick a random image and assign it to the background image of that box. I would just like to ensure that the same image does not appear twice, as well as include some sort of transition rather than simply changing the image. Any help here is greatly appreciated.
HTML:
<div class="stats__grid--desktop">
<div class="grid__top">
<div class="grid__top--item one" style="background-image: url(../css/images/work-template/bench/stats2/a.png);"></div>
<div class="grid__top--item two" style="background-image: url(../css/images/work-template/bench/stats2/b.png);"></div>
<div class="grid__top--item three" style="background-image: url(../css/images/work-template/bench/stats2/c.png);"></div>
<div class="grid__top--item four" style="background-image: url(../css/images/work-template/bench/stats2/d.png);"></div>
</div>
<div class="grid__mid">
<div class="grid__top--item five" style="background-image: url(../css/images/work-template/bench/stats2/e.png);"></div>
<div class="grid__top--item six" style="background-image: url(../css/images/work-template/bench/stats2/f.png);"></div>
<div class="grid__top--item seven" style="background-image: url(../css/images/work-template/bench/stats2/g.png);"></div>
<div class="grid__top--item eight" style="background-image: url(../css/images/work-template/bench/stats2/h.png);"></div>
</div>
</div>
jQuery:
window.setInterval(function() {
var imgArray = ["../css/images/work-template/bench/stats2/j.png", "../css/images/work-template/bench/stats2/k.png", "../css/images/work-template/bench/stats2/l.png"]
var imgSelect = 0 + Math.floor(Math.random() * 2);
var number = 1 + Math.floor(Math.random() * 8);
if (number == 1) {
var imgChange = "one";
}
else if (number == 2) {
var imgChange = "two";
}
else if (number == 3) {
var imgChange = "three";
}
else if (number == 4) {
var imgChange = "four";
}
else if (number == 5) {
var imgChange = "five";
}
else if (number == 6) {
var imgChange = "six";
}
else if (number == 7) {
var imgChange = "seven";
}
else if (number == 8) {
var imgChange = "eight";
}
else {
var imgChange = "nine";
}
$("." + imgChange).css( "background-image", "url("+imgArray[imgSelect]+")" );
var temp = $("." + imgChange).css("background-image")
console.log(temp)
}, 500);
Upvotes: 0
Views: 1664
Reputation: 565
Based on what you've explained, it looks like you're already properly selecting a random image and random item in the grid. All that's left to do is ensure that you're not displaying the same image at the same time.
I would also suggest changing your class names so that your system is more flexible. Using "one"
, "two"
, "three"
, etc. works, but your HTML and CSS will be much more elegant and scalable if you instead use something like "g1"
, "g2"
, "g3"
, etc., where "g" stands for grid item. In that case, you'd do the following (trying to avoid hardcoding):
var imgArray = ["../css/images/work-template/bench/stats2/a.png", "../css/images/work-template/bench/stats2/b.png", "../css/images/work-template/bench/stats2/c.png", "../css/images/work-template/bench/stats2/d.png", "../css/images/work-template/bench/stats2/e.png", "../css/images/work-template/bench/stats2/f.png", "../css/images/work-template/bench/stats2/g.png", "../css/images/work-template/bench/stats2/h.png", "../css/images/work-template/bench/stats2/i.png", "../css/images/work-template/bench/stats2/j.png", "../css/images/work-template/bench/stats2/k.png", "../css/images/work-template/bench/stats2/l.png"];
setInterval(function() {
var $gridItems = $(".stats__grid--desktop .grid__top--item");
var gridLength = $gridItems.length;
var gridItemNum = 1 + Math.floor(Math.random() * gridLength);
var $gridItem = $(".stats__grid--desktop .grid__top--item.g" + gridItemNum);
var illegalImgs = [];
var legalImgs = [];
// Loop through images currently in grid to eliminate them
for (var i = 0; i < gridLength; i++) {
var curr = $($gridItems[i]).css("background-image");
curr = curr.replace('url(','').replace(')','').replace(/\"/gi, "");
curr = curr.replace(/http(?:s)?:\/\/\w+\.\w+/gi, '..');
var imgIndex = imgArray.indexOf(curr);
illegalImgs.push(imgIndex);
}
// Find images that may be used ("legal" images)
for (var i = 0; i < imgArray.length; i++) {
if (illegalImgs.indexOf(i) === -1) { legalImgs.push(i); }
}
// Choose image randomly from legal images
var legalID = Math.floor(Math.random() * legalImgs.length);
var imgID = legalImgs[legalID];
var imgURL = imgArray[imgID];
$gridItem.css("background-image", "url(" + imgURL + ")");
}, 2000);
Alternatively, check out a working demo that I made on Codepen.
Additionally, here's one way to transition your background image: CSS3 background image transition
I also wanted to note that you don't necessarily need to use classes for each specific grid item. Even using the fix I've included above is a bit tedious. If you need to access each individual grid item separately, try using the :nth-child()
selector, and in Javascript, you can use the $(".some-element").children(".optional-selector-goes-here")[someInteger]
. More info on the nth-child selector here.
EDIT: Originally, there was an issue because your URLs were local, but I've added a regular expression to fix that. See the following line in the script above:
curr = curr.replace(/http(?:s)?:\/\/\w+\.\w+/gi, '..');
Upvotes: 2
Reputation: 30099
I suggest making a grid of div
elements each containing 2 swap img
elements which are absolutely positioned on top of each other.
Every time you swap images, use splice
to randomly remove a URL from the array and put it in the bottom img
and then fade it in as you fade out the top img
, creating a cross-fade effect. When the cross-fade finishes, push the src
of the top image back onto the URL array. Change the bottom img
to the top to be ready to do it again. Rinse and repeat.
I also suggest, as has been stated elsewhere that you uniquely reference each box with an id
that ends with its order number. This makes it easy to choose the element programatically, without a big if/then/else statement. It also makes it easy to change the size of the grid, as you don't need to change the code, just the css.
I made a grid, with each box coded like so:
<div class="grid__box" id="g0">
<img class="swap">
<img class="swap">
</div>
With g0
being unique in each box. g1
, g2
, g3
, etc.
The jQuery looks like this:
var imgArray = ["yoururlhere", "yoururlhere2", ..., "anotherurl" ];
// load the images from the array initially
function loadImages() {
$('.grid__box').each(function(i) {
var newImage = imgArray.splice(0,1)[0];
$(this).find('.swap').attr('src', newImage);
});
}
// choose a box at random, swap its image with a random one from the array
function swapImage() {
var imgChoice = Math.floor(Math.random() * imgArray.length);
var newImage = imgArray.splice(imgChoice,1)[0];
var target = Math.floor(Math.random() * $('.grid__box').length);
var mainImg = $('#g' + target + ' .swap').eq(1);
var swapImg = $('#g' + target + ' .swap').eq(0);
swapImg.show().attr('src', newImage);
imgArray.push(mainImg.attr('src'));
swapImg.fadeIn(2000);
mainImg.fadeOut(2000, function() {
// put the now invisible image in the back
// to be used as the swap image next time
swapImg.insertAfter(mainImg);
// do it again
swapImage();
});
}
loadImages();
swapImage();
JSFiddle Demo: https://jsfiddle.net/ttbpbj2v/
Upvotes: 0