1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        純CSS與JS流瀑布流的布局原理分析

        共 6243字,需瀏覽 13分鐘

         ·

        2022-03-07 23:13

        來(lái)源 | https://www.fly63.com


        瀑布流 

        又稱瀑布流式布局,是比較流行的一種網(wǎng)站頁(yè)面布局方式。即多行等寬元素排列,后面的元素依次添加到其后,等寬不等高,根據(jù)圖片原比例縮放直至寬度達(dá)到我們的要求,依次按照規(guī)則放入指定位置。


        為什么使用瀑布流

        瀑布流布局在我們現(xiàn)在的前端頁(yè)面中經(jīng)常會(huì)用的到,它可以有效的降低頁(yè)面的復(fù)雜度,節(jié)省很多的空間,對(duì)于整個(gè)頁(yè)面不需要太多的操作,只需要下拉就可以瀏覽用戶需要看到的數(shù)據(jù);并且,在當(dāng)前這個(gè)APP至上的時(shí)代,瀑布流可以提供很好的用戶體驗(yàn),通過(guò)結(jié)合下拉刷新,上拉加載進(jìn)行數(shù)據(jù)的懶加載等操作,對(duì)于用戶的體驗(yàn)感來(lái)說(shuō)是接近于滿分的!

        瀑布流的特點(diǎn)

        其實(shí)瀑布流的特點(diǎn)就是參差不齊的排列方式,以及流式布局的擴(kuò)展性,可以通過(guò)界面展示給用戶多條數(shù)據(jù),并且讓用戶可以有向下瀏覽的沖動(dòng)。

        瀑布流的代碼實(shí)現(xiàn)

        1、純 css 瀑布流:( multi-columns 方法 )

        // 這里是第一次接觸到 column-columns 這個(gè)屬性,這是一個(gè)可以設(shè)置將div元素中的文本分成幾列

        // 默認(rèn)值是:auto

        // 寫(xiě)法:

        column-count:3;-moz-column-count:3; /* Firefox */-webkit-column-count:3; /* Safari and Chrome */

        /* 注意:IE9及更早 IE 版本瀏覽器不支持 column-count 屬性 */

        // 這里還會(huì)用到另一個(gè)屬性 column-gap,用來(lái)調(diào)整邊距,實(shí)現(xiàn)瀑布流布局

        html結(jié)構(gòu)代碼如下:

        <div class="demo-1">     <div class="item">         <div class="item_content content-lar" style="height:100px;" > 1</div>     </div>     <div class="item">         <div class="item_content content-sma"style="height:150px;" > 2</div>     </div>    <div class="item">         <div class="item_content content-mid"style="height:50px;" > 3</div>     </div>    <div class="item">         <div class="item_content content-sma" style="height:200px;" > 4</div>     </div>    <div class="item">         <div class="item_content content-mid"style="height:60px;" > 5 </div>     </div>    <div class="item">         <div class="item_content content-lar"style="height:90px;" > 6</div>     </div>     <div class="item">         <div class="item_content content-sma"> 7</div>     </div>    <div class="item">         <div class="item_content content-lar"style="height:120px;" > 8</div>     </div>    <div class="item">         <div class="item_content content-lar"> 9</div>     </div>    <div class="item">         <div class="item_content content-sma" style="height:100px;" > 10 </div>     </div>    <div class="item">         <div class="item_content content-mid"> 11 </div>     </div>    <div class="item">         <div class="item_content content-mid"style="height:100px;" > 12</div>     </div>    <!-- more items --> </div>

        CSS代碼如下:

        .demo-1{        -moz-column-count:3; /* Firefox */       -webkit-column-count:3; /* Safari 和 Chrome */       column-count:3;       -moz-column-gap: 1em;       -webkit-column-gap: 1em;       column-gap: 1em;       width: 80%;       margin:0 auto;    }    .item {         padding: 2em;        margin-bottom: 2em;        -webkit-column-break-inside: avoid;        break-inside: avoid; /*防止斷點(diǎn)*/        background: #ccc;        text-align: center;    }

        效果圖:


        這里有個(gè)弊端,這并不符合瀑布流的原理,如果使用純css寫(xiě)瀑布流,則每一塊都是從上往下排列,不能做到從左到右排列,并且不會(huì)識(shí)別哪一塊圖片放在哪個(gè)地方合適,若是再配合動(dòng)態(tài)加載,效果會(huì)特別不好,所以只能通過(guò)JS來(lái)實(shí)現(xiàn)瀑布流。
        那么這里用圖片來(lái)分析一下我們想要的瀑布流是什么樣的。
        瀑布流的位置分析圖解
        如下方圖片。假設(shè)一排放5張圖片。當(dāng)?shù)谝慌排艥M足夠多的等寬圖片時(shí),顯示的是這樣的。那么假如我們要放第6張圖片的時(shí)候,應(yīng)該放在什么位置呢?


        如果按照我們的正常邏輯來(lái)想,應(yīng)該是放在第一張圖片下面,依次水平排列過(guò)去(如下圖)


        但現(xiàn)實(shí)并非如此!在瀑布流中,從第2行開(kāi)始,接下去的每一張圖片都會(huì)放在上行中高度最低的那一列圖片下方。(如下圖)


        為什么呢?因?yàn)榉胖盟?,這一列的高度為所有列中最小,所以會(huì)放置在這個(gè)地方。

        那么如果再繼續(xù)放置下去,第七張圖片應(yīng)該放在第三列圖片下方,以此類推。


        所以每次加載圖片時(shí),會(huì)需要判斷哪一列的圖片累計(jì)的高度最小,那么下一張圖片就放在哪一列,即瀑布流算法去判斷圖片的確定位置。

        JS代碼實(shí)現(xiàn)

        實(shí)現(xiàn)思路:

        1、設(shè)定每一列圖片的寬度和間距

        2、獲取當(dāng)前窗口的總寬度,從而根據(jù)圖片寬度去旁段分成幾列

        3、獲取所有圖片元素,定義一個(gè)空數(shù)組來(lái)保存高度

        4、遍歷所有容器,開(kāi)始判斷  當(dāng)頁(yè)面加載完成,或頁(yè)面寬度發(fā)生變化時(shí),調(diào)用函數(shù)。


          • 如果當(dāng)前處于第一行時(shí):直接設(shè)置圖片位置【 即 top為間距的大小,left為(當(dāng)前圖片的寬度+間距) * 當(dāng)前圖片的值+間距大小 】,并保存當(dāng)前元素高度。

          • 如果當(dāng)前不處于第一行時(shí):進(jìn)行高度對(duì)比,通過(guò)遍歷循環(huán),拿到最小高度和相對(duì)應(yīng)的索引,設(shè)置圖片位置【 即 top為最小高度值+間距*2,left為 (當(dāng)前圖片的寬度+間距) * 索引 值+間距大?。?,并修改當(dāng)前索引的高度為當(dāng)前元素高度。

        5、當(dāng)頁(yè)面加載完成,或頁(yè)面寬度發(fā)生變化時(shí),調(diào)用函數(shù)。 

        代碼實(shí)現(xiàn)

        <script type="text/javascript">    // 定義瀑布流算法函數(shù)    function fall() {        const minGap = 20; // 最小間距,讓每一列的最小空隙可以自定義,避免太過(guò)擁擠的情況發(fā)生。但是,會(huì)通過(guò)計(jì)算得到真實(shí)的間距。        const itemWidth = 300; // 每一項(xiàng)的寬度,即當(dāng)前每一個(gè)圖片容器的寬度。保證每一列都是等寬不等高的。        const scrollBarWidth = getScrollbarWidth();    // 獲取滾動(dòng)條的寬度        const pageWidth = window.innerWidth - scrollBarWidth; // 獲取當(dāng)前頁(yè)面的寬度 = window.innerWidth - 滾動(dòng)條的寬度        const column = Math.floor(pageWidth / (itemWidth + minGap)); // 實(shí)際列數(shù)=頁(yè)面寬度/(圖片寬度+最小間距)        const gap = (pageWidth - itemWidth * column) / column/2; // 計(jì)算真實(shí)間距 = (頁(yè)面寬度- 圖片寬度*實(shí)際列數(shù))/實(shí)際列數(shù)/2        const items = document.querySelectorAll('img'); // 獲取所有的外層元素        const heightArr = []; // 定義一個(gè)空數(shù)組,保存最低高度。
        // 獲取滾動(dòng)條的寬度 function getScrollbarWidth() { const oDiv = document.createElement('div');//創(chuàng)建一個(gè)div // 給div設(shè)置樣式。隨便定義寬高,只要能獲取到滾動(dòng)條就可以 oDiv.style.cssText = `width: 50px;height: 50px;overflowY: scroll;` document.body.appendChild(oDiv);//把div添加到body中 const scrollbarWidth = oDiv.offsetWidth - oDiv.clientWidth;// 使最大寬度和可視寬度相減,獲得到滾動(dòng)條寬度。 oDiv.remove();//移除創(chuàng)建的div return scrollbarWidth;//返回滾動(dòng)條寬度 }

        for (let i = 0; i < items.length; i++) { // 遍歷所有的外層容器 const height = items[i].offsetHeight; // 如果當(dāng)前處在第一行 if (i < column) { // 直接設(shè)置元素距離上部的位置和距離左邊的距離。 items[i].style.cssText = `top: ${gap}px;left: ${(itemWidth + gap) * i + gap}px`; // 保存當(dāng)前元素的高度。 heightArr.push(height); } else { // 不是第一行的話,就進(jìn)行比對(duì)。 let minHeight = heightArr[0]; // 先保存第一項(xiàng)的高度 let minIndex = 0; // 保存第一項(xiàng)的索引值 for (let j = 0; j < heightArr.length; j++) { // 通過(guò)循環(huán)遍歷比對(duì),拿到最小值和最小值的索引。 if (minHeight > heightArr[j]) { minHeight = heightArr[j]; minIndex = j; } } // 通過(guò)最小值為當(dāng)前元素設(shè)置top值,通過(guò)索引為當(dāng)前元素設(shè)置left值。 items[i].style.cssText = `top: ${minHeight + gap *2}px; left: ${(itemWidth + gap) * minIndex + gap}px`; // 并修改當(dāng)前索引的高度為當(dāng)前元素的高度 heightArr[minIndex] = minHeight + gap + height; } } } // 頁(yè)面加載完成調(diào)用一次。 window.onload = fall; // 頁(yè)面尺寸發(fā)生改變?cè)俅握{(diào)用。 window.onresize = fall;</script>

        最終效果圖:


        總結(jié)瀑布流布局原理

        • 設(shè)置圖片寬度一致

        • 根據(jù)瀏覽器寬度以及每列寬度計(jì)算出列表個(gè)數(shù),列表默認(rèn)0

        • 當(dāng)圖片加載完成,所有圖片依次放置在最小的列數(shù)下面

        • 父容器高度取列表數(shù)組的最大值

        引申知識(shí)點(diǎn)

        • let,const以及var三者的區(qū)別

        • 滾動(dòng)加載圖片(懶加載原理)

        • 反撇號(hào)(`)基礎(chǔ)知識(shí)

        • style和style.cssTest 的區(qū)別


        學(xué)習(xí)更多技能

        請(qǐng)點(diǎn)擊下方公眾號(hào)

        瀏覽 37
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            黄色电影亚洲 | 豪妇荡乳黄淑珍13 | 黑人男女粗大猛烈进出视频 | 骚狐网站| 天天操丝袜| 色偷偷大香蕉 | 欧美做爱网站 | 无码精品视频免费看 | 十大尺度做爰未删减电影暗欲 | 日韩第二页 |