瀑布流效果已经成为展示类型网站的首选,所以有必要掌握其实现过程。实现这个效果目前有三种方法,分别为:JavaScript原生方法、jQuery方法、CSS3多栏布局。
一、其中JavaScript方法就不多总结了,JQuery方法可以大大简洁JavaScript代码量。直接上jQuery代码
<pre name="code" class="html"><!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>瀑布流</title>
<style type="text/css">
* {
margin: 0;
padding: 0;
}
article {
position: relative;
margin: auto 40px;
width: 100%;
}
article .box {
position: relative;
float: left;
}
article .box .content {
padding: 10px;
border: 1px solid #ccc;
border-radius: 5px;
}
article .box .content img {
width: 280px;
height: auto;
}
</style>
</head>
<body>
<article>
<div class="box">
<div class="content">
<img src="images/1.jpg">
</div>
</div>
<div class="box">
<div class="content">
<img src="images/2.jpg">
</div>
</div>
<div class="box">
<div class="content">
<img src="images/3.jpg">
</div>
</div>
<div class="box">
<div class="content">
<img src="images/4.jpg">
</div>
</div>
<div class="box">
<div class="content">
<img src="images/5.jpg">
</div>
</div>
<div class="box">
<div class="content">
<img src="images/6.jpg">
</div>
</div>
<div class="box">
<div class="content">
<img src="images/7.jpg">
</div>
</div>
<div class="box">
<div class="content">
<img src="images/8.jpg">
</div>
</div>
<div class="box">
<div class="content">
<img src="images/1.jpg">
</div>
</div>
<div class="box">
<div class="content">
<img src="images/2.jpg">
</div>
</div>
<div class="box">
<div class="content">
<img src="images/3.jpg">
</div>
</div>
<div class="box">
<div class="content">
<img src="images/4.jpg">
</div>
</div>
<div class="box">
<div class="content">
<img src="images/5.jpg">
</div>
</div>
<div class="box">
<div class="content">
<img src="images/6.jpg">
</div>
</div>
<div class="box">
<div class="content">
<img src="images/7.jpg">
</div>
</div>
<div class="box">
<div class="content">
<img src="images/8.jpg">
</div>
</div>
<div class="box">
<div class="content">
<img src="images/1.jpg">
</div>
</div>
<div class="box">
<div class="content">
<img src="images/2.jpg">
</div>
</div>
<div class="box">
<div class="content">
<img src="images/3.jpg">
</div>
</div>
<div class="box">
<div class="content">
<img src="images/4.jpg">
</div>
</div>
<div class="box">
<div class="content">
<img src="images/5.jpg">
</div>
</div>
<div class="box">
<div class="content">
<img src="images/6.jpg">
</div>
</div>
<div class="box">
<div class="content">
<img src="images/7.jpg">
</div>
</div>
<div class="box">
<div class="content">
<img src="images/8.jpg">
</div>
</div>
</article>
<script type="text/javascript" src="js/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$(window).on("load", function() {
imgLocation();
var dataImg = {
"data": [{"src": "1.jpg"},{"src": "2.jpg"}, {"src": "3.jpg"}, {"src": "4.jpg"}, {"src": "5.jpg"}, {"src": "6.jpg"}, {"src": "7.jpg"}, {"src": "8.jpg"}]};
$(window).on("scroll", function() {
if (scrollSide()) {
$.each(dataImg.data, function(index, value) {
var box = $("<div>").addClass("box").appendTo($("article"));
var content = $("<div>").addClass("content").appendTo(box);
$("<img>").attr("src", "./images/" + $(value).attr("src")).appendTo(content)
})
imgLocation();
}
});
});
});
function scrollSide() {
var box = $(".box");
var lastboxHeight = box.last().offset().top + Math.floor(box.last().height() / 2)
var documentHeight = $(window).height();
var scrollHeight = $(window).scrollTop();
return (lastboxHeight < scrollHeight + documentHeight) ? true : false;
}
function imgLocation() {
var box = $(".box");
var boxWidth = box.eq(0).width();
var num = Math.floor($("article").width() / boxWidth);
var boxArr = [];
box.each(function(i, value) {
var boxHeight = box.eq(i).height();
if (i < num) {
boxArr[i] = boxHeight;
} else {
var minboxHeight = Math.min.apply(null, boxArr);
var minboxIndex = $.inArray(minboxHeight, boxArr);
$(value).css({
"position": "absolute",
"top": minboxHeight,
"left": box.eq(minboxIndex).position().left
});
boxArr[minboxIndex] += box.eq(i).height();
}
});
}
</script>
</body>
</html>
</pre>
以上是jQuery实现瀑布流的全部代码,下面对其逐个分析。
1.jQuery实现瀑布流布局图片定位
function imgLocation() {
var box = $("article>div"); /*匹配articl以下所有一级div,也可以用$(".box")实现*/
var boxWidth = box.eq(0).width(); /*获取每一个图片的宽度*/
var num = Math.floor($("article").width() / boxWidth); /*获取列数,用math.floor取整*/
var boxArr = []; /*便利前六张图片的div,将其高度放入数组内*/
/*遍历每一个box元素*/
box.each(function(index, value) {
/*index为每一个元素的索引*/
/*value为所有class为box的每一个div,是一个DOM对象*/
var boxHeight = box.eq(index).height(); /*获取每一个box的高*/
if (index < num) {
//设置第一排图片的位置
boxArr[index] = boxHeight;
} else {
var minboxHeight = Math.min.apply(null, boxArr); /*获取数组内高度最小的值,apply的第一个参数传递作用域,第二个参数传递数组。Math.min.apply(null, [1, 2, 3]) 等价于 Math.min(1, 2, 3)*/
var minboxIndex = $.inArray(minboxHeight, boxArr); /*获取最小高度的box在数组中的索引,其中$.inArray(value,array)方法为确定第一个参数在数组中的位置,从0开始计数(如果没有找到则返回 -1 )*/
//设置从第二排开始所有图片的位置
//将DOM对象value转化为jQuery对象$(value)才能使用jQuery方法
$(value).css({
"position": "absolute",
"top": minboxHeight,
"left": box.eq(minboxIndex).position().left
});
boxArr[minboxIndex] += box.eq(index).height();/*改变数组值*/
}
});
2.jQuery实现瀑布流布局图片加载功能
jQuery两大优点:支持连缀,隐式迭代。jQuery方法只能由jQuery对象使用
$(document).ready(function() {二. CSS3多栏布局实现瀑布流效果
$(window).on("load", function() {
imgLocation();
var dataImg = {
"data": [{"src": "1.jpg"}, {"src": "2.jpg"}, {"src": "3.jpg"}, {"src": "4.jpg"}, {"src": "5.jpg"}, {"src": "6.jpg"}, {"src": "7.jpg"}, {"src": "8.jpg"}]
}; /*遍历JASON格式数据*/
//绑定一个滚动条事件
$(window).on("scroll", function() {
if (scrollSide()) {
//遍历dataImg数据data属性,$.each()方法不同于例遍 jQuery 对象的 $().each() 方法,此方法可用于例遍任何对象。回调函数拥有两个参数:第一个为对象的成员或数组的索引,第二个为对应变量或内容。
$.each(dataImg.data, function(index, value) {
var box = $("<div>").addClass("box").appendTo($("article")); /*创建class为box的div*/
var content = $("<div>").addClass("content").appendTo(box);/*创建class为content的div于box中*/
//.attr()既可以获取属性又可以设置属性
$("<img>").attr("src", "./images/" + $(value).attr("src")).appendTo(content)/*创建图片与content中*/
})
//调用图片定位函数
imgLocation();
}
});
});
});
//检测是否具备加载图片条件
function scrollSide() {
//判断最后一张图片距顶部的距离
var lastbox = $(".box").last(); /*获取最后一张图片*/
var lastboxHeight = lastbox.offset().top + Math.floor(lastbox.height() / 2) /*获取最后一张图片的一半顶部的距离*/
var documentHeight = $(window).height(); /*获取页面高度*/
var scrollHeight = $(window).scrollTop(); /*获取滚动条滚动距离*/
return (lastboxHeight < scrollHeight + documentHeight) ? true : false;
}
CSS3实现瀑布流效果就是用到了CSS3新增属性中的多列(Multi-Column)属性。
以下为CSS代码
article {回顾一下CSS3中多列属性:
position: relative;
margin: auto 40px;
width: 100%;
-webkit-column-width:300px;
-moz-column-width:300px;
-o-column-width:300px;
-ms-column-width:300px;
}
article .box {
position: relative;
float: left;
}
article .box .content {
padding: 10px;
border: 1px solid #ccc;
border-radius: 5px;
}
article .box .content img {
width: 280px;
height: auto;
}
1.column-width用长度值来定义列宽。不允许负值;
2.column-count用整数值来定义列数。不允许负值;
3.column-gap用长度值来定义列与列之间的间隙。不允许负值;
4.column-rule:<'column-rule-width'>||<'column-rule-style'>||<'column-rule-color'>
column-rule-width:设置或检索对象的列与列之间的边框厚度。
olumn-rule-style:设置或检索对象的列与列之间的边框样式。
column-rule-color:设置或检索对象的列与列之间的边框颜色。
注意:1.column的浏览器兼容问题,不同内核要写其前缀-webkit -ms -o -moz
2.column-width 和column-count没有必要同时出现
3.column-rule设置列与列之间的边框
4.column-gap 设置列间距,不一定定义多少,实际就显示多少。其计算规则:用当前浏览器宽口宽除以定义的列宽,剩下的距离平均分配。
三、jQuery与CSS3实现瀑布流方法比较
1.jQuery方式:需要计算,列数等于浏览器窗口宽度/图片宽度,图片定位是根据每一列数据库的高度计算接下来图片的位置。
2.CSS3方式:
a.不需要计算,浏览器自动计算,只需设置1列宽,性能高
b.列宽随着浏览器宽口大小进行改变,用户体验不好;
c.图片排序按照垂直顺序排列,打乱图片显示顺序
d.图片加载还是需要js
补充:
在实际工作中还需要添加些许代码来应对浏览器加载图片的各种情况,现添加代码如下:
addImageToContainer(dataImg.data);
window.onscroll = function(e) {
if ($(window).scrollTop() + $(window).height() >= $(document).height()) {
addImageToContainer(dataImg.data);
}
}
function addImageToContainer(srcList) {
//处理img src
srcList = srcList.map(function(data) {
return "./images/" + data.src;
});
finishSameImageLoaded(srcList, function() {
$.each(srcList, function(index, value) {
var box = $("<div>").addClass("box").appendTo($("article"));
var content = $("<div>").addClass("content").appendTo(box);
$("<img>").attr("src", value).appendTo(content);
});
imgLocation();
})
}
function finishSameImageLoaded(srcArr, done) {
var DeferList = srcArr.map(function(src, index, arr) {
var defer = $.Deferred();
var img = new Image();
img.src = src;
if (img.complete) {
defer.resolve();
} else {
img.onload = function() {
defer.resolve();
}
}
return defer;
});
$.when.apply($, DeferList).done(done);
}