瀑布流的实现方式(原生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 相关文章推荐
js内存泄露的几种情况详细探讨
May 31 Javascript
ie8下修改input的type属性报错的解决方法
Sep 16 Javascript
jQuery实现的简单分页示例
Jun 01 Javascript
深入理解逻辑表达式的用法 与或非的用法
Jun 06 Javascript
JavaScript页面实时显示当前时间实例代码
Oct 23 Javascript
jQuery基于xml格式数据实现模糊查询及分页功能的方法
Dec 25 Javascript
基于JS代码实现简单易用的倒计时 x 天 x 时 x 分 x 秒效果
Jul 13 Javascript
Vue项目中quill-editor带样式编辑器的使用方法
Aug 08 Javascript
JavaScript运行原理分析
Feb 09 Javascript
Java设计中的Builder模式的介绍
Mar 22 Javascript
微信小程序使用gitee进行版本管理
Sep 20 Javascript
原生Javascript+HTML5一步步实现拖拽排序
Jun 12 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循环函数使用介绍之PHP基础入门教程
2013/09/21 PHP
PHP 生成N个不重复的随机数
2015/01/21 PHP
php实现cookie加密的方法
2015/03/10 PHP
JavaScript是否可实现多线程  深入理解JavaScript定时机制
2009/12/22 Javascript
jquery实现点击TreeView文本父节点展开/折叠子节点
2013/01/10 Javascript
jQuery实现div浮动层跟随页面滚动效果
2014/02/11 Javascript
JavaScript 实现鼠标拖动元素实例代码
2014/02/24 Javascript
用javascript将数据导入Excel示例代码
2014/09/10 Javascript
jQuery实现动态表单验证时文本框抖动效果完整实例
2015/08/21 Javascript
JavaScript File API文件上传预览
2016/02/02 Javascript
jquery div模态窗口的简单实例
2016/05/28 Javascript
JS使用eval()动态创建变量的方法
2016/06/03 Javascript
JS结合bootstrap实现基本的增删改查功能
2016/07/22 Javascript
BootStrap Tooltip插件源码解析
2016/12/27 Javascript
jQuery Pagination分页插件使用方法详解
2017/02/28 Javascript
js实现悬浮窗效果(支持拖动)
2017/03/09 Javascript
微信小程序开发之从相册获取图片 使用相机拍照 本地图片上传
2017/04/18 Javascript
JS使用ActiveXObject实现用户提交表单时屏蔽敏感词功能
2017/06/20 Javascript
Vue编写多地区选择组件
2017/08/21 Javascript
vue项目常用组件和框架结构介绍
2017/12/24 Javascript
vue-music 使用better-scroll遇到轮播图不能自动轮播问题
2018/12/03 Javascript
javaScript把其它类型转换为Number类型
2019/10/13 Javascript
Vue 实现html中根据类型显示内容
2019/10/28 Javascript
使用Python脚本操作MongoDB的教程
2015/04/16 Python
Python获取指定字符前面的所有字符方法
2018/05/02 Python
python实现音乐下载的统计
2018/06/20 Python
python使用信号量动态更新配置文件的操作
2020/04/01 Python
python自定义函数def的应用详解
2020/06/03 Python
CSS3实现闪烁动画效果的方法
2015/02/09 HTML / CSS
街头时尚在线:JESSICABUURMAN
2019/06/16 全球购物
党员领导干部承诺书
2014/05/28 职场文书
学习十八大的心得体会
2014/09/12 职场文书
保安辞职信范文
2015/02/28 职场文书
同学聚会通知短信
2015/04/20 职场文书
2019最新劳动仲裁申请书!
2019/07/08 职场文书
2019大学生社会实践报告汇总
2019/08/16 职场文书