-2

Let's say I have a folder with 10 images files and I want my vanilla JS to randomize them and produce them within a Bootstrap container on a website by making use of the grid layout. Of course, this is going to need some resizing of the images making sure that the aspect ratio is still maintained. I couldn't come up with a solution to randomize them inside a container. What I'm trying is to create something of a collage with randomization.

I saw this, but this is just uploading the file.

HTML

    <div class="container">
        <div class="masonry">
            <div class="masonry-item">
                <img class="masonry-content " src="./images/Gallery/001.JPG" />
            </div>
            <div class="masonry-item">
                <img class="masonry-content " src="./images/Gallery/002.JPG" />
            </div>
            <div class="masonry-item">
                <img class="masonry-content " src="./images/Gallery/009.JPG" />
            </div>
        </div>
    </div>

JS

function resizeMasonryItem(item){
    /* Get the grid object, its row-gap, and the size of its implicit rows */
    var grid = document.getElementsByClassName('masonry')[0],
        rowGap = parseInt(window.getComputedStyle(grid).getPropertyValue('grid-row-gap')),
        rowHeight = parseInt(window.getComputedStyle(grid).getPropertyValue('grid-auto-rows'));

    /*
    * Spanning for any brick = S
    * Grid's row-gap = G
    * Size of grid's implicitly create row-track = R
    * Height of item content = H
    * Net height of the item = H1 = H + G
    * Net height of the implicit row-track = T = G + R
    * S = H1 / T
    */
    var rowSpan = Math.ceil((item.querySelector('.masonry-content').getBoundingClientRect().height+rowGap)/(rowHeight+rowGap));

    /* Set the spanning as calculated above (S) */
    item.style.gridRowEnd = 'span '+rowSpan;

    /* Make the images take all the available space in the cell/item */
    item.querySelector('.masonry-content').style.height = rowSpan * 10 + "px";
}

/**
 * Apply spanning to all the masonry items
 *
 * Loop through all the items and apply the spanning to them using 
 * `resizeMasonryItem()` function.
 *
 * @uses resizeMasonryItem
 */
function resizeAllMasonryItems(){
    // Get all item class objects in one list
    var allItems = document.getElementsByClassName('masonry-item');

    /*
    * Loop through the above list and execute the spanning function to
    * each list-item (i.e. each masonry item)
    */
    for(var i=0;i>allItems.length;i++){
    resizeMasonryItem(allItems[i]);
    }
}

/**
 * Resize the items when all the images inside the masonry grid 
 * finish loading. This will ensure that all the content inside our
 * masonry items is visible.
 *
 * @uses ImagesLoaded
 * @uses resizeMasonryItem
 */
function waitForImages() {
    var allItems = document.getElementsByClassName('masonry-item');
    for(var i=0;i<allItems.length;i++){
    imagesLoaded( allItems[i], function(instance) {
        var item = instance.elements[0];
        resizeMasonryItem(item);
    } );
    }
}

/* Resize all the grid items on the load and resize events */
var masonryEvents = ['load', 'resize'];
masonryEvents.forEach( function(event) {
    window.addEventListener(event, resizeAllMasonryItems);
} );

/* Do a resize once more when all the images finish loading */
waitForImages();

CSS

.masonry {
    display: grid;
    grid-gap: 10px;
    grid-template-columns: repeat(auto-fill, minmax(200px,1fr));
    grid-auto-rows: 0;
}

.masonry-item {
    border-radius: 5px;
}

.masonry-item {
    background-color: #eee;
    border-radius: 5px;
    overflow: hidden;
}

.masonry-item,
.masonry-item img {
    position: relative;
}

.masonry-item:after {
    font-weight: bold;
    background-color: rgba(0, 0, 0, .5);
    content: counter(masonry);
    counter-increment: masonry;
    position: absolute;
    top: 0;
    left: 0; 
    height: 100%;
    width: 100%;
    color: white;
    display: flex;
    justify-content: center; 
    align-items: center;
    transition: all .1s ease-in;
}

.masonry-item:hover:after {
    font-size: 30px;
    background-color: rgba(0, 0, 0, .75);
}
  • 1
    Let's say, you try it first ? This is not a free coding website. Please try something before asking. If you did try something, please include you attempt. – Nicolas Aug 24 '20 at 11:36
  • store the images path in an array, [shuffle](https://stackoverflow.com/questions/6274339/how-can-i-shuffle-an-array) it, then display – Cid Aug 24 '20 at 11:37
  • @Nicolas, I added my code – Ieshaan Saxena Aug 24 '20 at 12:06
  • I tried this in a separate file it and it works fine, but something seems to be the problem when I use with a Bootstrap container. – Ieshaan Saxena Aug 24 '20 at 12:07

1 Answers1

1

You could make an array of the image URLs that you want to use, then another containing numbers from 0 up to N-1 images which can be used to access the images. You would then shuffle the index list with a function like:

function shuffle(indices) {
  indices.sort(() => Math.random() - 0.5);
}

Then you could use the (shuffled) indices to get the src attribute from the images array which you can assign to the HTML (bootstrap) elements you have specified.

Tensza
  • 213
  • 1
  • 9