这篇文章主要为大家详细介绍了原生 js+jquery+css3 实现瀑布流的相关代码,三种实现瀑布流的方法,感兴趣的小伙伴们可以参考一下
jQuery 是一个兼容多浏览器的 javascript 框架,核心理念是 write less,do more(写得更少, 做得更多)。jQuery 在 2006 年 1 月由美国人 John Resig 在纽约的 barcamp 发布,吸引了来自世界各地的众多 JavaScript 高手加入,由 Dave Methvin 率领团队进行开发。
前言
项目需求要弄个瀑布流的页面,用的是 waterfall 这个插件,感觉还是可以的,项目赶就没自己的动手写。最近闲来没事,就自己写个。大致思路理清楚,还是挺好实现的...
原生 javascript 版
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>
- 瀑布流-javascript
- </title>
- <style>
- *{margin:0;padding:0;} #content{position: relative;margin:0 auto;} .box{padding:10px;float:
- left;}/*首行浮动,第二行开始绝对定位*/ .box img{width: 180px;height:auto;display: block;}
- </style>
- <script>
- window.onload = function() {
- waterfall('content', 'box');
- //改变窗口大小时,重新排列
- window.onresize = function() {
- waterfall('content', 'box');
- }
- //如果数据不够,没出现滚动条,自动加载数据
- var time = setInterval(function() {
- if (checkscrollside()) {
- addDate(); //插入数据
- waterfall('content', 'box'); //加载完数据从新排列
- } else {
- clearInterval(time);
- window.onscroll = function() {
- if (checkscrollside()) {
- addDate();
- waterfall('content', 'box');
- };
- }
- }
- },
- 1000)
- }
- // 数据插入
- function addDate() {
- var dataInt = ['1.jpg', '2.jpg', '3.jpg', '4.jpg', '5.jpg', '6.jpg', '7.jpg', '8.jpg']; //模拟数据,也可以是对象
- var oParent = document.getElementById('content');
- for (var i = 0; i < dataInt.length; i++) { //循环插入数据
- var oBox = document.createElement('div');
- oBox.className = 'box';
- oParent.appendChild(oBox);
- var oImg = document.createElement('img');
- oImg.src = './img/' + dataInt[i];
- oBox.appendChild(oImg);
- }
- }
- //主函数
- function waterfall(parentID, childClass) {
- var oParent = document.getElementById(parentID);
- var arrBox = getClassObj(parentID, childClass); // getClassObj()获取子class的数组
- var iBoxW = arrBox[0].offsetWidth; // 获取瀑布流块的宽度
- var num = Math.floor(document.documentElement.clientWidth / iBoxW); //计算窗口能容纳几列
- oParent.style.width = iBoxW * num + 'px'; //设置父级宽度
- var arrBoxH = []; //数组,用于存储每列中的所有块框相加的高度
- for (var i = 0; i < arrBox.length; i++) { //遍历数组瀑布流 块
- var boxH = arrBox[i].offsetHeight; //获取当前块的高度
- if (i < num) {
- arrBox[i].style.cssText = ""; //防止用户改变窗口大小,到时样式出错
- arrBoxH[i] = boxH; //第一行中的num个块box 先添加进数组arrBoxH
- } else {
- var minH = Math.min.apply(null, arrBoxH); //获取数组arrBoxH中的最小值minH
- var minHIndex = getminHIndex(arrBoxH, minH); //遍历数组获取最小值minH的索引
- arrBox[i].style.position = 'absolute'; //设置绝对位移
- arrBox[i].style.top = minH + 'px';
- arrBox[i].style.left = minHIndex * iBoxW + 'px'; //也可以直接获取arrBox[minHIndex].offsetLeft
- arrBoxH[minHIndex] += arrBox[i].offsetHeight; //添加后,更新最小列高
- }
- }
- }
- //获取子class的数组
- function getClassObj(parentID, childClass) {
- var oParent = document.getElementById(parentID);
- var allChildObj = oParent.getElementsByTagName('*'); //获取父级下的所有子集
- var childObj = []; //创建一个数组 用于收集子元素
- for (var i = 0; i < allChildObj.length; i++) { //遍历子元素、判断类别、压入数组
- if (allChildObj[i].className == childClass) {
- childObj.push(allChildObj[i]);
- }
- };
- return childObj;
- }
- //获取数组最小值的索引
- function getminHIndex(arr, minH) {
- for (var i in arr) {
- if (arr[i] == minH) {
- return i;
- }
- }
- }
- // 判断滚动条是否到底部
- function checkscrollside() {
- var arrBox = getClassObj("content", 'box');
- //获取最后一个瀑布流块的高度:距离网页顶部(实现未滚到底就开始加载)
- var lastBoxH = arrBox[arrBox.length - 1].offsetTop;
- var scrollTop = document.documentElement.scrollTop || document.body.scrollTop; //获取滚动条卷走的高度
- var documentH = document.documentElement.clientHeight; //显示页面文档的高
- return (lastBoxH < scrollTop + documentH) ? true: false; //到达指定高度后 返回true,触发waterfall()函数
- }
- </script>
- </head>
- <body>
- <div id="content">
- <div class="box">
- <img src="img/0.jpg" alt="">
- </div>
- <div class="box">
- <img src="img/1.jpg" alt="">
- </div>
- <div class="box">
- <img src="img/2.jpg" alt="">
- </div>
- <div class="box">
- <img src="img/3.jpg" alt="">
- </div>
- <div class="box">
- <img src="img/4.jpg" alt="">
- </div>
- <div class="box">
- <img src="img/5.jpg" alt="">
- </div>
- <div class="box">
- <img src="img/6.jpg" alt="">
- </div>
- <div class="box">
- <img src="img/7.jpg" alt="">
- </div>
- <div class="box">
- <img src="img/8.jpg" alt="">
- </div>
- <div class="box">
- <img src="img/9.jpg" alt="">
- </div>
- <div class="box">
- <img src="img/10.jpg" alt="">
- </div>
- </div>
- </body>
- </html>
jquery 版本
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>
- 瀑布流-jquery
- </title>
- <style>
- *{margin:0;padding:0;} #content{position: relative;margin:0 auto;} .box{padding:10px;float:
- left;} .box img{width: 180px;height:auto;display: block;}
- </style>
- <script src="js/jquery-1.11.1.min.js">
- </script>
- <script>
- $(function() {
- waterfall();
- //改变窗口大小时,重新排列
- $(window).resize(function() {
- waterfall();
- })
- //如果数据不够,没出现滚动条,自动加载数据
- var time = setInterval(function() {
- if (checkscrollside()) {
- addDate(); //插入数据
- waterfall(); //加载完数据从新排列
- } else {
- clearInterval(time);
- $(window).scroll(function() {
- if (checkscrollside()) {
- addDate();
- waterfall();
- };
- })
- }
- },
- 1000)
- })
- // 数据插入
- function addDate() {
- var dataInt = ['1.jpg', '2.jpg', '3.jpg', '4.jpg', '5.jpg', '6.jpg', '7.jpg', '8.jpg']; //模拟数据,也可以是对象
- var oParent = $('#content');
- for (var i = 0; i < dataInt.length; i++) { //循环插入数据
- oParent.append('<div class="box"><img src="./img/' + dataInt[i] + '" alt=""></div>');
- }
- }
- //主函数
- function waterfall() {
- var arrBox = $('#content').children('.box'); // box对象
- var iBoxW = arrBox.eq(0).innerWidth(); // 获取瀑布流块的宽度,注意width(),跟innerWidth()的区别
- var num = Math.floor($(window).width() / iBoxW); //计算窗口能容纳几列
- $('#content').css('width', iBoxW * num); //设置父级宽度
- var arrBoxH = []; //数组,用于存储每列中的所有块框相加的高度
- for (var i = 0; i < arrBox.length; i++) { //遍历数组瀑布流 块
- var boxH = arrBox.eq(i).innerHeight(); //获取当前块的高度
- if (i < num) {
- arrBox.eq(i).attr('style', ''); //防止用户改变窗口大小,到时样式出错
- arrBoxH[i] = boxH; //第一行中的num个块box 先添加进数组arrBoxH
- } else {
- var minH = Math.min.apply(null, arrBoxH); //获取数组arrBoxH中的最小值minH
- var minHIndex = $.inArray(minH, arrBoxH); //使用jquery提供的工具
- arrBox.eq(i).css({
- 'position': 'absolute',
- 'top': minH,
- 'left': minHIndex * iBoxW
- }); //设置定位
- arrBoxH[minHIndex] += arrBox.eq(i).innerHeight(); //添加后,更新最小列高
- }
- }
- }
- // 判断滚动条是否到底部
- function checkscrollside() {
- var arrBox = $('#content').children('.box');
- //获取最后一个瀑布流块的高度:距离网页顶部(实现未滚到底就开始加载)
- var lastBoxH = arrBox.eq(arrBox.length - 1).offset().top;
- var scrollTop = $(window).scrollTop() //获取滚动条卷走的高度
- var documentH = $(window).height();; //显示页面文档的高
- return (lastBoxH < scrollTop + documentH) ? true: false; //到达指定高度后 返回true,触发waterfall()函数
- }
- </script>
- </head>
- <body>
- <div id="content">
- <div class="box">
- <img src="img/0.jpg" alt="">
- </div>
- <div class="box">
- <img src="img/1.jpg" alt="">
- </div>
- <div class="box">
- <img src="img/2.jpg" alt="">
- </div>
- <div class="box">
- <img src="img/3.jpg" alt="">
- </div>
- <div class="box">
- <img src="img/4.jpg" alt="">
- </div>
- <div class="box">
- <img src="img/5.jpg" alt="">
- </div>
- <div class="box">
- <img src="img/6.jpg" alt="">
- </div>
- <div class="box">
- <img src="img/7.jpg" alt="">
- </div>
- <div class="box">
- <img src="img/8.jpg" alt="">
- </div>
- <div class="box">
- <img src="img/9.jpg" alt="">
- </div>
- <div class="box">
- <img src="img/10.jpg" alt="">
- </div>
- </div>
- </body>
- </html>
大致思路
1. 先让第一行的浮动
2. 计算第一行的每个块的高度
3. 遍历第一行之后的每一个块,逐个放在最小高度的下面
4. 加载数据插入最后,再重新计算
注意点
a. 原生 js
1. 定义了 getClassObj() 函数用于获取 class 类的对象,方便调用。考虑了兼容性 getElementsByClassName
2. 定义了 getminHIndex() 函数用户获取最小值的索引
3. 设置块与块之间的距离最好用 padding,这样的话 offsetHeight 可以直接获取得到高度。如果设置 margin 则得多加个外边距的距离
4. 代码中设置了定时器加载数据,其实可以省略,只要保证第一次加载的数据能满屏就可以。如果没出现滚动条的话 onscroll 事件是不会执行到的。也就没办法加载数据了
5. 代码中的计算宽度也可以修改,设计的页面是定宽的瀑布流的话。这里主要是做了响应式的处理
- var arrBox=getClassObj(parentID,childClass);// getClassObj()获取子class的数组
- var iBoxW=arrBox[0].offsetWidth;// 获取瀑布流块的宽度
- var num=Math.floor(document.documentElement.clientWidth/iBoxW);//计算窗口能容纳几列
- oParent.style.width=iBoxW*num+'px';//设置父级宽度
6. 每设置一块位移,都要在列高的数组上增加数值,防止块重叠
- arrBox[i].style.position='absolute';//设置绝对位移
- arrBox[i].style.top=minH+'px';
- arrBox[i].style.left=minHIndex*iBoxW+'px';//也可以直接获取arrBox[minHIndex].offsetLeft
- arrBoxH[minHIndex]+=arrBox[i].offsetHeight;//添加后,更新最小列高
b.jquery
1. 思路是跟 js 一样的,只是 jquery 封装了很多方法,让我们简便的就实现了
2. 注意 width(), 跟 innerWidth() 的区别。前者只能获取宽度值(不包括补白 padding)
css3 版本
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>
- 瀑布流-css3
- </title>
- <style>
- *{margin:0;padding:0;} #content{margin:0 auto;position: relative;width:1200px;column-count:6;-moz-column-count:6;-webkit-column-count:6;}
- .box{padding:10px;width: 180px;} .box img{width: 180px;height:auto;display:
- block;}
- </style>
- <script>
- window.onload = function() {
- //如果数据不够,没出现滚动条,自动加载数据
- var time = setInterval(function() {
- if (checkscrollside()) {
- addDate(); //插入数据
- } else {
- clearInterval(time);
- window.onscroll = function() {
- if (checkscrollside()) {
- addDate();
- };
- }
- }
- },
- 1000)
- }
- // 数据插入
- function addDate() {
- var dataInt = ['1.jpg', '2.jpg', '3.jpg', '4.jpg', '5.jpg', '6.jpg', '7.jpg', '8.jpg']; //模拟数据,也可以是对象
- var oParent = document.getElementById('content');
- for (var i = 0; i < dataInt.length; i++) { //循环插入数据
- var oBox = document.createElement('div');
- oBox.className = 'box';
- oParent.appendChild(oBox);
- var oImg = document.createElement('img');
- oImg.src = './img/' + dataInt[i];
- oBox.appendChild(oImg);
- }
- }
- //获取子class的数组
- function getClassObj(parentID, childClass) {
- var oParent = document.getElementById(parentID);
- var allChildObj = oParent.getElementsByTagName('*'); //获取父级下的所有子集
- var childObj = []; //创建一个数组 用于收集子元素
- for (var i = 0; i < allChildObj.length; i++) { //遍历子元素、判断类别、压入数组
- if (allChildObj[i].className == childClass) {
- childObj.push(allChildObj[i]);
- }
- };
- return childObj;
- }
- // 判断滚动条是否到底部
- function checkscrollside() {
- var arrBox = getClassObj("content", 'box');
- //获取最后一个瀑布流块的高度:距离网页顶部(实现未滚到底就开始加载)
- var lastBoxH = arrBox[arrBox.length - 1].offsetTop;
- var scrollTop = document.documentElement.scrollTop || document.body.scrollTop; //获取滚动条卷走的高度
- var documentH = document.documentElement.clientHeight; //显示页面文档的高
- return (lastBoxH < scrollTop + documentH) ? true: false; //到达指定高度后 返回true,触发waterfall()函数
- }
- </script>
- </head>
- <body>
- <div id="content">
- <div class="box">
- <img src="img/0.jpg" alt="">
- </div>
- <div class="box">
- <img src="img/1.jpg" alt="">
- </div>
- <div class="box">
- <img src="img/2.jpg" alt="">
- </div>
- <div class="box">
- <img src="img/3.jpg" alt="">
- </div>
- <div class="box">
- <img src="img/4.jpg" alt="">
- </div>
- <div class="box">
- <img src="img/5.jpg" alt="">
- </div>
- <div class="box">
- <img src="img/6.jpg" alt="">
- </div>
- <div class="box">
- <img src="img/7.jpg" alt="">
- </div>
- <div class="box">
- <img src="img/8.jpg" alt="">
- </div>
- <div class="box">
- <img src="img/9.jpg" alt="">
- </div>
- <div class="box">
- <img src="img/10.jpg" alt="">
- </div>
- </div>
- </body>
- </html>
注意点
1. 滚动加载还是得另外加 js
2. 加载的数据,是竖向排列的。体验不是很友好
3. 有兼容性问题,Internet Explorer 10 +
来源: http://www.phperz.com/article/17/0303/264296.html