瀑布流的实现方式(原生js+jquery+css3)


Posted in Javascript onJune 28, 2020

前言

项目需求要弄个瀑布流的页面,用的是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 +

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
javascript parseInt 大改造
Sep 27 Javascript
JavaScript 存在陷阱 删除某一区域所有节点
May 10 Javascript
javascript实现浏览器窗口传递参数的方法
Sep 03 Javascript
node.js中的http.response.removeHeader方法使用说明
Dec 14 Javascript
IE10中flexigrid无法显示数据的解决方法
Jul 26 Javascript
JavaScript原生xmlHttp与jquery的ajax方法json数据格式实例
Dec 04 Javascript
JS实现表单验证功能(验证手机号是否存在,验证码倒计时)
Oct 11 Javascript
JS实现图片上传预览功能
Nov 21 Javascript
浅谈Node Inspector 代理实现
Oct 19 Javascript
详解vue中$nextTick和$forceUpdate的用法
Dec 11 Javascript
Vue实现跑马灯效果
May 25 Javascript
uni-app实现获取验证码倒计时功能
Nov 01 Javascript
jquery计算出left和top,让一个div水平垂直居中的简单实例
Jul 13 #Javascript
Javascript类型系统之undefined和null浅析
Jul 13 #Javascript
JS基础随笔(菜鸟必看篇)
Jul 13 #Javascript
Bootstrap的Refresh Icon也spin起来
Jul 13 #Javascript
jQuery实现div横向拖拽排序的简单实例
Jul 13 #Javascript
用jQuery向div中添加Html文本内容的简单实现
Jul 13 #Javascript
使用jQuery加载html页面到指定的div实现方法
Jul 13 #Javascript
You might like
使用php批量删除数据库下所有前缀为prefix_的表
2014/06/09 PHP
ThinkPHP通过AJAX返回JSON的两种实现方法
2014/12/18 PHP
php封装db类连接sqlite3数据库的方法实例
2017/12/19 PHP
ThinkPHP框架获取最后一次执行SQL语句及变量调试简单操作示例
2018/06/13 PHP
PHP strripos函数用法总结
2019/02/11 PHP
[对联广告] JS脚本类
2006/08/27 Javascript
基于jquery的拖动布局插件
2011/11/25 Javascript
js判读浏览器是否支持html5的canvas的代码
2013/11/18 Javascript
javascript操作css属性
2013/12/30 Javascript
javascript正则表达式定义(语法)总结
2016/01/08 Javascript
JavaScript中style.left与offsetLeft的使用及区别详解
2016/06/08 Javascript
原生JS获取元素集合的子元素宽度实例
2016/12/14 Javascript
jQuery窗口拖动功能的实现代码
2017/02/04 Javascript
基于模板引擎Jade的应用(详解)
2017/12/12 Javascript
微信小程序实现自定义picker选择器弹窗内容
2020/05/26 Javascript
在Express中提供静态文件的实现方法
2019/10/17 Javascript
JS数组Reduce方法功能与用法实例详解
2020/04/29 Javascript
python自定义异常实例详解
2017/07/11 Python
使用python对excle和json互相转换的示例
2018/10/23 Python
深入浅析python 协程与go协程的区别
2019/05/09 Python
pytorch实现onehot编码转为普通label标签
2020/01/02 Python
浅析Python 抽象工厂模式的优缺点
2020/07/13 Python
Python使用jpype模块调用jar包过程解析
2020/07/29 Python
html5 的a标签 Href 拨电话的写法
2013/11/04 HTML / CSS
Timex手表官网:美国运动休闲手表品牌
2017/01/28 全球购物
Lookfantastic法国官网:英国知名美妆购物网站
2017/10/28 全球购物
short s1 = 1; s1 = s1 + 1;有什么错? short s1 = 1; s1 += 1;有什么错?
2014/09/26 面试题
标准毕业生自荐信范文
2013/11/04 职场文书
幼儿园小班家长寄语
2014/04/02 职场文书
作风整顿个人剖析材料
2014/10/06 职场文书
2015年电工工作总结
2015/04/10 职场文书
安全承诺书格式范本
2015/04/28 职场文书
农村结婚典礼主持词
2015/06/29 职场文书
Python的这些库,你知道多少?
2021/06/09 Python
Python+Appium自动化测试的实战
2021/06/30 Python
python中pd.cut()与pd.qcut()的对比及示例
2022/06/16 Python