web前端學習筆記-瀑布流的算法分析與代碼實現

瀑布流效果目前應用很普遍,像花瓣,新浪輕博,蘑菇街,美麗說等好多網站都有.也有好多支持該效果的前段框架,今天學習了一下這種效果的實現,不依賴插件,本身動手分析實現過程,爲了便於敘述清楚,分析中的一些名詞爲本身擬定,不當之處還望見諒.javascript

 

思路分析css

步驟一:構建成行元素 + 尋找新增元素追加位置html

瀑布流全部元素的寬度是固定的,咱們用瀏覽器的寬度除以每一個瀑布流塊的寬度,就是每一行可容納的瀑布流塊的個數.由於,每一個瀑布流塊的高度不一,咱們姑且把組成一行的這組元素稱爲成行元素,在成行元素放置完畢後,咱們若是要再增長一個元素,那麼它的位置應該這樣找?java

「獲取成行元素集合中高度最低的那個元素,待放置的元素的top值應該是這個最低元素的高,left值應該是這個最低元素的left值」jquery

這樣,新增的這一個元素咱們就找到了它存放的位置.這樣成行元素中的最低高度值就變爲了原來的高度+新增元素的高度.數組

 

步驟二:重複步驟一,依賴成行元素追加新元素瀏覽器

步驟一中咱們已經實現了一次成行元素追加一個新的元素,這樣新元素增長以後咱們就構建了新的成行元素,以後的操做就是在新的成行元素中追加新元素,原理同步驟一.

app

步驟三:實現滾動位置監聽,到底部時加載數據

框架

代碼實現學習

 

實現步驟一描述效果:



實現代碼

<!doctype html>
<html>
<head>
    <meta charset="UTF-8">
    <title>瀑布流效果實現</title>
    <script type="text/javascript" src="scripts/jquery-1.8.2.min.js"></script>
    <script type="text/javascript" src="scripts/jquery.easydrag.handler.beta2.js"></script>
    <script type="text/javascript"> window.onload=function(){ //獲取父級對象
            var oParent = document.getElementById("main"); //獲取父級[第一個參數]下的全部的子元素[按照第二個參數匹配]
            var aPin = getClassObject(oParent,"pin"); //獲取每個塊的寬度
            var iPinW = aPin[0].offsetWidth; // //計算每行放多少個pin(瀑布流塊)頁面的寬度/每個瀑布流塊的寬度
            var num = Math.floor(document.documentElement.clientWidth/iPinW);
            //重置父級的樣式,這樣保證圖片總體居中
 oParent.style.cssText="width:" + num*iPinW + "px;margin:0 auto;"; var compareArray = []; //將一整行的瀑布流塊的高度壓入一個數組
            for (var i = 0; i<num; i++) { compareArray[i] = aPin[i].offsetHeight; } //獲取該行瀑布流高度最低的值
            var minHeight = Math.min.apply('',compareArray); //alert(compareArray + ",min=" + minHeight);
            //獲取改行高度值最小的瀑布流塊的索引
            var minHkey = getMinHeightKey(compareArray,minHeight); //爲新增的瀑布流塊增長樣式
 aPin[num].style.position = "absolute"; aPin[num].style.top = minHeight + "px"; //設定新增長的瀑布流塊的top和left
 aPin[num].style.left =aPin[minHkey].offsetLeft + "px"; //將該索引位置的高度改變爲新增後的高度[原來瀑布流塊的高度+新增的瀑布流塊的高度]
 compareArray[minHkey] += aPin[num].offsetHeight; } /** * 獲取parent下全部樣式名爲className的對象集合 */
        function getClassObject(parent,className){ var obj = parent.getElementsByTagName("*"); var result = []; for(var i=0; i<obj.length;i++){ //變量若是匹配className,將匹配的對象放入數組
                if(obj[i].className==className){ result.push(obj[i]); } } return result; } /** * 獲取arr數組中值爲minH的值在數組中的索引 */
        function getMinHeightKey(arr,minH){ for(key in arr){ if(arr[key] == minH){ return key; } } } </script>
    <style type="text/css">
        /*設置每個瀑布流塊*/ #main .pin{ width:220px; height: auto; padding: 15px 0px 0px 15px; /*上 右 下 左*/ float: left;
        }
        /*設置每個瀑布流塊中的圖像樣式*/ #main .pin .box{ width: 200px; height: auto; padding: 10px; background: #FFF; border: 1px solid #ccc; box-shadow: 0px 0px 6px #ccc; /*中間投影*/ border-radius: 5px; /*圓角*/
        } #main .pin .box img{ width: 200px;

        }
    </style>
</head>
<body>
    <div id="main">
        <!--每個小塊-->
        <div class="pin">
            <div class="box">
                <img src="images/2012110120000859759.jpg">
            </div>
        </div>

        <!--每個小塊-->
        <div class="pin">
            <div class="box">
                <img src="images/2012072300483800466.jpg">
            </div>
        </div>

        <!--每個小塊-->
        <div class="pin">
            <div class="box">
                <img src="images/2012101912011350194.jpg">
            </div>
        </div>

        <!--每個小塊-->
        <div class="pin">
            <div class="box">
                <img src="images/2012102421195356552.jpg">
            </div>
        </div>

        <!--每個小塊-->
        <div class="pin">
            <div class="box">
                <img src="images/2012072312335411883.jpg">
            </div>
        </div>


        <!--每個小塊-->
        <div class="pin">
            <div class="box">
                <img src="images/2012082910221472225.jpg">
            </div>
        </div>
        

    </div>
