原生JS實現瀑布流布局


瀑布流,又稱瀑布流式布局。是比較流行的一種網站頁面布局,視覺表現為參差不齊的多欄布局,隨着頁面滾動條向下滾動,這種布局還會不斷加載數據塊並附加至當前尾部。

1、首先瀑布流所有的圖片應該保持寬度一致,高度是由內容決定。

通過定位的方式是我們實現瀑布流的最基本的原理,只要我們動態的設置它的top值、left值,就能讓它排列。

2、定位后確定瀏覽器顯示區域內,一行能放多少列圖片盒子。

  • 獲取頁面的寬度
  • 獲取圖片盒子的寬度
  • 顯示的列數 = 頁面寬度/圖片盒子寬度
  • column = pageWidth / itemWidth

3、為了美觀我們可以加上一個空隙

  • 顯示的列數 = 頁面寬度/(圖片盒子寬度+間隙);
  • column = pageWidth / (itemWidth + gap);

4、 確定列數之后,排列第一行

  • 下面還有很多圖片盒子,我們先要排列第1行,所以在for循環里就要判斷一下,當i(所有圖片盒子的索引) < column(顯示列數)的時候,說明在第1行;
  • 知道在第1行之后,動態設置每個圖片盒子的left值就能排好第1行。
  • left = i * ( itemWidth + gap );

5、第1行排列好之后,獲取第1行所有圖片盒子的高度

  • 需要定義一個數組arr,將獲取到的高度存在數組中,因為第2行排列的時候需要考慮top值,此時只能根據第1行圖片盒子的高度來設置;
  • 獲取圖片高度的時候要注意,程序必須寫在入口函數onload里面,因為圖片的加載特性是:等頁面都加載完之后才去請求加載,所以不寫在入口函數里可能會出現高度獲取不到的情況。

6、排列第2行

  • 獲取到剛剛數組中,高度最小的那一列,將第2行的第1個圖片盒子放置在它的下方;
  • 此時的left值就是高度最小列的offsetLefttop值就是:第1行高度最小列的高度(為了布局美觀可以加上上下間隙gap)。
  • 記錄下高度最小列的索引index,后面計算會用到;
  • 設置完成之后,會發現后面所有的圖片都疊在這個高度最小列的下面,原因就是此時的最小列高度沒有改變,應該加上下面圖片的高度,得出一個新高度。

7、改變最小列當前高度

  • 此時的這一列高度其實已經發生改變了,所以需要將新高度賦值給數組
  • 當前高度最小列的高度 = 當前高度最小列的高度 + 間隙 + 下面圖片盒子的高度

8、觸發resize事件

  • 將整個設置樣式的部分封裝成一個函數,在onload里面注冊一個resize事件,只要頁面一發生改變,就觸發樣式部分的代碼。
  • 實時改變pageWidth的寬度,這樣瀑布流就會是一個響應式的效果了

9、懶加載效果

  • 目前我們用的是30張圖片,假如一個頁面中有幾百張圖片的時候,我們不可能等到它都加載完再顯示,所有這里引入一個懶加載的概念,我們規定第30張為顯示的最后一張圖片,當滾動條滾動到30張的時候,應該加載下一批圖片。
  • 即頁面可視區高度+滾動條卷去的高度 = 第30圖片的offsetTop;的時候加載下面的圖片。

代碼:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>瀑布流</title>
    <link rel="stylesheet" type="text/css" href="../css/flow.css">
    <script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script>
    <script type="text/javascript" src="../js/script.js"></script>
</head>
<body>
    <div id="main">
        <div class="box">
            <div class="pic">
                <img src="../img/food-list1.png">
            </div>
        </div>
        <div class="box">
            <div class="pic">
                <img src="../img/food-list2-1.png">
            </div>
        </div>
        .
                .
                .
        <div class="box">
            <div class="pic">
                <img src="../img/food-list2-2.png">
            </div>
        </div>
        <div class="box">
            <div class="pic">
                <img src="../img/food-list2-3.png">
            </div>
        </div>
    </div>
</body>
</html>
html部分
 
css部分
 
window.onload=function(){
    waterfall("main","box");
    var dataInt={"data":[{"src":"food-list2-1.png"},{"src":"food-list2-2.png"},{"src":"food-list2-3.png"},{"src":"food-list2-4.png"},{"src":"food-list1.png"}]};
    window.onscroll=function(){
        
        if(checkScrollSlide()){
            var oParent=document.getElementById('main');
            for(let i=0;i<dataInt.data.length;i++){
                var oBox=document.createElement("div");
                oBox.className='box';
                oParent.appendChild(oBox);
                var oPic=document.createElement("div");
                oPic.className="pic";
                oBox.appendChild(oPic);
                var oImg=document.createElement("img");
                oImg.src="../img/"+dataInt.data[i].src;
                oPic.appendChild(oImg);
            }
            waterfall("main","box");
        }
    }
}
function waterfall(parent,box){
    //獲取main下所有class為box的元素
    var oParent=document.getElementById(parent);
    var oBoxs=getByClass(oParent,box);
    //獲取列數
    var oBoxW=oBoxs[0].offsetWidth;
    // console.log(document.documentElement.clientWidth)
    var cols=parseInt(screen.availWidth/oBoxW);
    oParent.style.cssText="width:"+oBoxW*cols+"px;margin:0 auto"
    var hArr=[];//存放每列圖片高度
    for(let i=0;i<oBoxs.length;i++){
        if(i<cols){
            hArr.push(oBoxs[i].offsetHeight)
        }else{
            var minH=Math.min.apply(null,hArr);
            var index=getMinhIndex(hArr,minH);
            oBoxs[i].style.position='absolute';
            oBoxs[i].style.top=minH+'px';
            oBoxs[i].style.left=oBoxW*index+'px';
            hArr[index]+=oBoxs[i].offsetHeight;
        }
    }
}

//根據class獲取元素
function getByClass(parent,clsName){
    var boxArr=[];
    var oElements=parent.getElementsByTagName('*');
    for(let item of oElements){
        if(item.className==clsName){
            boxArr.push(item)
        }
    }
    return boxArr;
}

function getMinhIndex(arr,val){
    for (var i in arr) {
        if(arr[i]==val)
            return i;
    }
}

//檢測是否具備滾動加載數據塊的條件
function checkScrollSlide(){
    var oParent=document.getElementById('main');
    var oBoxs=getByClass(oParent,'box');
    var lastBoxH=oBoxs[oBoxs.length-1].offsetTop+parseInt(oBoxs[oBoxs.length-1].offsetHeight);
    var scrollTop=document.documentElement.scrollTop||document.body.scrollTop;
    var totalH=scrollTop+document.documentElement.clientHeight;
    return (lastBoxH<=totalH)?true:false;
}
js部分

 

效果圖:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM