前端實現瀑布流的方法彙總 (╥╯﹏╰╥)ง曾經被難倒過。。。

方法總結:

方法一:純CSS佈局

缺點:
每個item是從上到下排列的。如果需要動態加載item,(⊙o⊙)…那真是糟糕透頂!
這個就瞭解瞭解,實際項目中不會這樣寫的。
在這裏插入圖片描述

方法二:JS計算位置

利用絕對定位absolute,通過JS計算每個item的的topleft

實際項目中圖片的寬高一般是由後端返回過來。這樣前端就不需要計算圖片寬高,用戶體驗會更好!
總之,具體問題具體分析,萬一後端沒返回寬高的勒 (︶︹︺)
在這裏插入圖片描述

方法三: 使用別人寫的插件

方法1.1:multi-column多列布局瀑布流

演示代碼:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>multi-columns瀑布流佈局</title>
    <style>
        .container {
            margin: 0 auto;
            width: 1000px;
            column-count: 5; /* 列數 */
            column-gap: 20px; /* 列間距 */
        }
        .item {
            margin-bottom: 10px;
            /* 防止多列布局,分頁媒體和多區域上下文中的意外中斷 */
            break-inside: avoid;
        }
        .item img{
            width: 100%;
            height:100%;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="item">
            <img  src="img/bg1.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg2.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg3.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg4.jpeg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg5.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg6.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg7.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg8.jpeg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg9.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg10.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg11.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg12.jpg" alt="" />
        </div>
    </div>
</body>

</html>

方法1.2:Flex彈性佈局瀑布流

演示代碼:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Flexbox瀑布流佈局</title>
    <style>
        .wrapper{
            display: flex;
            flex-direction: row; /* 每列container 水平排列*/
            justify-content: space-between; /* 兩端對齊,間隔相等*/
            margin: 0 auto;   /* 整體居中 */
            width:1000px;
        }
        .container{
            width:240px;
        }
        .item{
            margin-bottom:10px;
        }
        .item img{
            width:100%;
        }

    </style>
</head>
<body>
    <div class="wrapper">
        <div class="container">
            <div class="item">
                <img  src="img/bg1.jpg" alt="" />
            </div>
            <div class="item">
                <img  src="img/bg2.jpg" alt="" />
            </div>
            <div class="item">
                <img  src="img/bg3.jpg" alt="" />
            </div>
        </div>
        <div class="container">
            <div class="item">
                <img  src="img/bg4.jpeg" alt="" />
            </div>
            <div class="item">
                <img  src="img/bg5.jpg" alt="" />
            </div>
            <div class="item">
                <img  src="img/bg6.jpg" alt="" />
            </div>
        </div>
        <div class="container">
            <div class="item">
                <img  src="img/bg7.jpg" alt="" />
            </div>
            <div class="item">
                <img  src="img/bg8.jpeg" alt="" />
            </div>
            <div class="item">
                <img  src="img/bg9.jpg" alt="" />
            </div>
        </div>
        <div class="container">
            <div class="item">
                <img  src="img/bg10.jpg" alt="" />
            </div>
            <div class="item">
                <img  src="img/bg11.jpg" alt="" />
            </div>
            <div class="item">
                <img  src="img/bg12.jpg" alt="" />
            </div>
        </div>
        
    </div>
</body>
</html>

方法2.1:原生JS瀑布流

實際項目中需要根據具體情況做相應的改動
大致情況有:

  • 瀑布流整體的寬度(下面的演示代碼寬度爲全屏)
  • 內部item元素的高度(有些項目item裏不單單就是一張圖片,還有文本。下面的演示代碼只含一張圖片)
  • 實際請求數據時,圖片還沒加載完就執行js,導致獲取的寬高都爲0;需要利用img.onload來判斷圖片是否加載完畢,再執行位置的計算
  • css動畫效果

演示代碼:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>JS實現瀑布流1</title>
    <!-- 樣式部分 -->
    <style>
        .container{
            position:relative;
        }
        .item{
            overflow: hidden;
            position: absolute;
        }
        .item img {
            width: 95%;
        }
    </style>
</head>
<body>
    <!-- html 部分 -->
    <div id="container">
        <div class="item">
            <img  src="img/bg1.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg2.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg3.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg4.jpeg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg5.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg6.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg7.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg8.jpeg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg9.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg10.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg11.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg12.jpg" alt="" />
        </div>
    </div>
    <!-- js 部分 -->
    <script>
        // 封裝成一個函數
        function waterFall() {
            var container = document.getElementById('container');
            var items = container.children;
            var columns = 5; //5列

            //根據屏幕寬度和設定的列數, 計算出實際item的寬度
            var pageWidth = getClient().width;
            var itemWidth = parseInt(pageWidth/columns); 

            // 存儲每列當前的高度
            var arr = []; 

            for (var i = 0; i < items.length; i++) {
                // 設置每個item的寬度
                items[i].style.width=itemWidth+'px';

                // 根據實際圖片的寬高比列 計算出實際item的高度
                var height = items[i].querySelector("img").height;
                var width = items[i].querySelector("img").width;
                var bi = itemWidth/width;  //獲取縮小的比值
                var itemHeight = parseInt(height*bi); //圖片的高度*比值 = item的高度
                
                // 第一行,item的top都爲0,特殊處理
                if (i < columns) {
                    items[i].style.top = 0;
                    items[i].style.left = itemWidth * i + 'px';
                    arr.push(itemHeight);

                } else {
                    // 其他行:通過尋找arr數組裏的最小高度,來計算item的位置

                    // 找到arr數組中最小高度和它的索引
                    var minHeight = arr[0];
                    var index = 0;
                    for (var j = 0; j < arr.length; j++) {
                        if (minHeight > arr[j]) {
                            minHeight = arr[j];
                            index = j;
                        }
                    }
                    // 設置該item的位置
                    // top值就是最小列的高度 
                    items[i].style.top = arr[index] + 'px';
                    // left值就是最小列距離左邊的距離
                    items[i].style.left = items[index].offsetLeft + 'px';

                    // 修改最小列的高度 
                    // 最小列的高度 = 當前自己的高度 + 拼接過來的高度 
                    arr[index] = arr[index] + itemHeight;
                }
            }
        }
     
        // 獲取屏幕寬高  clientWidth 處理兼容性 
        function getClient() {
            return {
                width: window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth,
                height: window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight
            }
        }
        // 返回垂直方向滾動的像素  scrollTop兼容性處理 
        function getScrollTop() {
            return window.pageYOffset || document.documentElement.scrollTop;
        }

        window.onload = function() {
            // 一進來就調用一次
            waterFall();
        };

        // 頁面尺寸改變時實時觸發waterFall()函數,重新排列
        window.onresize = function() {
            waterFall();
        };

        // 當滾動到最後item的時候,模擬ajax請求獲取數據,動態添加到html中
        window.onscroll = function() {
            var container = document.getElementById('container');
            var items = container.children;
            // 當屏幕高度+滾動高度 >= 最後一個item的距外層container的高度, 即滾動到最後了
            if (getClient().height + getScrollTop() >= items[items.length - 1].offsetTop) {
                // 模擬 ajax 獲取的數據 
                var datas = [
                    "img/bg13.jpg",
                    "img/bg14.jpg",
                    "img/bg15.jpg",
                    "img/bg16.jpg",
                    "img/bg17.jpg",
                    "img/bg1.jpg",
                    "img/bg2.jpg",
                    "img/bg3.jpg",
                    "img/bg4.jpeg",
                ];
                // 循環獲取到的數據,添加到hmtl中
                for (var i = 0; i < datas.length; i++) {
                    var div = document.createElement("div");
                    div.className = "item";
                    div.innerHTML = '<img src="' + datas[i] + '" alt="">';
                    container.appendChild(div);
                };

                // 重新排列一下
                waterFall();
            }

        };
    
    </script>
</body>
</html>

方法2.1:JQ瀑布流

實際項目中需要根據具體情況做相應的改動
大致情況有:

  • 瀑布流整體的寬度(下面的演示代碼寬度爲全屏)
  • 內部item元素的高度(有些項目item裏不單單就是一張圖片,還有文本。下面的演示代碼只含一張圖片)
  • 實際請求數據時,圖片還沒加載完就執行js,導致獲取的寬高都爲0;需要利用img.onload來判斷圖片是否加載完畢,再執行位置的計算
  • css動畫效果
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>JQ實現瀑布流佈局</title>
    <style>
        .container{
            width: 100%;
            position:relative;
        }
        .item{
            overflow: hidden;
            position: absolute;
        }
        .item img {
            width: 95%;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="item">
            <img  src="img/bg1.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg2.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg3.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg4.jpeg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg5.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg6.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg7.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg8.jpeg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg9.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg10.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg11.jpg" alt="" />
        </div>
        <div class="item">
            <img  src="img/bg12.jpg" alt="" />
        </div>
    </div>
    <script src="js/jquery-3.4.1.min.js"></script>
    <script>
    
        function waterFall() {
            // 1- 確定圖片的寬度 - 滾動條寬度
            var pageWidth = getClient().width-8;
            var columns = 5; //3列
            var itemWidth = parseInt(pageWidth/columns); //得到item的寬度
            $(".item").width(itemWidth); //設置到item的寬度
            
            var arr = [];

            $(".container .item").each(function(i){
                var height = $(this).find("img").height();
                var width = $(this).find("img").width();
                var bi = itemWidth/width; //獲取縮小的比值
                var boxheight = parseInt(height*bi); //圖片的高度*比值 = item的高度

                if (i < columns) {
                    // 2- 確定第一行
                    $(this).css({
                        top:0,
                        left:(itemWidth) * i
                    });
                    arr.push(boxheight);

                } else {
                    // 其他行
                    // 3- 找到數組中最小高度  和 它的索引
                    var minHeight = arr[0];
                    var index = 0;
                    for (var j = 0; j < arr.length; j++) {
                        if (minHeight > arr[j]) {
                            minHeight = arr[j];
                            index = j;
                        }
                    }

                    // 4- 設置下一行的第一個盒子位置
                    // top值就是最小列的高度 
                    $(this).css({
                        top:arr[index],
                        left:$(".container .item").eq(index).css("left")
                    });

                    // 5- 修改最小列的高度 
                    // 最小列的高度 = 當前自己的高度 + 拼接過來的高度
                    arr[index] = arr[index] + boxheight;
                }
            });
        }

        //clientWidth 處理兼容性
        function getClient() {
            return {
                width: window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth,
                height: window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight
            }
        }

        // 返回垂直方向滾動的像素  scrollTop兼容性處理 
        function getScrollTop() {
            return window.pageYOffset || document.documentElement.scrollTop;
        }

        // 頁面尺寸改變時實時觸發
        window.onresize = function() {
            //重新定義瀑布流
            waterFall();
        };

        //初始化
        window.onload = function(){
            //實現瀑布流
            waterFall();
        }

          // 當滾動到最後item的時候,模擬ajax請求獲取數據,動態添加到html中
          window.onscroll = function() {
            var container = $(".container");
            var items =$(".container .item");
            // 當屏幕高度+滾動高度 >= 最後一個item的距外層container的高度, 即滾動到最後了
            if (getClient().height + getScrollTop() >= items[items.length - 1].offsetTop) {
                // 模擬 ajax 獲取的數據 
                var datas = [
                    "img/bg13.jpg",
                    "img/bg14.jpg",
                    "img/bg15.jpg",
                    "img/bg16.jpg",
                    "img/bg17.jpg",
                    "img/bg1.jpg",
                    "img/bg2.jpg",
                    "img/bg3.jpg",
                    "img/bg4.jpeg",
                ];
                // 循環獲取到的數據,添加到hmtl中
                for (var i = 0; i < datas.length; i++) {
                    container.append(`<div class="item"><img src=${datas[i]}></div>`);
                };

                // 重新排列一下
                waterFall();
            }

        };
    
    </script>
</body>
</html>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章