Home > Back-end >  Pick random index and change till all unique are done then restart
Pick random index and change till all unique are done then restart

Time:08-26

I have image gallery with 6 image slot and i have a array with n no of image object like this

          "src" : {
            "1x" : "/clients/Logo-1.png",
            "2x" : "/clients/[email protected]",
            "3x" : "/clients/[email protected]"
          },
          "alt" : "xyz"
        } 

what i want is to show random 6 image from array and then every 5 sec randomly one slot need to be change and get update with a new unique image which must not be in first 6 slot and then after finishing all it should continue the 5 sec change with a new unique image which must not be in those 6 slot.

what i have tried

           let randomList = this.shuffleArray(this.LogosListObj);
           let FirstSixImg = randomList.slice(0, 6);
           let LeftAllImg = randomList.slice(6   1);
           let RandomIndex = this.randomNoRepeats([0,1,2,3,4,5])
           let RandomSecoundImg = this.randomNoRepeats(Array.apply(null, new Array(LeftAllImg.length)).map(function(el, i) {return i}))
           let RandomFirstImg = this.randomNoRepeats(Array.apply(null, new Array(FirstSixImg.length)).map(function(el, i) {return i}))
           this.ImageToShowList = [...FirstSixImg];
           let checkArr = [];
           let checkArr2 = [];
           let flag = false;
           let index,secndIndex,thirdIndex;
           const LogoChange = (arr) =>{
             if(!flag) {
                secndIndex = RandomSecoundImg();
                  console.log('1st',secndIndex)
                if(checkArr.indexOf(secndIndex) == -1) {
                    index = RandomIndex();
                    checkArr.push(secndIndex)
                    ctl.ImageToShowList[index] =  {};
                    ctl.ImageToShowList[index] = LeftAllImg[secndIndex];
                    Vue.set(ctl.ImageToShowList, index, LeftAllImg[secndIndex])
                    ctl.PreviousImgObj = {...LeftAllImg[secndIndex]};
                } else {
                  flag = true;
                  checkArr = [];
                }
             }
             if(flag) {
                 thirdIndex = RandomFirstImg();
                  console.log('2nd',thirdIndex)
               if(checkArr2.indexOf(thirdIndex) == -1) {
                  checkArr2.push(thirdIndex)
                  ctl.ImageToShowList[thirdIndex] =  {};
                  ctl.ImageToShowList[thirdIndex] = FirstSixImg[thirdIndex];
                  Vue.set(ctl.ImageToShowList, thirdIndex, FirstSixImg[thirdIndex])
                  ctl.PreviousImgObj = {...FirstSixImg[thirdIndex]};
                }else {
                  flag = false;
                  checkArr2 = [];
                  LogoChange();
                }
             }
            
            }
           
           setInterval(()=>{ 
             LogoChange();
          }, 1000);

where randomNoRepeats is

randomNoRepeats : (array) => {
        var copy = array.slice(0);
        return function() {
          if (copy.length < 1) { copy = array.slice(0); }
          var index = Math.floor(Math.random() * copy.length);
          var item = copy[index];
          copy.splice(index, 1);
          return item;
        };

and shuffleArray is

shuffleArray : (array) => {
          for (let i = array.length - 1; i > 0; i--) {
            const j = Math.floor(Math.random() * (i   1));
            const temp = array[i];
            array[i] = array[j];
            array[j] = temp;
          }
          return array; 
      },

this.ImageToShowList is used in html part to display Any help with logic or change will be appreciate.

CodePudding user response:

here is a simple script. you will need the following

  • pool this will contain all possible values you would like
  • single function to update the show array

fiddle preview

I have my example fiddle here, but this is the breakdown:

Your data would look something like this:

let galleryPool = [
    {
        "src" : {
            "1x" : "/clients/Logo-1.png",
            "2x" : "/clients/[email protected]",
            "3x" : "/clients/[email protected]"
        },
        "alt" : "xyz",
        "color": "red"
    },
    ...
]

(I added a color property so you could see the changes since I don't actually have any images.)

The first thing I do is drop in my handy-dandy Fisher–Yates shuffle, since this is a great way to get a random element out of an array.

Array.prototype.shuffle = function() {
    let currentIndex = this.length,  randomIndex;
  while (currentIndex != 0) {
    randomIndex = Math.floor(Math.random() * currentIndex);
    currentIndex--;
    [this[currentIndex], this[randomIndex]] = [this[randomIndex], this[currentIndex]];
  }

  return this;
}

I initialize the gallery first, and set up the 5-second timeout to change images in the gallery.

let displayedGallery = []
initialGallerySetup();

function initialGallerySetup() {
    let galleryContainer = document.getElementById("gallery-container")
  galleryPool.shuffle()
  displayedGallery = galleryPool.splice(0, 6)
  for(let index = 0; index < displayedGallery.length; index  ) {
    let data = displayedGallery[index]
    galleryContainer.appendChild(generateGalleryItem(data))
  }
  galleryTickUpdate()
}

this function makes an img dom element I can then add to the container. I'm using your src here but you can change whatever values in here to alter how all of the images in the gallery are displayed.

function generateGalleryItem(data) {
  let item = document.createElement("img")
  item.style.backgroundColor = data.color
  item.src = data.src[0]
  item.className = "gallery-item"
  return item
}

This function calls itself every 5 seconds, and will pick a random item from the gallery to swap with another item not currently displayed.

function galleryTickUpdate() {
  setTimeout(() => {
    let randomIndex = Math.floor(displayedGallery.length * Math.random())
    swapItemAtIndex(randomIndex)
    galleryTickUpdate()
  },5000)
}

Here's the magic. I grab the randomly chosen item out of the displayed gallery items, pick a new item from the unused gallery pool items, put the old one back in the pool and the new one gets pushed back into the gallery display in the same spot.

function swapItemAtIndex(index) {
    let galleryContainer = document.getElementById("gallery-container")
    let displaySlot = galleryContainer.children[index]
    let returning = displayedGallery[index]
    galleryPool.shuffle()
    let newDisplay = galleryPool.pop();
    displayedGallery[index] = newDisplay
    galleryPool.push(returning)
    galleryContainer.insertBefore(generateGalleryItem(newDisplay), displaySlot)
    galleryContainer.removeChild(displaySlot)
}

If you want to enforce running through the whole array, just check when the galleryPool array is empty, then repopulate it and re-run the init function. Otherwise, this will happily run forever.

  • Related