瀑布流javascript
又稱瀑布流式佈局,是比較流行的一種網站頁面佈局方式。即多行等寬元素排列,後面的元素依次添加到其後,等寬不等高,根據圖片原比例縮放直至寬度達到咱們的要求,依次按照規則放入指定位置。css
爲何使用瀑布流html
瀑布流佈局在咱們如今的前端頁面中常常會用的到,它能夠有效的下降頁面的複雜度,節省不少的空間,對於整個頁面不須要太多的操做,只須要下拉就能夠瀏覽用戶須要看到的數據;而且,在當前這個APP至上的時代,瀑布流能夠提供很好的用戶體驗,經過結合下拉刷新,上拉加載進行數據的懶加載等操做,對於用戶的體驗感來講是接近於滿分的!前端
瀑布流的特色java
其實瀑布流的特色就是良莠不齊的排列方式,以及流式佈局的擴展性,能夠經過界面展現給用戶多條數據,而且讓用戶能夠有向下瀏覽的衝動。web
瀑布流的代碼實現算法
1.純 css 瀑布流:( multi-columns 方法 )數組
// 這裏是第一次接觸到 column-columns 這個屬性,這是一個能夠設置將div元素中的文本分紅幾列瀏覽器
//默認值是:autoapp
//寫法:
column-count:3;
-moz-column-count:3; / Firefox /
-webkit-column-count:3; / Safari and Chrome /
/ 注意:IE9及更早 IE 版本瀏覽器不支持 column-count 屬性 /
//這裏還會用到另外一個屬性 column-gap,用來調整邊距,實現瀑布流佈局
html結構代碼以下:
學習Q-q-u-n: 784783012 ,分享學習的方法和須要注意的小細節,不停更新最新的教程和學習技巧 (從零基礎開始到前端項目實戰教程,學習工具,全棧開發學習路線以及規劃) <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; /*防止斷點*/ background: #ccc; text-align: center; }
效果圖:
這裏有個弊端,這並不符合瀑布流的原理,若是使用純css寫瀑布流,則每一塊都是從上往下排列,不能作到從左到右排列,而且不會識別哪一塊圖片放在哪一個地方合適,如果再配合動態加載,效果會特別很差,因此只能經過JS來實現瀑布流。
那麼這裏用圖片來分析一下咱們想要的瀑布流是什麼樣的。
瀑布流的位置分析圖解
以下方圖片。假設一排放5張圖片。當第一排排知足夠多的等寬圖片時,顯示的是這樣的。那麼假如咱們要放第6張圖片的時候,應該放在什麼位置呢?
若是按照咱們的正常邏輯來想,應該是放在第一張圖片下面,依次水平排列過去(以下圖)
但現實並不是如此!在瀑布流中,從第2行開始,接下去的每一張圖片都會放在上行中高度最低的那一列圖片下方。(以下圖)
爲何呢?由於放置它以前,這一列的高度爲全部列中最小,因此會放置在這個地方。
那麼若是再繼續放置下去,第七張圖片應該放在第三列圖片下方,以此類推。
因此每次加載圖片時,會須要判斷哪一列的圖片累計的高度最小,那麼下一張圖片就放在哪一列,即瀑布流算法去判斷圖片的肯定位置。
JS代碼實現
實現思路:
代碼實現
<script type="text/javascript"> // 定義瀑布流算法函數 function fall() { const minGap = 20; // 最小間距,讓每一列的最小空隙能夠自定義,避免太過擁擠的狀況發生。可是,會經過計算獲得真實的間距。 const itemWidth = 300; // 每一項的寬度,即當前每個圖片容器的寬度。保證每一列都是等寬不等高的。 const scrollBarWidth = getScrollbarWidth(); // 獲取滾動條的寬度 const pageWidth = window.innerWidth - scrollBarWidth; // 獲取當前頁面的寬度 = window.innerWidth - 滾動條的寬度 const column = Math.floor(pageWidth / (itemWidth + minGap)); // 實際列數=頁面寬度/(圖片寬度+最小間距) const gap = (pageWidth - itemWidth * column) / column/2; // 計算真實間距 = (頁面寬度- 圖片寬度*實際列數)/實際列數/2 const items = document.querySelectorAll('img'); // 獲取全部的外層元素 const heightArr = []; // 定義一個空數組,保存最低高度。 // 獲取滾動條的寬度 function getScrollbarWidth() { const oDiv = document.createElement('div');//建立一個div // 給div設置樣式。隨便定義寬高,只要能獲取到滾動條就能夠 oDiv.style.cssText = `width: 50px;height: 50px;overflowY: scroll;` document.body.appendChild(oDiv);//把div添加到body中 const scrollbarWidth = oDiv.offsetWidth - oDiv.clientWidth;// 使最大寬度和可視寬度相減,得到到滾動條寬度。 oDiv.remove();//移除建立的div return scrollbarWidth;//返回滾動條寬度 } for (let i = 0; i < items.length; i++) { // 遍歷全部的外層容器 const height = items[i].offsetHeight; // 若是當前處在第一行 if (i < column) { // 直接設置元素距離上部的位置和距離左邊的距離。 items[i].style.cssText = `top: ${gap}px;left: ${(itemWidth + gap) * i + gap}px`; // 保存當前元素的高度。 heightArr.push(height); } else { // 不是第一行的話,就進行比對。 let minHeight = heightArr[0]; // 先保存第一項的高度 let minIndex = 0; // 保存第一項的索引值 for (let j = 0; j < heightArr.length; j++) { // 經過循環遍歷比對,拿到最小值和最小值的索引。 if (minHeight > heightArr[j]) { minHeight = heightArr[j]; minIndex = j; } } // 經過最小值爲當前元素設置top值,經過索引爲當前元素設置left值。 items[i].style.cssText = `top: ${minHeight + gap *2}px; left: ${(itemWidth + gap) * minIndex + gap}px`; // 並修改當前索引的高度爲當前元素的高度 heightArr[minIndex] = minHeight + gap + height; } } } // 頁面加載完成調用一次。 window.onload = fall; // 頁面尺寸發生改變再次調用。 window.onresize = fall; </script> 學習Q-q-u-n: 784783012 ,分享學習的方法和須要注意的小細節,不停更新最新的教程和學習技巧 (從零基礎開始到前端項目實戰教程,學習工具,全棧開發學習路線以及規劃)
最終效果圖:
總結瀑布流佈局原理
引伸知識點