开发者问题收集

随机图像函数 Javascript

2021-04-01
92

我正在尝试编写我的第一个自定义 JavaScript 函数,但遇到了一些障碍。

我试图在我的网页上放置三个缩略图,并让我的代码从众多图像中抓取三张并在加载时显示它们。 我遇到的问题围绕着图像重复或能够处理两次选择图像的情况(这是类似的问题)。 我尝试了许多不同的条件,但似乎无法突破。

这是我的代码:

let imgThumbnails = document.querySelectorAll('.img-fluid');
let chosenNums = [];

let imgNumber = () => { //object random
    return Math.floor(Math.random() * (Object.keys(pictures).length));
}

const pictures = {
    0 : { "src" : "Images - Copy/crack_plant.jpg", "alt" : "Seedling growing through bricks"},
    1 : { "src" : "Images - Copy/desert_botanical.jpg", "alt" : "Phoenix's Desert Botanical Garden"},
    2 : { "src" : "Images - Copy/LookUp.jpg", "alt" : "Looking up through forest"},
    3 : { "src" : "Images - Copy/LookUpLeaves.jpg", "alt" : "Looking up at leaves"},
    4 : { "src" : "Images - Copy/Road_Through_Trees.jpg", "alt" : "A path covered by trees"},
    5 : { "src" : "Images - Copy/Sand.jpg", "alt" : "Tiny balls of sand formed by crabs"},
    6 : { "src" : "Images - Copy/Snow.jpg", "alt" : "Powder day at Breckenridge"},
}; // these images are hosted locally for me at the moment

//attempt 1

const imgPopulate = () => {
    imgThumbnails.forEach( a => {
        let pictureNum = imgNumber();
        while (!chosenNums.includes(pictureNum) && chosenNums.length <= 3) {
            a.src = pictures[pictureNum].src;
            chosenNums.push(pictureNum);
        }
    });
}

imgPopulate();


//attempt 2

while (chosenNums.length <= 3) {
    let pictureNum = imgNumber();
    if(chosenNums.includes() !== pictureNum) {
        for(let i = 0; i <=3; i++) {
            imgThumbnails[i].src = pictures[pictureNum].src
            chosenNums.push(pictureNum);
        }
    } 
}

//attempt 3
do {
    for(let i = 0; i <=3; i++) {
        let pictureNum = imgNumber();
            if(chosenNums.includes() !== pictureNum) {
                imgThumbnails[i].src = pictures[pictureNum].src
                chosenNums.push(pictureNum);
            } else {
                continue;
            }
    }
} while (chosenNums.length <= 3);
<!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">
    <link href="views/css/bootstrap.min.css" rel="stylesheet">
    <title>Showin Photos</title>
</head>
<body>
    <div class="container">
        <div class="row">
            <div class="col">
                <img id = "photo1" class="img-fluid" src="" alt="">
            </div>
            <div class="col">
                <img id = "photo2" class="img-fluid" src="" alt="">
            </div>
            <div class="col">
                <img id = "photo3" class="img-fluid" src="" alt="">
            </div>
        </div>
    </div>



<script src="views/js/bootstrap.min.js"></script>    
<script src="index.js"></script>
</body>
</html>

尝试: 1:这个有时有效,除非它从已经使用过的图片对象中命中一个数字。然后它只会显示一个空白的缩略图。我相信这个问题是因为它使用了 forEach。所以它只对每个项目运行一次,即使它之前被使用过,我的 while 循环也不会影响它。

2/3:我从这两次尝试中都遇到了同样的问题。这些尝试偶尔会将同一张图片用于不同的缩略图。我还收到:“未捕获的类型错误:无法设置未定义的属性‘src’”,这与“pictures[pictureNum].src”有关,但所有缩略图仍然充满了图像?!?!

如果可以提供任何帮助,无论是帮助修复此代码还是如果您有其他方法,我都应该尝试编写此代码,以便我可以尝试。 正如我所说,这是我第一次尝试自定义函数,我觉得我的视野变得狭窄,无法真正从不同角度看待它。

谢谢!

2个回答

您可以使用以下概念:

  1. 使用 Object.values 将图片转换为数组,然后对数组进行打乱。
// see shuffle options in the snippet
const data = shuffle(Object.values(pictures));
  1. 由于数据现在已打乱,只需使用 array.slice 从数组中获取前 3 个项目即可。>
const selected = data.slice(0, 3);

如果您使用 Flavios Copes 排序,则可以在一行中完成此操作随机播放:

const selected = Object.values(pictures).sort(() => Math.random() - 0.5).slice(0, 3);
const pictures = {
  0: {
    "src": "Images - Copy/crack_plant.jpg",
    "alt": "Seedling growing through bricks"
  },
  1: {
    "src": "Images - Copy/desert_botanical.jpg",
    "alt": "Phoenix's Desert Botanical Garden"
  },
  2: {
    "src": "Images - Copy/LookUp.jpg",
    "alt": "Looking up through forest"
  },
  3: {
    "src": "Images - Copy/LookUpLeaves.jpg",
    "alt": "Looking up at leaves"
  },
  4: {
    "src": "Images - Copy/Road_Through_Trees.jpg",
    "alt": "A path covered by trees"
  },
  5: {
    "src": "Images - Copy/Sand.jpg",
    "alt": "Tiny balls of sand formed by crabs"
  },
  6: {
    "src": "Images - Copy/Snow.jpg",
    "alt": "Powder day at Breckenridge"
  },
};

// shuffle array using Durstenfeld shuffle algorithm 
function shuffle(array) {
  for (let i = array.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [array[i], array[j]] = [array[j], array[i]];
  }

  return array;
}

// convert to an array and shuffle
const data = shuffle(Object.values(pictures));

// grab the first 3
const selected = data.slice(0, 3);

console.info(selected);

// one liner using Flavios Copes sort 
console.info(Object.values(pictures).sort(() => Math.random() - 0.5).slice(0, 3));
Samuel Goldenbaum
2021-04-01

好的,首先,您不需要具有数字键的对象。这本质上是一个数组。与对象相比,数组可以更简单地为您提供所需的功能。

您只需要使用 while 循环来检查它刚刚从数组中挑选的随机图像是否已经是挑选的图像,您可以通过单独存储生成的随机图像来做到这一点。

let pics = document.querySelectorAll(".img-fluid");
let chosenNums = [];

let getRandom = () => { 
    return Math.floor(Math.random() * pictures.length);
}

// An object with sequential numbers for keys is essentially an array
// so just use an Array.
const pictures = [
    { "src" : "Images - Copy/crack_plant.jpg", "alt" : "Seedling growing through bricks"},
    { "src" : "Images - Copy/desert_botanical.jpg", "alt" : "Phoenix's Desert Botanical Garden"},
    { "src" : "Images - Copy/LookUp.jpg", "alt" : "Looking up through forest"},
    { "src" : "Images - Copy/LookUpLeaves.jpg", "alt" : "Looking up at leaves"},
    { "src" : "Images - Copy/Road_Through_Trees.jpg", "alt" : "A path covered by trees"},
    { "src" : "Images - Copy/Sand.jpg", "alt" : "Tiny balls of sand formed by crabs"},
    { "src" : "Images - Copy/Snow.jpg", "alt" : "Powder day at Breckenridge"}
]; 

// Keep looping until we have 3 randoms
while(chosenNums.length < 3){
  let random = getRandom();  // Get a random
  // Check to see if the random is NOT already in the output array
  if(!chosenNums.includes(random)){
    chosenNums.push(random); // It's not so add it
  }
}

// Now that the output array has 3 randoms in it, loop over them
chosenNums.forEach(function(num, index){
  // Set up the img element corresponding to the loop index
  // with the data from the picture corresponding to the index
  // in the array of randoms
  pics[index].src = pictures[num].src;
  pics[index].alt = pictures[num].alt;  
});
<div class="container">
   <div class="row">
     <div class="col">
        <img id = "photo1" class="img-fluid">
     </div>
     <div class="col">
        <img id = "photo2" class="img-fluid">
     </div>
     <div class="col">
        <img id = "photo3" class="img-fluid">
     </div>
  </div>
</div>
Scott Marcus
2021-04-01