瀑布流的实现方式(原生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 相关文章推荐
图标线性回归斜着移动到指定的位置
Aug 16 Javascript
jquery操作select大全
Apr 25 Javascript
jQuery的one()方法用法实例
Jan 19 Javascript
javascript高级编程之函数表达式 递归和闭包函数
Nov 29 Javascript
JS中mouseover和mouseout多次触发问题如何解决
Jun 06 Javascript
Bootstrap Navbar Component实现响应式导航
Oct 08 Javascript
JavaScript下拉菜单功能实例代码
Mar 01 Javascript
AngularJS双向绑定和依赖反转实例详解
Apr 15 Javascript
vue+axios+element ui 实现全局loading加载示例
Sep 11 Javascript
bootstrap-table实现表头固定以及列固定的方法示例
Mar 07 Javascript
记录一次完整的react hooks实践
Mar 11 Javascript
jquery 验证用户名是否重复代码实例
May 14 jQuery
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
阿里对象存储OSS在laravel框架中的使用方法
2019/10/13 PHP
JS处理VBArray的函数使用说明
2008/05/11 Javascript
表格 隔行换色升级版
2009/11/07 Javascript
jquery checkbox全选、取消全选实现代码
2010/03/05 Javascript
Javascript中获取出错代码所在文件及行数的代码
2010/09/23 Javascript
表单JS弹出填写提示效果代码
2011/04/16 Javascript
尝试动手制作javascript放大镜效果
2015/12/25 Javascript
node.js插件nodeclipse安装图文教程
2020/10/19 Javascript
微信小程序 页面跳转传参详解
2016/10/28 Javascript
bootstrap fileinput完整实例分享
2016/11/08 Javascript
原生js实现回复评论功能
2017/01/18 Javascript
js中作用域的实例解析
2017/03/16 Javascript
vue数组对象排序的实现代码
2018/06/20 Javascript
Three.js实现简单3D房间布局
2018/12/30 Javascript
JavaScript简单编程实例学习
2020/02/14 Javascript
[56:47]Ti4 循环赛第三日 iG vs Liquid
2014/07/12 DOTA
[04:49]期待西雅图之战 2016国际邀请赛中国区预选赛WINGS战队赛后采访
2016/06/29 DOTA
用python实现批量重命名文件的代码
2012/05/25 Python
python二叉树的实现实例
2013/11/21 Python
关于反爬虫的一些简单总结
2017/12/13 Python
如何在python字符串中输入纯粹的{}
2018/08/22 Python
Python+OpenCV实现图像融合的原理及代码
2018/12/03 Python
对python生成业务报表的实例详解
2019/02/03 Python
python 实现查询Neo4j多节点的多层关系
2019/12/23 Python
Python2与Python3的区别详解
2020/02/09 Python
基于SQLAlchemy实现操作MySQL并执行原生sql语句
2020/06/10 Python
python 基于opencv操作摄像头
2020/12/24 Python
美国知名生活购物网站:Goop
2017/11/03 全球购物
英国泽西岛植物:Jersey Plants Direct
2019/08/07 全球购物
Mountain Hardwear官网:攀岩服装和户外装备
2019/09/26 全球购物
Linux Interview Questions For software testers
2013/05/17 面试题
经营目标责任书
2015/05/08 职场文书
2015年大学团支部工作总结
2015/05/13 职场文书
婚礼家长致辞
2015/07/27 职场文书
2019秋季运动会口号
2019/06/25 职场文书
「偶像大师 MILLION LIVE!」七尾百合子手办开订
2022/03/21 日漫