I'm learning JavaScript and I want to do this exercise in which I want to generate and show random images one by one with the interval of 1 second and 4 images in one row and total 3 rows and 12 images and once this cycle completes it must repeat again with a different images sequence below is the code which I write so far but it generates all images at once
HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Random Image Generator</title>
<script src="main.js"></script>
</head>
<body onload="imageTimeOut();" style="max-width: 400px;">
<h2 style="color: blue">Random Image Generator</h2>
<br>
<span id="result"> </span>
</body>
</html>
JavaScript
var imgTimer;
function imageTimeOut(){
imgTimer = setTimeout(getRandomImage, 1000);
}
function getRandomImage() {
//declare an array to store the images
var randomImage = new Array();
//insert the URL of images in array
randomImage[0] = "images/1.png";
randomImage[1] = "images/2.png";
randomImage[2] = "images/3.png";
randomImage[3] = "images/4.png";
randomImage[4] = "images/5.png";
randomImage[5] = "images/6.png";
randomImage[6] = "images/7.png";
randomImage[7] = "images/8.png";
randomImage[8] = "images/9.png";
randomImage[9] = "images/10.png";
randomImage[10] = "images/11.png";
randomImage[11] = "images/12.png";
for (let i = 0; i < 12; i ) {
//generate a number and provide to the image to generate randomly
var number = Math.floor(Math.random() * randomImage.length);
//print the images generated by a random number
document.getElementById("result").innerHTML = '<img src="' randomImage[number] '" style="width:100px" />';
}
}
CodePudding user response:
I would split this up a bit.
Part 1: Layout
To get 3 rows with 4 images per row, I would use CSS grid.
You can declare display: grid;
on your <span id="result">
element. This will declare a grid container for the content you want to display.
Then you can also declare grid-template-columns: repeat(4, 1fr)
to get 4 even responsive columns.
This will make sure you get a 3x4 grid for your 12 images.
If you want to set some space between the images in the grid, grid-gap
is nice for this. Here is a sample of this:
#result {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-gap: 20px;
}
Part 2: Randomize the image list
You can make a small utility shuffle function (e.g. Fisher-Yates algorithm).
/**
* @description
* shuffles an array of strings
* with the Fisher-Yates algorithm
*
* @param {string[]} array - array of image sources
* @returns {string[]} - shuffled array copy of image sources
*/
const shuffleArray = (array) => {
const _arrCopy = [...array];
for (let i = _arrCopy.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i 1));
[_arrCopy[i], _arrCopy[j]] = [_arrCopy[j], _arrCopy[i]];
}
return _arrCopy;
};
Then you can pass the list of images to this function when you are ready to reset the list.
Part 3: Create DOM functions with timer
See the runnable snippet below for this code.
// START: dummy data -------------------------------
const base = "https://images.dog.ceo/breeds";
const twelveImages = [
`${base}/terrier-australian/n02096294_3704.jpg`,
`${base}/terrier-australian/n02096294_8531.jpg`,
`${base}/terrier-bedlington/n02093647_930.jpg`,
`${base}/terrier-border/n02093754_1722.jpg`,
`${base}/terrier-border/n02093754_6082.jpg`,
`${base}/terrier-cairn/n02096177_1569.jpg`,
`${base}/terrier-cairn/n02096177_2703.jpg`,
`${base}/terrier-cairn/n02096177_2913.jpg`,
`${base}/terrier-cairn/n02096177_9528.jpg`,
`${base}/terrier-dandie/n02096437_290.jpg`,
`${base}/beagle/1271553739_Milo.jpg`,
`${base}/cotondetulear/100_2013.jpg`
];
// END: dummy data ---------------------------------
/**
* @description
* shuffles an array of strings
* with the Fisher-Yates algorithm
*
* @param {string[]} array - array of image sources
* @returns {string[]} - shuffled array copy of image sources
*/
const shuffleArray = (array) => {
const _copy = [...array];
for (let i = _copy.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i 1));
[_copy[i], _copy[j]] = [_copy[j], _copy[i]];
}
return _copy;
};
// --------------------------------------------
/**
* @description
* creates a new image element and appends it inside the given wrapper
*
* @param {HTMLElement} wrapper - wrapper to append images to
* @param {number} imageIndex - current image index
* @param {string} imageSrc - image source to use
* @returns {void}
*/
const appendNewImage = (wrapper, imageIndex, imageSrc) => {
// create image element
const img = document.createElement("img");
// set image source
img.src = imageSrc;
// append image to wrapper
wrapper.append(img);
};
// run image generator program
const run = () => {
let idx = 0;
let images = shuffleArray(twelveImages);
setInterval(() => {
// select result wrapper
const wrapper = document.getElementById("result");
// if we've reached the end, do a reset
if (idx === images.length) {
// remove images from wrapper
wrapper.innerHTML = "";
// reshuffle images
images = shuffleArray(twelveImages);
// reset counter index
idx = 0;
}
appendNewImage(wrapper, idx, images[idx]);
// increment image index
idx = 1;
}, 1000);
};
// start it
run();
body {
padding: 0px 40px;
}
#result {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-gap: 20px;
}
/*
NOTE:
This is outside the scope of your question,
but please note that this image CSS is just
dummy css for this stackoverflow snippet.
You will need to adjust this image CSS
to account for different viewports
and whatever aspect ratios your images have.
Ideally you can use responsive images.
SEE: https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images
*/
img {
width: 100%;
height: 250px;
object-fit: cover;
box-shadow: 2px 1px 1px #eee;
transition: transform 250ms;
border-radius: 5px;
}
img:hover {
transform: scale(1.05);
}
<h2 style="color: blue">Random Image Generator</h2>
<span id="result"></span>
CodePudding user response:
It's difficult to understand what you're really trying to accomplish. Perhaps you should really just shuffle your array, and use setInterval
:
//<![CDATA[
/* js/external.js */
let doc, htm, bod, nav, M, I, mobile, S, Q, hC, aC, rC, tC, shuffle; // for use on other loads
addEventListener('load', ()=>{
doc = document; htm = doc.documentElement; bod = doc.body; nav = navigator; M = tag=>doc.createElement(tag); I = id=>doc.getElementById(id); mobile = /Mobi/i.test(nav.userAgent);
S = (selector, within)=>{
let w = within || doc;
return w.querySelector(selector);
}
Q = (selector, within)=>{
let w = within || doc;
return w.querySelectorAll(selector);
}
hC = (node, className)=>{
return node.classList.contains(className);
}
aC = (node, ...classNames)=>{
node.classList.add(...classNames);
return aC;
}
rC = (node, ...classNames)=>{
node.classList.remove(...classNames);
return rC;
}
tC = (node, className)=>{
node.classList.toggle(className);
return tC;
}
shuffle = array=>{
let a = array.slice(), i = a.length, n, h;
while(i){
n = Math.floor(Math.random()*i--); h = a[i]; a[i] = a[n]; a[n] = h;
}
return a;
}
// tiny library above - below can be put on another page using a load Event (except // end load line);
function fourImgsEvery(outputNode, imgArray, often = 1000){
const a = shuffle(imgArray), img0 = M('img'), img1 = M('img'), img2 = M('img'), img3 = M('img'); // shuffle array and make images
outputNode.appendChild(img0); outputNode.appendChild(img1); outputNode.appendChild(img2); outputNode.appendChild(img3);
let i = 0, l = imgArray.length;
return setInterval(()=>{ // returns interval so you can clear it
if(i === l)i = 0;
img0.src = a[i ]; img1.src = a[i ]; img2.src = a[i ]; img3.src = a[i ];
}, often);
}
const images = ['https://i.stack.imgur.com/tGgv6.jpg?s=128&g=1', 'https://www.gravatar.com/avatar/ee6e12042dc31b1ef27471482f9ff91f?s=96&d=identicon&r=PG&f=1',
'https://i.stack.imgur.com/R5UKi.jpg?s=128&g=1', 'https://i.stack.imgur.com/xduoU.png?s=96&g=1', 'https://www.gravatar.com/avatar/0555bd0deb416a320a0069abef08078a?s=128&d=identicon&r=PG&f=1', 'https://www.gravatar.com/avatar/f00013ceab8fb1928885c5c172fbfd4a?s=96&d=identicon&r=PG', 'https://i.stack.imgur.com/hMDvl.jpg?s=128&g=1', 'https://www.gravatar.com/avatar/6605deca5924e84df1a4847f607b87c6?s=96&d=identicon&r=PG', 'https://i.stack.imgur.com/IFOp5.jpg?s=96&g=1', 'https://i.stack.imgur.com/I4fiW.jpg?s=96&g=1', 'https://www.gravatar.com/avatar/976f07be84907aad663ce8c1c51cf5c4?s=96&d=identicon&r=PG', 'https://i.stack.imgur.com/4HovX.jpg?s=128&g=1'];
const out = I('output');
fourImgsEvery(out, images);
}); // end load
//]]>
/* css/external.css */
*{
box-sizing:border-box;
}
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8' /><meta name='viewport' content='width=device-width, height=device-height, initial-scale:1, user-scalable=no' />
<title>Random Images</title>
<link type='text/css' rel='stylesheet' href='css/external.css' />
<script src='js/external.js'></script>
</head>
<body>
<div id='output'></div>
</body>
</html>