</body>
</html>

實現步驟二描述效果

實現代碼

<!doctype html>
<html>
<head>
    <meta charset="UTF-8">
    <title>瀑布流效果實現</title>
    <script type="text/javascript" src="scripts/jquery-1.8.2.min.js"></script>
    <script type="text/javascript" src="scripts/jquery.easydrag.handler.beta2.js"></script>
    <script type="text/javascript"> window.onload=function(){ //獲取父級對象
            var oParent = document.getElementById("main"); //獲取父級[第一個參數]下的全部的子元素[按照第二個參數匹配]
            var aPin = getClassObject(oParent,"pin"); //獲取每個塊的寬度
            var iPinW = aPin[0].offsetWidth; // //計算每行放多少個pin(瀑布流塊)頁面的寬度/每個瀑布流塊的寬度
            var num = Math.floor(document.documentElement.clientWidth/iPinW);
            //重置父級的樣式,這樣保證圖片總體居中
 oParent.style.cssText="width:" + num*iPinW + "px;margin:0 auto;"; var compareArray = []; //遍歷獲取到的全部瀑布流塊
            for (var i = 0; i<aPin.length; i++) { if(i<num){ //成行元素
 compareArray[i] = aPin[i].offsetHeight; }else{ //獲取成行元素中高度最低的值
                    var minHeight = Math.min.apply('',compareArray); //alert(compareArray + ",min=" + minHeight);
                    //獲取成行元素中高度最低元素的索引
                    var minHkey = getMinHeightKey(compareArray,minHeight); //爲新增的瀑布流塊設置定位
 aPin[i].style.position = "absolute"; aPin[i].style.top = minHeight + "px"; //設定新增長的瀑布流塊的top和left
 aPin[i].style.left =aPin[minHkey].offsetLeft + "px"; //將該索引位置的高度改變爲新增後的高度[原來瀑布流塊的高度+新增的瀑布流塊的高度]
 compareArray[minHkey] += aPin[i].offsetHeight; } } } /** * 獲取parent下全部樣式名爲className的對象集合 */
        function getClassObject(parent,className){ var obj = parent.getElementsByTagName("*"); var result = []; for(var i=0; i<obj.length;i++){ //變量若是匹配className,將匹配的對象放入數組
                if(obj[i].className==className){ result.push(obj[i]); } } return result; } /** * 獲取arr數組中值爲minH的值在數組中的索引 */
        function getMinHeightKey(arr,minH){ for(key in arr){ if(arr[key] == minH){ return key; } } } </script>
    <style type="text/css">
        /*設置每個瀑布流塊*/ #main .pin{ width:220px; height: auto; padding: 15px 0px 0px 15px; /*上 右 下 左*/ float: left;
        }
        /*設置每個瀑布流塊中的圖像樣式*/ #main .pin .box{ width: 200px; height: auto; padding: 10px; background: #FFF; border: 1px solid #ccc; box-shadow: 0px 0px 6px #ccc; /*中間投影*/ border-radius: 5px; /*圓角*/
        } #main .pin .box img{ width: 200px;

        }
    </style>
</head>
<body>
    <div id="main">
        <!--每個小塊-->
        <div class="pin">
            <div class="box">
                <img src="images/2012110120000859759.jpg">
            </div>
        </div>

        <!--每個小塊-->
        <div class="pin">
            <div class="box">
                <img src="images/2012072300483800466.jpg">
            </div>
        </div>

        <!--每個小塊-->
        <div class="pin">
            <div class="box">
                <img src="images/2012101912011350194.jpg">
            </div>
        </div>

        <!--每個小塊-->
        <div class="pin">
            <div class="box">
                <img src="images/2012102421195356552.jpg">
            </div>
        </div>

        <!--每個小塊-->
        <div class="pin">
            <div class="box">
                <img src="images/2012072312335411883.jpg">
            </div>
        </div>

        <!--每個小塊-->
        <div class="pin">
            <div class="box">
                <img src="images/2012082910221472225.jpg">
            </div>
        </div>

        <!--每個小塊-->
        <div class="pin">
            <div class="box">
                <img src="images/2012082910024626515.jpg">
            </div>
        </div>

    </div>
</body>
</html>

會看到新增的瀑布流塊在新的成行元素中自動尋找高度最低的那個元素塊的相對位置進行追加.添加更多元素查看效果

步驟三:實現滾動到底部時加載數據
該部分沒有什麼功能,只是檢測滾動條的位置距離瀏覽器底部的相對距離進行數據加載,加載數據時建立對應的瀑布流塊.判斷相對距離的實現邏輯以下

 function checkScrollSite(){ var oParent = document.getElementById("main"); var aPin = getClassObject(oParent,"pin"); //加載數據依賴最後一個瀑布流塊變化 var lastPinHeight = aPin[aPin.length-1].offsetTop + Math.floor(aPin[aPin.length-1].offsetHeight/2) ; var scrollTop = document.documentElement.scrollTop || document.body.scrollTop; //瀏覽器高度 var documentH = document.documentElement.clientHeight; if(lastPinHeight<documentH + scrollTop){ //請求數據 return true; } return false; }

在此感謝,鄭印在學習上給予的指導.

轉載請註明出處:[http://www.cnblogs.com/dennisit/p/3244987.html]

相關文章
相關標籤/搜索