1. 程式人生 > 實用技巧 >原生js實現瀑布流

原生js實現瀑布流

前言:

  這玩意兒大家肯定經常見到,但是應該怎麼實現的呢?現在列出來三種方式

  原始碼:(還未上傳,稍等)

第一種:通過html標籤實現,比如分3列,將資料平分為3分分別填充。

  適合:圖片高度一致。

  優點:簡單

  缺點:因為每個資料不一樣,每一列的高低可能相差比較大。

程式碼如下:

<!DOCTYPE html>
<html lang="en">

    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0"
> <title>瀑布流1</title> <link rel="stylesheet" href="1.css"> <script src="1.js"></script> </head> <body> <div id="box"> </div> </body> <script> //存放參數 let box = document.getElementById(
"box"); //元素 let width = 600; //寬度,單位px let jianJu = 6; //每列之間的間距,單位px let col = 3; //分為多少列 let dataList = [ { url: "http://pic.sc.chinaz.com/Files/pic/pic9/202007/apic26715_s.jpg", title: "1行主題", content:
"1行內容" }, { url: "http://pic2.sc.chinaz.com/Files/pic/pic9/202007/apic26552_s.jpg", title: "1行主體", content: "2行內容2行內容2行內容2行內容" }, { url: "http://pic2.sc.chinaz.com/Files/pic/pic9/202007/apic26408_s.jpg", title: "1行主題", content: "3行內容" }, { url: "http://pic.sc.chinaz.com/Files/pic/pic9/202007/apic26313_s.jpg", title: "1行主題", content: "4行內容" }, { url: "http://pic1.sc.chinaz.com/Files/pic/pic9/202007/bpic20697_s.jpg", title: "1行主題", content: "5行內容" }, { url: "http://pic1.sc.chinaz.com/Files/pic/pic9/202004/bpic20013_s.jpg", title: "2行主題", content: "1行內容" }, { url: "http://pic2.sc.chinaz.com/Files/pic/pic9/202005/apic25546_s.jpg", title: "3行主題", content: "1行內容" }, { url: "http://pic2.sc.chinaz.com/Files/pic/pic9/202005/apic25309_s.jpg", title: "4行主題", content: "1行內容" }, { url: "http://pic2.sc.chinaz.com/Files/pic/pic9/202007/apic26488_s.jpg", title: "4行主題", content: "4行內容" }, { url: "http://pic2.sc.chinaz.com/Files/pic/pic9/202007/apic26473_s.jpg", title: "超過2行的主題", content: "超過3行的內容" }, { url: "http://pic2.sc.chinaz.com/Files/pic/pic9/202007/apic26395_s.jpg", title: "其他", content: "其他" }, { url: "http://pic2.sc.chinaz.com/Files/pic/pic9/202005/apic25357_s.jpg", title: "其他", content: "其他" }, { url: "http://pic2.sc.chinaz.com/Files/pic/pic9/202005/apic25357_s.jpg", title: "其他", content: "其他" } ] </script> <script> //呼叫 aaa(box, width, col, dataList); </script> </html>
.div-class{
    float: left;
}
/*標題文字的樣式*/
.tit{   
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;

    font-weight: bold;
}
/*介紹文字的樣式*/
.con{
    
}
function aaa(ele, wid, num, arr) {
    let _this = this;
    let nData = Math.round(arr.length / num);   // 先將資料(arr)分為n(num)份
    let colWidth = wid / num;
    for (let i = 0; i < num; i++) {
        let colDiv = document.createElement('div');
        let startIndex = nData * i;         // 每份資料開始的索引
        let newData = null;
        colDiv.style.width = colWidth + "px";
        colDiv.style.marginLeft = jianJu + "px";
        colDiv.className = "div-class";
        
        if (i==num-1) {
            newData = arr.slice(startIndex, arr.length + 1);    //最後一部分資料
        } else {
            newData = arr.slice(startIndex, startIndex + nData);
        }
        for (let j = 0; j < newData.length; j++) {
            let childDiv = document.createElement("p");
            _this.pStyle(childDiv, newData[j], colWidth);
            colDiv.appendChild(childDiv);
        }
        ele.appendChild(colDiv);
    }
}

function pStyle(p, item, colWidth) {
    let img = document.createElement('img');
    let tit = document.createElement('p');
    let con = document.createElement('p');
    img.src = item.url;
    img.style.width = colWidth + 'px';
    tit.className = "tit";
    tit.innerHTML = item.title;
    con.className = "con";
    con.innerHTML = item.content;
    p.appendChild(img);
    p.appendChild(tit);
    p.appendChild(con);
}

第二種:通過css實現

  適合:文字分列

  優點:簡單

  缺點:因為圖片高低不一,頁面不一致

程式碼如下:

