瀑布流佈局
瀑布流,又稱瀑布流式佈局。
是比較流行的一種網站頁面佈局,視覺表現爲參差不齊的多欄佈局,隨着頁面滾動條向下滾動,這種佈局還會不斷加載數據塊並附加至當前尾部。
瀑布流特點:等寬不等高,第二行的第一張圖片要加載到第一行中最矮的圖片的下面。
1. 原生JavaScript方式實現
index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>waterfall_flow_layout</title>
<style>
*{
margin: 0;
padding: 0;
}
#main{
position: relative;
}
.box{
padding: 15px 0 0 15px; /*設置頂部和底部的距離*/
float: left; /*設置圖片浮動(顯示在同一行)*/
}
.pic{
padding: 10px; /*內邊距*/
border:1px solid #ccc; /*邊框*/
border-radius: 5px; /*圓角*/
box-shadow: 0 0 5px #ccc; /*設置陰影,水平和垂直陰影都爲0,陰影程度爲5px*/
}
.pic img{
width:165px; /*設置圖片都等寬*/
height: auto;
}
</style>
</head>
<body>
<div id="main">
<div class="box">
<div class="pic">
<img src="./images/0.jpg">
</div>
</div>
<div class="box">
<div class="pic">
<img src="./images/1.jpg">
</div>
</div>
<div class="box">
<div class="pic">
<img src="./images/2.jpg">
</div>
</div>
<div class="box">
<div class="pic">
<img src="./images/3.jpg">
</div>
</div>
<div class="box">
<div class="pic">
<img src="./images/4.jpg">
</div>
</div>
<div class="box">
<div class="pic">
<img src="./images/5.jpg">
</div>
</div>
<div class="box">
<div class="pic">
<img src="./images/6.jpg">
</div>
</div>
<div class="box">
<div class="pic">
<img src="./images/7.jpg">
</div>
</div>
<div class="box">
<div class="pic">
<img src="./images/8.jpg">
</div>
</div>
<div class="box">
<div class="pic">
<img src="./images/9.jpg">
</div>
</div>
<div class="box">
<div class="pic">
<img src="./images/10.jpg">
</div>
</div>
<div class="box">
<div class="pic">
<img src="./images/11.jpg">
</div>
</div>
<div class="box">
<div class="pic">
<img src="./images/12.jpg">
</div>
</div>
<div class="box">
<div class="pic">
<img src="./images/13.jpg">
</div>
</div>
<div class="box">
<div class="pic">
<img src="./images/14.jpg">
</div>
</div>
<div class="box">
<div class="pic">
<img src="./images/15.jpg">
</div>
</div>
<div class="box">
<div class="pic">
<img src="./images/16.jpg">
</div>
</div>
<div class="box">
<div class="pic">
<img src="./images/17.jpg">
</div>
</div>
<div class="box">
<div class="pic">
<img src="./images/18.jpg">
</div>
</div>
<div class="box">
<div class="pic">
<img src="./images/19.jpg">
</div>
</div>
<div class="box">
<div class="pic">
<img src="./images/20.jpg">
</div>
</div>
<div class="box">
<div class="pic">
<img src="./images/21.jpg">
</div>
</div>
<div class="box">
<div class="pic">
<img src="./images/22.jpg">
</div>
</div>
<div class="box">
<div class="pic">
<img src="./images/23.jpg">
</div>
</div>
</div>
<script src="./js/js_waterfall_flow_layout.js"></script>
</body>
</html>
js_waterfall_flow_layout.js
//原生JavaScript實現瀑布流佈局
window.οnlοad= function(){
waterfall('main','box');
//模擬從後臺來的數據
var dataInt = {"data":[{"src":'24.jpg'},{"src":'25.jpg'},{"src":'26.jpg'},{"src":'27.jpg'}]};
window.onscroll = function(){
if(checkScrollSlide){
var oParent = document.getElementById('main');
//將加載的數據渲染到當前頁面的尾部
for(var i=0; i <dataInt.data.length; i++){
var oBox = document.createElement('div'); //添加 元素節點
oBox.className = 'box'; //添加 類名 name屬性
oParent.appendChild(oBox); //添加子元素到父元素的後面
oPic = document.createElement('div');
oPic.className = 'pic';
oBox.appendChild(oPic);
var oImg = document.createElement('img');
oImg.src = './images/' + dataInt.data[i].src;
oPic.appendChild(oImg);
}
waterfall('main','box'); //再次調用瀑布流佈局
}
}
}
//瀑布流佈局實現
function waterfall(parent, box){
//將main下的所有class爲box的元素取出來
var oParent = document.getElementById(parent);
//獲取parent父元素下的所有box元素
var oBoxes = getByClass(oParent, box);
//計算整個頁面的列數( 頁面寬 / box的寬 )
//offsetWidth:獲取元素的寬度(width + padding + border + 父級padding)
var oBoxW = oBoxes[0].offsetWidth;
var cols = Math.floor(document.documentElement.clientWidth / oBoxW); //獲取頁面寬度除以box的寬
oParent.style.cssText = 'width:' + oBoxW*cols + 'px;margin:0 auto;'; //設置main的寬度,設置之後居中
var hArr = []; //數組中先存的是第一行的6張圖片的高度,之後存的是每一列的圖片的高度
for(var i=0; i<oBoxes.length; i++){
if(i < cols){
hArr.push(oBoxes[i].offsetHeight);
}else{
var minH = Math.min.apply(null,hArr); //apply()改變函數(方中)this的指向
var oIndex = getMinhIndex(hArr, minH); //數組中值最小的索引
//改變盒子的位置
oBoxes[i].style.position = 'absolute';
oBoxes[i].style.top = minH + 'px';
//oBoxes[i].style.left = oBoxW * oIndex + 'px';
oBoxes[i].style.left = oBoxes[oIndex].offsetLeft + 'px'; //另一種方法
//改變最小值 : 原來的值 + 新加的圖片的值
hArr[oIndex] += oBoxes[i].offsetHeight;
}
}
}
//根據class獲取元素(獲取指定父元素下的所有子元素)
function getByClass(parent, className){
var boxArr = []; //用來存儲取到的所有class爲box元素
var oElements = parent.getElementsByTagName('*');
//遍歷所有獲取到的元素
for(var i = 0; i<oElements.length; i++){
if(oElements[i].className == className){
boxArr.push(oElements[i]);
}
}
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 + Math.floor(oBoxs[oBoxs.length-1].offsetHeight / 2);
//滾動條向下滾動的距離(上面看不見的)
var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
//當前瀏覽器頁面的可視高度
var height = document.body.clientHeight || document.documentElement.clientHeight;
return (lastBoxH > scrollTop + height) ? true : false;
}
2. 用jQuery實現
引入jQuery: <script src="./js/jquery-1.8.3.min.js"></script>
然後只需要將上面的引入的js代碼改成如下即可:
//用jQuery實現瀑布流佈局
$(window).on('load', function(){
waterfall();
var dataInt = {"data":[{"src":'24.jpg'},{"src":'25.jpg'},{"src":'26.jpg'},{"src":'27.jpg'}]};
//滾動條事件
$(window).on('scroll', function(){
if(checkScrollSlide){
$.each(dataInt.data, function(key,value){
//利用jquery的兩大特點:支持連綴,隱式迭代
var oBox = $('<div>').addClass('box').appendTo($('#main'));
var oPic = $('<div>').addClass('pic').appendTo($(oBox));
var oImg = $('<img>').attr('src','./images/' + $(value).attr('src')).appendTo($(oPic));
});
}
waterfall();
})
});
//實現瀑布流佈局(不能滾動)
function waterfall(){
var $boxs = $('#main>div'); //獲取class爲box的元素
var w = $boxs.eq(0).outerWidth(); //outerWidth獲取的寬度值包含padding border
var cols =Math.floor($(window).width() / w ); //計算列數
$('#main').width(w*cols).css('margin','0 auto');
var hArr = [];
$boxs.each(function(index,value){
//index 索引 value是一個dom對象
var h = $boxs.eq(index).outerHeight();
if(index < cols){ //前cols個圖片
hArr[index] = h;
}else{
var minH = Math.min.apply(null,hArr);
var minHIndex = $.inArray(minH,hArr);
//設置從第七張之後的圖片的位置
$(value).css({ //將dom對象轉換成jquery對象
'position':'absolute',
'top':minH + 'px',
'left': minHIndex*w + 'px'
});
hArr[minHIndex] += $boxs.eq(index).outerHeight();
}
});
}
//判斷是否具備滾動的條件
function checkScrollSlide(){
//獲取最後一個元素
var $lastBox = $('#main>div').last();
var lastBoxDis = $lastBox.offset().top + Math.floor($lastBox.outerHeight() / 2);
//獲取頁面滾走的距離
var scrollTop = $(window).scrollTop();
//獲取可視頁面的高度
var documentH = $(window).height();
return (lastBoxDis < scrollTop + documentH) ? true : false;
}
3. 用css3實現(主要用到多欄佈局的新特性)
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>css3_waterfall_flow_layout</title>
<style>
#main{
/* 設置列寬,202 = 圖片寬度165 + 內邊距10*2 + 邊框1*2 + box的15 */
-webkit-column-width: 202px;
-moz-column-width: 202px;
-o-column-width:202px;
-ms-column-width:202px;
}
.box{
padding: 10px 0 0 15px;
}
.pic{
padding:10px;
border:1px solid #ccc;
border-radius: 5px;
box-shadow:0 0 5px #ccc;
width:165px;
}
.pic img{
display: block;
width:165px;
height: auto;
}
</style>
</head>
<body>
<div id="main">
<div class="box">
<div class="pic">
<img src="./images/0.jpg">
</div>
</div>
<div class="box">
<div class="pic">
<img src="./images/1.jpg">
</div>
</div>
<div class="box">
<div class="pic">
<img src="./images/2.jpg">
</div>
</div>
<div class="box">
<div class="pic">
<img src="./images/3.jpg">
</div>
</div>
<div class="box">
<div class="pic">
<img src="./images/4.jpg">
</div>
</div>
<div class="box">
<div class="pic">
<img src="./images/5.jpg">
</div>
</div>
<div class="box">
<div class="pic">
<img src="./images/6.jpg">
</div>
</div>
<div class="box">
<div class="pic">
<img src="./images/7.jpg">
</div>
</div>
<div class="box">
<div class="pic">
<img src="./images/8.jpg">
</div>
</div>
<div class="box">
<div class="pic">
<img src="./images/9.jpg">
</div>
</div>
<div class="box">
<div class="pic">
<img src="./images/10.jpg">
</div>
</div>
<div class="box">
<div class="pic">
<img src="./images/11.jpg">
</div>
</div>
<div class="box">
<div class="pic">
<img src="./images/12.jpg">
</div>
</div>
<div class="box">
<div class="pic">
<img src="./images/13.jpg">
</div>
</div>
<div class="box">
<div class="pic">
<img src="./images/14.jpg">
</div>
</div>
<div class="box">
<div class="pic">
<img src="./images/15.jpg">
</div>
</div>
<div class="box">
<div class="pic">
<img src="./images/16.jpg">
</div>
</div>
<div class="box">
<div class="pic">
<img src="./images/17.jpg">
</div>
</div>
<div class="box">
<div class="pic">
<img src="./images/18.jpg">
</div>
</div>
<div class="box">
<div class="pic">
<img src="./images/19.jpg">
</div>
</div>
<div class="box">
<div class="pic">
<img src="./images/20.jpg">
</div>
</div>
<div class="box">
<div class="pic">
<img src="./images/21.jpg">
</div>
</div>
<div class="box">
<div class="pic">
<img src="./images/22.jpg">
</div>
</div>
<div class="box">
<div class="pic">
<img src="./images/23.jpg">
</div>
</div>
<div class="box">
<div class="pic">
<img src="./images/24.jpg">
</div>
</div>
<div class="box">
<div class="pic">
<img src="./images/25.jpg">
</div>
</div>
<div class="box">
<div class="pic">
<img src="./images/26.jpg">
</div>
</div>
<div class="box">
<div class="pic">
<img src="./images/27.jpg">
</div>
</div>
<div class="box">
<div class="pic">
<img src="./images/28.jpg">
</div>
</div>
</div>
</body>
</html>
4. 對比瀑布流佈局實現方式:
原生JS:
需要計算, 列數 = 瀏覽器窗口寬度 / 圖片寬度 ,圖片定位是根據每一列數據庫的高度計算接下來圖片的位置。
圖片順序是按照圖片計算的位置橫向排列,位置是計算出來的,比較規範。
css3:
不需要計算,瀏覽器自動計算,只需要設置列寬,性能高
列寬隨着瀏覽器窗口大小進行改變,用戶體驗不好
圖片排序按照垂直順序排列,打亂圖片顯示順序
圖片加載還是依靠JavaScript實現