BerkinAKKAYA / svelte-image-gallery

A Masonry-Like Image Container for Svelte
https://madewithsvelte.com/svelte-image-gallery
52 stars 13 forks source link

Height Balancing Option #1

Closed BerkinAKKAYA closed 2 months ago

BerkinAKKAYA commented 4 years ago

Component distributes the images to the columns according to their counts. Every column has same amount of images. But if images has very different heights or there are so many images, column heights can be very different. I tried to solve it but couldn't properly do it. Here is what i tried:

    async function Draw () {
        const images = Array.from(slotHolder.childNodes).filter(child => child.tagName === "IMG");
        columns = [...Array(columnCount).keys()].map(() => []);

        while (images.length > 0) {
            const col = ShortestColumn();
            columns[col] = [...columns[col] || [], images.pop().src];
            await new Promise(res => { setTimeout(res, 100) });
        }
    }

    function ShortestColumn() {
        const columns = document.querySelectorAll(".column");

        const ColumnHeight = index => {
            const column = columns[index];
            const content = Array.from(column.querySelectorAll("img"));
            const heights = content.map(img => img.clientHeight);
            return heights.reduce((a, b) => (a + b), 0);
        }

        let result = 0;

        for (let i=0; i<columns.length; i++) {
            if (ColumnHeight(i) < ColumnHeight(result)) {
                result = i;
            }
        }

        return result;
    }

It always adds an image to the shortest column. The drawback is that you have to wait for at least 100ms between every draw for DOM to update, so you can calculate the column's new height.