<!DOCTYPE html>
<html lang="en">

    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>瀑布流2</title>
        <link rel="stylesheet" href="2.css">
    </head>

    <body>

        <div class="box" style="width:600px">
            主要用於文字分列,主要用於文字分列,主要用於文字分列,主要用於文字分列
            主要用於文字分列,主要用於文字分列,主要用於文字分列,主要用於文字分列
            主要用於文字分列,主要用於文字分列,主要用於文字分列,主要用於文字分列
            <h2>主要用於文字分列,主要用於文字分列,主要用於文字分列,主要用於文字分列</h2>
            <div>
                主要用於文字分列,主要用於文字分列,主要用於文字分列,主要用於文字分列
                主要用於文字分列,主要用於文字分列,主要用於文字分列,主要用於文字分列
            </div>
        </div>

        <div class="box" style="width:600px">

        </div>

    </body>
    <script>
        //存放參數
        let box = document.getElementsByClassName("box")[1];       //元素
        let dataList = [
            {
                url: "http://pic.sc.chinaz.com/Files/pic/pic9/202007/apic26715_s.jpg",
                title: "1行主題",
                content: "1行內容"
            },
            {
                url: "http://pic2.sc.chinaz.com/Files/pic/pic9/202007/apic26552_s.jpg",
                title: "1行主體",
                content: "2行內容2行內容2行內容2行內容"
            },
            {
                url: "http://pic2.sc.chinaz.com/Files/pic/pic9/202007/apic26408_s.jpg",
                title: "1行主題",
                content: "3行內容"
            },
            {
                url: "http://pic.sc.chinaz.com/Files/pic/pic9/202007/apic26313_s.jpg",
                title: "1行主題",
                content: "4行內容"
            },
            {
                url: "http://pic1.sc.chinaz.com/Files/pic/pic9/202007/bpic20697_s.jpg",
                title: "1行主題",
                content: "5行內容"
            },
            {
                url: "http://pic1.sc.chinaz.com/Files/pic/pic9/202004/bpic20013_s.jpg",
                title: "2行主題",
                content: "1行內容"
            },
            {
                url: "http://pic2.sc.chinaz.com/Files/pic/pic9/202005/apic25546_s.jpg",
                title: "3行主題",
                content: "1行內容"
            },
            {
                url: "http://pic2.sc.chinaz.com/Files/pic/pic9/202005/apic25309_s.jpg",
                title: "4行主題",
                content: "1行內容"
            },
            {
                url: "http://pic2.sc.chinaz.com/Files/pic/pic9/202007/apic26488_s.jpg",
                title: "4行主題",
                content: "4行內容"
            },
            {
                url: "http://pic2.sc.chinaz.com/Files/pic/pic9/202007/apic26473_s.jpg",
                title: "超過2行的主題",
                content: "超過3行的內容"
            },
            {
                url: "http://pic2.sc.chinaz.com/Files/pic/pic9/202007/apic26395_s.jpg",
                title: "其他",
                content: "其他"
            },
            {
                url: "http://pic2.sc.chinaz.com/Files/pic/pic9/202005/apic25357_s.jpg",
                title: "其他",
                content: "其他"
            },
            {
                url: "http://pic2.sc.chinaz.com/Files/pic/pic9/202005/apic25357_s.jpg",
                title: "其他",
                content: "其他"
            }
        ]
    </script>
    <script>
        for (let a = 0; a < dataList.length; a++) {
            var img = document.createElement("img");
            img.src = dataList[a].url;

            box.appendChild(img);
        }
    </script>

</html>
*{
    margin: 0;
    padding: 0;
}
.box{
    -webkit-column-count: 3; /* Chrome, Safari, Opera */
    -moz-column-count: 3; /* Firefox */
    column-count: 3;    /*建立多列*/

    -webkit-column-gap: 10px; /* Chrome, Safari, Opera */
    -moz-column-gap: 10px; /* Firefox */
    column-gap: 10px;      /*列與列間的間隙*/

    -webkit-column-rule-style: solid; /* Chrome, Safari, Opera */
    -moz-column-rule-style: solid; /* Firefox */
    column-rule-style: solid;   /*列與列間的邊框樣式*/
    -webkit-column-rule-width: 1px; /* Chrome, Safari, Opera */
    -moz-column-rule-width: 1px; /* Firefox */
    column-rule-width: 1px;
    -webkit-column-rule-color: lightblue; /* Chrome, Safari, Opera */
    -moz-column-rule-color: lightblue; /* Firefox */
    column-rule-color: lightblue;

    -webkit-column-width: 100px; /* Chrome, Safari, Opera */
    column-width: 100px;    /*指定列的寬度*/
}
h2{
    -webkit-column-span: all; /* Chrome, Safari, Opera */
    column-span: all;       /*指定元素跨越多少列*/
}
img{
    width: 100%;
}

第三種:通過js實現,檢測每一列的高度,然後選擇最低的插入資料

  適合:相容

  優點:不會出現每列高度差很多的情況

  缺點:能耗高,資料多的話效率慢

程式碼如下:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>瀑布流3</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        .tit {
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;

            font-weight: bold;
        }

        .con {

        }
    </style>
    <script src="3.js"></script>
