1.瀑布流布局
思路:
要求:當圖片寬度相同,高度不同時;如何做一面圖片墻;每次圖片加載到每列最低的位置;
1.圖片的容器要相對定位,圖片要相對容器絕對定位;
2.首先要求出當瀏覽器打開時或者改變大小時,瀏覽器的窗口能放入幾張圖片;即形成幾列;
3.創建一個空數組來存放每列的高度值;
4.當有圖片加載時根據數組里存放的高度大小;把圖片放入高度最小的列;
5.當放入后更改放入后的高度;這樣每次都可以把圖片放入高度最低的列里形成好看的圖片墻了。重點:
.content{
position:relative;
}
.item{
position: absolute;
transition:all 1s; /*漸變效果*/
}
function waterFull(){
var nodeWidth =$('.item').width();//元素寬度
var num =parseInt($('.content').width()/nodeWidth)//一排放多少個(取整)
var itemArr = [];//存放每列的高度;
for(var i=0; i<num;i++){//初始化
itemArr[i]=0;//目前每列高度為0;
}
$('.item').each(function(){//循環所有圖片
var minValue = Math.min.apply(null,itemArr) //獲取數組最小值(第一次就是數組的第一項0;)
var minIndex = itemArr.indexOf(minValue)//獲取最小值的下標;
$(this).css({//通過改變top left ;放入圖片的位置;
top:itemArr[minIndex],
left:$(this).outerWidth(true)*minIndex
})
itemArr[minIndex] += $(this).outerHeight(true);//更改添加后列的高度
})
}
- 看下效果:
- 優化:
1.在改變窗口大小時重新加載圖片位置
2.當滾動時繼續的加載圖片;(寫一個判斷是否加載的函數checkScroll)
3.當滾動時發送ajax性后端要數據加載圖片;(我這里是自己給的數據json模擬)
4.優化代碼放入立即執行函數;
var WaterFull=(function(){
function init(){
waterFull()
$(window).resize(function(){//改變窗口大小
waterFull()
})
$(window).on('scroll',Scroll)//當窗口滾動時Mocks數據;
}
function waterFull(){
var nodeWidth =$('.item').width();//元素寬度
var num =parseInt($('.content').width()/nodeWidth)//一排放多少個(取整)
var itemArr = [];//存放每列的高度;
for(var i=0; i<num;i++){//初始化
itemArr[i]=0;//目前每列高度為0;
}
$('.item').each(function(){//循環所有圖片
var minValue = Math.min.apply(null,itemArr) //獲取數組最小值(第一次就是數組的第一項0;)
var minIndex = itemArr.indexOf(minValue)//獲取最小值的下標;
$(this).css({//通過改變top left ;放入圖片的位置;
top:itemArr[minIndex],
left:$(this).outerWidth(true)*minIndex
})
itemArr[minIndex] += $(this).outerHeight(true);//更改添加后列的高度
})
}
function Scroll(){
var dataInt = {
'data':[{'src':'1.png'},{'src':'2.png'},{'src':'3.png'},{'src':'4.png'},{'src':'5.png'},{'src':'6.png'},{'src':'7.png'},
{'src':'8.png'},{'src':'9.png'},{'src':'10.png'},{'src':'11.png'},{'src':'12.png'},{'src':'13.png'},{'src':'14.png'}]
}
var isArrive= false;//防止多次滾動重復數據
if(checkScroll() && !isArrive){
var oParent = document.getElementsByClassName('content')[0];
for(var i =0;i<dataInt.data.length;i++){
isArrive=true;
var oDiv =document.createElement('div');//添加元素節點
oDiv.className ='item';
oDiv.innerHTML =''
oParent.appendChild(oDiv);
}
isArrive = false;
waterFull()
}
}
function checkScroll(){
var oParent = document.getElementsByClassName('content')[0];
var aDiv =oParent.getElementsByClassName('item');
var lastPinH=aDiv[aDiv.length-1].offsetTop+Math.floor(aDiv[aDiv.length-1].offsetHeight/2);
//創建【觸發添加塊框函數waterfall()】的高度:最后一個塊框的距離網頁頂部+自身高的一半(實現未滾到底就開始加載)
var scrollTop=$(window).scrollTop();//滾動高度
var winndowHeight=$(window).height(); //頁面高度
return (lastPinH<scrollTop+winndowHeight)? true : false ; //到達指定高度后 返回true,觸發waterfall()函數
}
return {
init:init
}
})()
WaterFull.init();
- 原生js代碼
function waterFull(){
var Oparent = document.getElementById('main');
var aPin =Oparent.getElementsByClassName('pin')//獲取存儲塊pin的數組;
var num =Math.floor(document.documentElement.clientWidth/aPin[0].offsetWidth)//獲取窗口每行能容納的個數
var pinHArr=[];//用于存儲 每列中的所有塊框相加的高度
for(var i =0 ; i<num;i++){
pinHArr[i]=0;
}
for(var i =0 ; i<aPin.length;i++){
//獲取PinHArr的最小值;
var minValue =Math.min.apply(null,pinHArr);
//獲取pinHArr最小值得索引;
var minIndex = pinHArr.indexOf(minValue);
aPin[i].style.top=minValue+'px';//用定位改變其top值
aPin[i].style.left=aPin[minIndex].offsetWidth*minIndex+'px';//用定位改變其left值
pinHArr[minIndex] += aPin[i].offsetHeight;//更改添加后列的高度
}
}
- css瀑布流效果:
- 關于css瀑布流:
方法有許多種,優缺點都有,但是本人建議用js或者jquery;因為畢竟是要向后端mock數據所以css布局不建議使用;就給出css3方法其中一種代碼
<style>
*{padding:0;margin:0;}
.clearfix:after,
.clearfix:before {
content: " ";
display: table;
}
.clearfix:after {
clear: both;
}
.main {
position: relative;
-webkit-column-width: 222px;
-moz-column-width: 222px;
/*column-width 屬性規定列的寬度。*/
-webkit-column-gap: 5px;
/*column-gap 屬性規定列之間的間隔。*/
-moz-column-gap: 5px;
}
.box {
float: left;
padding: 15px 0 0 15px;
transition: all 1s;
}
.box .pic {
width: 200px;
height: auto;
padding: 10px;
border-radius: 5px;
box-shadow: 0 0 5px #cccccc;
}
.box .pic img {
display: block;
width: 100%;
}
-
css3瀑布流布局:
我們將要用到的是CSS3新加的column屬性,通過指定容器的列個數column-count,列間距column-gap,列中間的邊框(間隔邊線)column-rule,列寬度column-width實現。優點:
1. 直接用CSS定義,方便快捷,是最好不過了;
2. 擴展方便。缺點:
1. 目前仍有部分瀏覽器不支持CSS3;
2.CSS3這種方式的數據排列是從上到下排列到一定高度后,再把剩余元素依次添加到下一列;
2.木桶布局
- 思路:
1.當圖片加載進來時,初始化new的image對象,給圖片定一個高度;獲取等比例下的寬度;
2.把圖片的寬高放入一個空數組,通過循環數組獲取圖片的總寬度;
3.拿獲取的總寬度跟容器寬度相比較,如果總寬度大于容器寬度,那就拿出最后一個圖片的寬度,直到總寬度小于容器的寬度。然后拉伸容器里的圖片讓,圖片填充這個容器的寬度(獲取容器里現在的最后高度)
4.再把數組清空,放入剛才被拿出的最后放不下那一項(重置數組總寬度)
5.寫一個函數渲染每排圖片(把新高度傳入進去)。
- 難點
1.當圖片加載進來時,初始化new的image對象,給圖片定一個高度;獲取等比例下的寬度;
loadImg:function(){//構建url就是一個接口;也可以是ajax;
var _this = this //保存作用于的this
var imgUrls = this.getImgUrls(40);//如果是ajax是不可能根據圖片地址獲取他的寬高的
$.each(imgUrls,function(idx,url){//所以循環這個數組,
var img = new Image();//創建一個圖片對象;
img.src =url;
img.onload =function(){
var imgInfo ={
target:$(img),//哪一張圖片
width:200*(img.width/img.height),// x/200=img.width/img.height
height:200//高度設為200;
}
_this.render(imgInfo);
}
})
},
2.把圖片的寬高放入一個空數組,通過循環數組獲取圖片的總寬度;
render: function(imgInfo){
var clientWidth = this.$ct.width();
var rowWidth = 0;
var newRowHeight = 0;
var lastImgInfo = imgInfo;
this.rowList.push(imgInfo);
for(var i=0; i< this.rowList.length; i++){
rowWidth = rowWidth + this.rowList[i].width;
}
3.那獲取的總寬度跟容器寬度相比較,如果總寬度大于容器寬度,那就拿出最后一個圖片的寬度,直到總寬度小于容器的寬度。然后拉伸容器里的圖片讓,圖片填充這個容器的寬度(獲取容器里現在的最后高度)
if(rowWidth > clientWidth){
this.rowList.pop();
rowWidth = rowWidth-lastImgInfo.width//目前每行的寬度;
newRowHeight = clientWidth*200/rowWidth;
// rowWidth/200 == clientWidth/ X
4.再把數組清空,放入剛才被拿出的最后放不下那一項(重置數組總寬度)
this.rowList = [];
this.rowList.push(imgInfo);
this.layout(newRowHeight);
5.寫一個函數渲染每排圖片(把新高度傳入進去)
layout: function(newRowHeight){
console.log('createRow');
var $rowCt = $('<div class="img-row"></div>');
$.each(this.rowList, function(idx, imgInfo){
var $imgCt = $('<div class="img-box"></div>'),
$img = $(imgInfo.target);
$img.height(newRowHeight);
$imgCt.append($img);
$rowCt.append($imgCt);
});
this.$ct.append($rowCt);
- 效果:
3.等高布局
思路:等高布局有幾種不同的方法如定位,但目前為止我認為瀏覽器兼容最好最簡便的應該是padding補償法。首先把列的padding-bottom設為一個足夠大的值,再把列的margin-bottom設一個與前面的padding-bottom的正值相抵消的負值,父容器設置超出隱藏,這樣子父容器的高度就還是它里面的列沒有設定padding-bottom時的高度,當它里面的任一列高度增加了,則父容器的高度被撐到它里面最高那列的高度,其他比這列矮的列則會用它們的padding-bottom來補償這部分高度差。因為背景是可以用在padding占用的空間里的,而且邊框也是跟隨padding變化的,所以就成功的完成了一個障眼法。
重點:
.wrap{
overflow: hidden;//父容器設置超出隱藏,這樣子父容器的高度就還是它里面的列沒有設定padding-bottom時的高度
}
.left{
float: left;
padding-bottom: 10000px;
margin-bottom: -10000px;
}
.right{
float: right;
padding-bottom: 10000px;
margin-bottom: -10000px;
}
- 看下效果:
- 代碼
<style>
.wrap{
width:100%;
background:#ccc;
overflow: hidden;
min-width: 600px;
}
.left{
width:300px;
float: left;
padding-bottom: 10000px;
margin-bottom: -10000px;
background: red;
text-align: center;
border: 1px saddlebrown solid;
}
.right{
width:300px;
float: right;
padding-bottom: 10000px;
margin-bottom: -10000px;
background:green;
text-align: center;
border: 1px saddlebrown solid;
}
h2{
padding: 10px;
}
</style>
</head>
<body>
<div class="wrap">
<div class="left">

</div>
<div class="right">

</div>
</div>
<button class="btn1">左側欄增加高度</button>
<button class="btn2">右側欄增加高度</button>
<script src="jquery-3.2.0.min.js"></script>
<script>
$('.btn1').on('click',function(){
$('.left').append('')
})
$('.btn2').on('click',function(){
$('.right').append('')
})
</script>
</body>
4. 圣杯布局
思路:
圣杯布局解決的問題是兩邊頂寬,中間自適應的三欄布局,中間欄要在放在文檔流前面以優先渲染。圣杯布局的三欄全部float浮動,但左右兩欄加上負margin讓其跟中間欄div并排,以形成三欄布局。解決”中間欄div內容不被遮擋“問題的思路:圣杯布局,為了中間div內容不被遮擋,將中間div設置了左右padding-left和padding-right后,將左右兩個div用相對布局position: relative并分別配合right和left屬性,以便左右兩欄div移動后不遮擋中間div。重點:
div{
float:left;
}
.wrap
{
padding-right: 100px;//空出左右位置給左右兩欄;
padding-left:100px
}
.left
{
margin-left: -100%;//左邊欄與中間攔并排;
position: relative;
left: -100px;//左邊的div寬度大小;
}
.right
{
margin-left: -100px;//右邊欄與中間攔并排;大小為右邊欄寬度;
position: relative;
left: 100px;//左邊的div寬度大小;
}
- 看下效果:
- 代碼
<style>
.wrap{
border: 1px saddlebrown solid;
padding-left:100px;
padding-right: 100px;
min-width: 600px;
}
.clear:after{
content:'';
display: block;
clear:both;
}
.main{
width:100%;
height: 200px;
float:left;
background:red;
}
.left{
float: left;
width:100px;
height: 100px;
background:green;
margin-left: -100%;
position: relative;
left: -100px;
}
.right
{
float: left;
width: 100px;
height: 100px;
background: pink;
margin-left: -100px;
position: relative;
left: 100px;
}
</style>
</head>
<body>
<div class="wrap clear">
<div class="main"></div>
<div class="left"></div>
<div class="right"></div>
</div>
</body>
5.雙飛翼布局:
思路:
圣杯布局和雙飛翼布局解決的問題是一樣的,就是兩邊頂寬,中間自適應的三欄布局,中間欄要在放在文檔流前面以優先渲染。圣杯布局和雙飛翼布局解決問題的方案在前一半是相同的,也就是三欄全部float浮動,但左右兩欄加上負margin讓其跟中間欄div并排,以形成三欄布局。不同在于解決”中間欄div內容不被遮擋“問題的思路不一樣;雙飛翼布局:為了中間div內容不被遮擋,直接在中間div內部創建子div用于放置內容,在該子div里用margin-left和margin-right為左右兩欄div留出位置。重點:
.main
{
width: 100%;
float: left;
}
.main .mainer//在中間div內部創建子div用于放置內容,在該子div里用margin-left和margin-right為左右兩欄div留出位置
{
margin-left: 120px;
margin-right: 120px;
}
.left
{
float: left;
margin-left: -100%; //左邊欄與中間攔并排;
}
.right
{
float: left;
margin-left: -100px; //右邊欄與中間攔并排
}
- 看下效果:
- 代碼:
.wrap
{
border: 1px saddlebrown solid;
min-width: 600px;
}
.clear:after
{
content: "";
display: block;
clear: both;
}
.main
{
width: 100%;
height: 200px;
float: left;
}
.main .mainer
{
background: black;
height: 200px;
margin-left: 120px;
margin-right: 120px;
}
.left
{
width:100px;
height: 100px;
background:green;
float: left;
margin-left: -100%;
}
.right
{
width: 100px;
height: 100px;
background: pink;
float: left;
margin-left: -100px;
}
</style>
</head>
<body>
<div class="wrap clear">
<div class="main">
<div class="mainer"></div>
</div>
<div class="left"></div>
<div class="right"></div>
</div>
</body>
- 圣杯雙飛翼的區別:
圣杯布局和雙飛翼布局解決的問題是一樣的,就是兩邊頂寬,中間自適應的三欄布局,中間欄要在放在文檔流前面以優先渲染。圣杯布局和雙飛翼布局解決問題的方案在前一半是相同的,也就是三欄全部float浮動,但左右兩欄加上負margin讓其跟中間欄div并排,以形成三欄布局。不同在于解決”中間欄div內容不被遮擋“問題的思路不一樣:圣杯布局,為了中間div內容不被遮擋,將中間div設置了左右padding-left和padding-right后,將左右兩個div用相對布局position: relative并分別配合right和left屬性,以便左右兩欄div移動后不遮擋中間div。雙飛翼布局,為了中間div內容不被遮擋,直接在中間div內部創建子div用于放置內容,在該子div里用margin-left和margin-right為左右兩欄div留出位置。
6. Flex布局:
Flex布局也是很常用的布局方法可以點擊鏈接去了解下Flex布局方法用法.
Flex布局
7.最后看下jquery實戰-無限加載-jsonp-瀑布流
希望對給位朋友有所幫助~~~
版權歸饑人谷__楠柒所有,如要轉載請請注明出處~