本文是我在学习了慕课网教程:瀑布流布局 后的学习笔记,具体代码见GitHub 。
瀑布流布局 适合于小数据块,每个数据块内容相近且没有侧重。通常,随着页面滚动条向下滚动,这种布局还会不断加载数据块并附加至当前尾部。
我们可以用多种方法实现瀑布流布局,如纯 JavaScript 方法实现,jQuery
方法以及使用 CSS3 实现。
网页结构与布局
先来看一下需要实现的效果。
瀑布流布局
可以看出图片之间等宽但不等高,相互之间有间隔,当页面滚动到底部时,加载更多的图片。
我们把所有的内容放在一个div
中。
每一张图片放在单独的div
中。
1 2 3 4 5 6 7 8 9 10 <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 >
然后设置 CSS
样式。内部的图片box
需要设置为绝对定位,相对其已定位的父元素进行定位,因此先将
main
容器设置为相对定位。
图片之间的间距可以用内边距(padding)或外边距(margin)来设置,由于之后我们需要用offsetWidth
这个属性来获得元素的宽,而offset
属性是不包括
margin 的,为了方便起见,使用padding
来设置间距。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 #main { position : relative; } .box { padding : 15px 0 0 15px ; float : left; } .pic { padding : 10px ; border : 1px solid #cccccc ; border-radius : 5px ; box-shadow : 0 0 5px #cccccc ; } .pic img { width : 165px ; height : auto; }
此时的效果如下:
瀑布流布局
可以看出离想要的效果还有一些差距,我们希望每一行图片排满后,下一行的图片能自动在排在高度最小的一列。这个效果将用
javascript 实现。
offsetWidth属性
用纯 JavaScript 实现效果
先定义两个函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 function getByClass (parent, className ) { var boxArray = []; var oElements = parent.getElementsByTagName('*' ); for (var i = 0 ; i < oElements.length; i++) { if (oElements[i].className == className) { boxArray.push(oElements[i]); } } return boxArray; } function getIndex (arr, val ) { for (var i = 0 ; i < arr.length; i++) { if (arr[i] === val) { return i; } } }
定义一个waterfall()
函数,设置页面的列数及居中,计算当前每一列的高度。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 function waterfall (parent, box ) { var oParent = document .getElementById(parent); var oBoxes = getByClass(oParent, box); var oBoxWidth = oBoxes[0 ].offsetWidth; var cols = Math .floor(document .documentElement.clientWidth / oBoxWidth); oParent.style.cssText = 'width:' + oBoxWidth * cols + 'px; margin:0 auto' ; var heightArray = []; for (var i = 0 ; i < oBoxes.length; i++) { if (i < cols) { heightArray.push(oBoxes[i].offsetHeight); } else { var minHeight = Math .min.apply(null , heightArray); var index = getIndex(heightArray, minHeight); oBoxes[i].style.position = 'absolute' ; oBoxes[i].style.top = minHeight + 'px' ; oBoxes[i].style.left = oBoxWidth * index + 'px' ; heightArray[index] += oBoxes[i].offsetHeight; } } }
调用waterfall()
函数,保证每张图片排在正确的位置上。
最后实现滚动加载的功能,当最后一个数据块已经有一半出现在页面上时,进行加载。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 function checkScrollSlide ( ) { var oParent = document .getElementById('main' ); var oBoxes = getByClass(oParent, 'box' ); var lastBoxHeight = oBoxes[oBoxes.length-1 ].offsetTop + Math .floor(oBoxes[oBoxes.length-1 ].offsetHeight / 2 ); var scrollTop = document .body.scrollTop || document .documentElement.scrollHeight; var height = document .body.clientHeight || document .documentElement.clientHeight; return (lastBoxHeight < scrollTop + height); } var dataInt = {"data" :[{"src" :'0.jpg' }, {"src" :'2.jpg' }, {"src" :'3.jpg' }, {"src" :'4.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' ; oParent.appendChild(oBox); var 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' ); } }
完整代码
用 jQuery 实现效果
用 jQuery 实现的思路与之前相同,只不过语法更简单。
jQuery
代码实现
参考资料