</head>

<body>
    <div id="waterFallBox">

    </div>
</body>

<script>
    // 分為N列
    // 每列的高度為 heightList = [100, 200, 300, 400, 200, 400.....]
    //  每次插入前,選出最低的一列
    //  然後插入
    //  最後更新陣列資訊,重複以上步驟

    let boxWidth = 600;     //外層div的寬度
    let N = 3;              //分為N列
    let mar = 5;           //列與列之間的寬度
    let round = {
        is: true,            //是否圓角
        content: "5px"       //設定圓角(is為true時生效)
    };
    let dataList = [        //需要填充的資料
        {
            url: "http://pic.sc.chinaz.com/Files/pic/pic9/202007/apic26715_s.jpg",
            title: "1行主題",
            content: "1行內容"
        },
        {
            url: "http://pic2.sc.chinaz.com/Files/pic/pic9/202007/apic26552_s.jpg",
            title: "1行主體",
            content: "2行內容2行內容2行內容2行內容"
        },
        {
            url: "http://pic2.sc.chinaz.com/Files/pic/pic9/202007/apic26408_s.jpg",
            title: "1行主題",
            content: "3行內容"
        },
        {
            url: "http://pic.sc.chinaz.com/Files/pic/pic9/202007/apic26313_s.jpg",
            title: "1行主題",
            content: "4行內容"
        },
        {
            url: "http://pic1.sc.chinaz.com/Files/pic/pic9/202007/bpic20697_s.jpg",
            title: "1行主題",
            content: "5行內容"
        },
        {
            url: "http://pic1.sc.chinaz.com/Files/pic/pic9/202004/bpic20013_s.jpg",
            title: "2行主題",
            content: "1行內容"
        },
        {
            url: "http://pic2.sc.chinaz.com/Files/pic/pic9/202005/apic25546_s.jpg",
            title: "3行主題",
            content: "1行內容"
        },
        {
            url: "http://pic2.sc.chinaz.com/Files/pic/pic9/202005/apic25309_s.jpg",
            title: "4行主題",
            content: "1行內容"
        },
        {
            url: "http://pic2.sc.chinaz.com/Files/pic/pic9/202007/apic26488_s.jpg",
            title: "4行主題",
            content: "4行內容"
        },
        {
            url: "http://pic2.sc.chinaz.com/Files/pic/pic9/202007/apic26473_s.jpg",
            title: "超過2行的主題",
            content: "超過3行的內容"
        },
        {
            url: "http://pic2.sc.chinaz.com/Files/pic/pic9/202007/apic26395_s.jpg",
            title: "其他",
            content: "其他"
        },
        {
            url: "http://pic2.sc.chinaz.com/Files/pic/pic9/202005/apic25357_s.jpg",
            title: "其他",
            content: "其他"
        },
        {
            url: "https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=2760607627,944470302&fm=26&gp=0.jpg",
            title: "其他",
            content: "其他"
        }
    ]

    window.onload = function () {
        this.appendChild();
    }        
</script>

</html>

function appendChild() {
    let box = document.getElementById("waterFallBox");      
    for (let i = 0; i < N; i++) {                   //根據需要生成N列,然後裝飾一下
        let childBox = document.createElement("div");       
        childBox.className = 'water-fall' + i;
        childBox.style.width = boxWidth/N + 'px';
        childBox.style.float = "left"; 
        childBox.style.marginLeft = mar + 'px';
        childBox.style.marginRight = mar + 'px';

        box.appendChild(childBox);
    }
    for (let j = 0; j < dataList.length; j++) {         //每次填充一個數據就檢測一次每一列的高度,找出最低的填充
        this.imgNodes(dataList[j]);
    }
}
function imgNodes(imgData) {
    let heightList = [];
    let minHeight = Infinity;
    let minIndex = 0;
    let createImgNode = null;
    let chooseNode = null;
    let nodeList = [];
    for (let i = 0; i < N; i++) {
        let node = document.getElementsByClassName('water-fall' + i)[0];
        nodeList.push(node);
        heightList.push(node.clientHeight);
    }

    for (let j = 0; j < heightList.length; j++) {       //找出最低列
        if (minHeight > heightList[j]) {
            minHeight = heightList[j];
            minIndex = j;
        }
    }
    //填充資料
    createImgNode = document.createElement('img');
    createTitNode = document.createElement('p');
    createContNode = document.createElement('p');
    createImgNode.src = imgData.url;
    createImgNode.style.width = boxWidth/N + 'px';
    if(round.is){
        createImgNode.style.borderRadius = round.content;
    }
    createTitNode.innerHTML = imgData.title;
    createTitNode.className = "tit";
    createContNode.innerHTML = imgData.content;
    createContNode.className = "con";
    
    nodeList[minIndex].appendChild(createImgNode);
    nodeList[minIndex].appendChild(createTitNode);
    nodeList[minIndex].appendChild(createContNode);
}