dimanche 9 décembre 2018

How to make horizontal margin between images constant in mosaic

I am trying to replicate a mosaic that can be found on many webpages. While looking for solutions to my problem I came accross a very good implementation on squarespace seen at https://native-demo.squarespace.com/images-native/. I have hosted my website containing the mosaic at http://alexstiles.000webhostapp.com.

My issue is that when you resize the window the horizontal spacing between the images flucuates like it has an animation instead of staying consistient. Although it sorts itself out if you resize slowly, rapid movements can cause the margin to be to large or small. This behavior is not present in the squarespace template. How can I remove this and make the margin consistient when resizing? I have already tried using css margins instead of javascript. I have added the javascript below to help.

let mosaic = document.getElementsByClassName("mosaic")[0]; // For a single mosaic for now
let numImages = 12;
let imageTopic = "design";
let originalImageTopic = "design";
let rowWidth = 3;
let scale = 1;
let mosaicLoader = document.getElementsByClassName("loader-container")[0]
let search = document.getElementById("search");
let searchBtn = document.getElementById("search-button");
let form = document.getElementsByTagName("form")[0];

function rem(rems) {
    return rems * (16 * scale);
}

searchBtn.addEventListener("click", function(event) {
    event.preventDefault();
    searchResult(search.value);
});

search.addEventListener("click", function() {
    form.classList.add("focused");
});

search.addEventListener("blur", function() {
    form.classList.remove("focused");
});

document.onkeydown = checkKey;

function checkKey(e) {
    e = e || window.event;
    if (e.keyCode == '13' || e.which == '13' || e.key === "Enter") {
        e.preventDefault();
        searchResult(search.value);
    }
}

if (window.location.hash) {
    let hash = window.location.hash.substring(1); //Puts hash in variable, and removes the # character
    search.value = hash;
    searchResult(hash);
}

function searchResult(query) {

    // Get and set query
    query = ((query != "" && query != originalImageTopic) ? search.value : imageTopic);
    imageTopic = query;
    if (imageTopic != originalImageTopic) {
        parent.location.hash = imageTopic;
        document.getElementById("search-term").textContent = imageTopic + " pictures";
    }

    // Put up loader while fetching images

    mosaicLoader.style.display = "flex";
    
    // Remove old images

    let length = mosaic.children.length;
    while (mosaic.lastChild && length > 1) {
        mosaic.removeChild(mosaic.lastChild);
        length--;
    }

    // Create new images

    let loadedImageNum = 0

    for (let i = 0; i < numImages; i++) {
        let image = document.createElement("img");
        image.src = `https://source.unsplash.com/random?${imageTopic}/sig${i}/`;
        mosaic.appendChild(image);
    }

    // Wait for all images to load

    let loadedImages = 0;
    let image = mosaic.querySelectorAll("img");

    imageCheck = setInterval(function() {
        for (let i = 0; i < numImages; i++) {
            if (image[i].naturalHeight !== 0 && image[i].complete) {
                loadedImages++;
            }
            if (loadedImages == numImages) {
                clearInterval(imageCheck);
                // alert("Loaded!")
                
                // Lay them out

                setTimeout(imagesLoaded, 2000); // Needs some time before laying out

                // Break loop

                break;
            }
        }
    }, 200)

}

searchResult(imageTopic); // Inital images with no search query

window.onload = function() {
    windowResizeEvents();
}

window.onresize = function() {
    windowResizeEvents();
}

function windowResizeEvents() {
    imagesLoaded();
}

function mosaicCalibration() {
    let images = document.querySelectorAll(".mosaic img");
    if (window.innerWidth < 750) {
        mosaic.classList.add("column");
    } else if (window.innerWidth < 1100) {
        rowWidth = 2;
    } else {
        rowWidth = 3 // Math.round(window.innerWidth/(426 + (2/3)));
    }

    if (window.innerWidth > 750) {
        mosaic.classList.remove("column");
        for (let i = 0; i < images.length; i++) {
            images[i].style.width = `calc((100% - ${((rowWidth - 1) * 1)}rem) / ${rowWidth})`;
        }
    }
}

function imagesLoaded() {

    // Find out row width, image width, etc

    mosaicCalibration();

    // Remove loader and set height to 0 so new height can be calculated

    mosaicLoader.style.display = "none";
    mosaic.style.height = 0;

    // Define variables

    let images = document.querySelectorAll(".mosaic img");
    let row = 0;
    let rowNum = 0;

    let margin = rem(1.25);

    let imageWidth = ((mosaic.scrollWidth - (2 * margin)) / rowWidth);
    let column = [];



    for (let i = 0; i < images.length; i++) {

        images[i].style.top = i > rowWidth - 1 ? column[i-rowWidth] + margin : 0; 

        if (row < rowWidth) {
            if (window.innerWidth > 1100) {
                images[i].style.left = row * imageWidth + (row >= 1 ? row * margin : 0);
            } else {
                images[i].style.left = row * imageWidth + (row >= 1 ? (row + 0.5) * margin : 0);
            }
            row++
        } else {
            images[i].style.left = 0;
            row = 1;
            rowNum++;
        }

        if (rowNum > 0) {
            column.push(column[i-rowWidth] + images[i].scrollHeight + margin);
        } else {
            column.push(images[i].scrollHeight);
        }
    }
    mosaic.style.height = mosaic.scrollHeight;
}



Aucun commentaire:

Enregistrer un commentaire