簡單實現一個不規則尺寸卡片自動填充佈局

要實現這樣的一個效果的, 光用css是flex或者float沒法實現的,css

要實現這樣的效果,咱們須要用到絕對定位,而後用到JavaScript,來計算每一個卡片的left和top值算法

這裏實現一個demoapp

首先建立一個卡片的容器dom

<div id="main">

 </div>

加點樣式flex

<style> * {
            margin: 0;
            padding: 0;
        }

        #main {
            width: 1000px;
            height: 800px;
            background: #ccc;
            display: flex;
            position: relative;
            padding: 10px;
            overflow: auto;
        }

        #main>div {
            outline: 1px solid #000;
            position: absolute;
        } </style>

咱們假設卡片寬度是固定的,默認爲100pxspa

隨機生成100組卡片數據code

const Container = document.getElementById("main");

        let totalWidth = Container.getBoundingClientRect().width

        const DefaultWidth = 100;


        function getRandom() {
            return Math.ceil(((Math.random()) * 50)) + 100
        }
        function Color() {
            let r = Math.ceil(Math.random() * 255);
            let g = Math.ceil(Math.random() * 255);
            let b = Math.ceil(Math.random() * 255);
            return 'rgba(' + r + ',' + g + ',' + b + ',0.8)';
        }
        let data = [];
        for (let i = 0; i < 100; i++) {
            data.push({
                height: getRandom(),
                background: Color(),
            })
        }

而後遍歷這100組數據生成卡片加入到容器中。blog

首次遍歷時,保存下每列的高度,行列信息,排序

而後第一行填滿後,剩下的行從沒列的最矮的卡片開始填充剩餘的卡片ip

以此邏輯填充完剩下的卡片。

代碼邏輯以下

/* 行列信息*/
        let rowColInfos = [];

        let currentCol = 0;
        let currentRow = 0;

        //每行信息排序一次
        let isSort = false;
        //當前行是否鋪滿標
        let mark = 0;

        const frag = document.createDocumentFragment();

        for (let d of data) {
            let div = document.createElement("div");
            div.style.width = DefaultWidth + "px";
            div.style.height = d.height + "px";
            div.style.backgroundColor = d.background;
            frag.append(div);

            //第一行,記錄當前列的初始數據
            if (currentRow === 0) {
                heightData[currentCol] = {
                    height: d.height,
                    row: currentRow,
                    col: currentCol,
                };
                div.style.left = DefaultWidth * currentCol + "px";
                div.style.top = 0;
                if (DefaultWidth * (currentCol + 1) + DefaultWidth >= totalWidth) {
                    currentRow++;
                }
                else
                    currentCol++;
            }
            else {
                //當前每列的高度,從低到高排序
                if (!isSort) {
                    heightData.sort((d1, d2) => d1.height - d2.height);
                    isSort = true;
                }

                for (let info of heightData) {
                    //取當前行數據信息給與當前卡片的位置
                    if (info.row + 1 === currentRow) {
                        div.style.left = info.col * DefaultWidth + "px";
                        div.style.top = info.height + "px";
                        info.height += d.height;
                        mark++;
                        info.row++;
                        break;
                    }
                }
                //這行填充滿了,進行下一輪填充
                if (mark === heightData.length) {
                    mark = 0;
                    isSort = false;
                    currentRow++;
                }
            }
        }
        Container.appendChild(frag);

總結

這裏簡單實現了固定寬度的卡片自動填充,若是須要擴展,好比

1.加個過渡效果,須要第一次遍歷便插入到元素中,第二次遍歷改變元素位置

2.不一樣寬度,不一樣高度的自適應,那太複雜,須要用到比較高級的算法,通常不用用到

若是有更好的方法,也可留言交流。

相關文章
相關標籤/搜索