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

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

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

(0)

相关推荐

  • jQuery实现瀑布流布局详解(PC和移动端)

    瀑布流布局已成为当今非常普遍的图片展示方式,无论是PC还是手机等移动设备上.这种布局图片的样式大概分为三种:等高等宽.等宽不等高.等高不等宽,接下来我们就最为普遍的等宽不等高形式来作为示例. 我们用百度图片作为范例: 这就是PC端比较常见的瀑布流布局方式,接下来我们审查下元素看看百度图片里面是如何布局: 可以看到,它里面实际是若干个等宽的列容器,通过计算将图片push到不同的容器里.而本文介绍的展示方法是通过定位的方式,虽然最后布局展示的方式不同,但之前的算法都比较类似. 动手 首先我们将如下样

  • 纯js实现瀑布流布局及ajax动态新增数据

    本文用纯js代码手写一个瀑布流网页效果,初步实现一个基本的瀑布流布局,以及滚动到底部后模拟ajax数据加载新图片功能. 缺点: 1. 程序不是响应式,不能实时调整页面宽度: 2. 程序中当新增ajax模拟数据图片后,是将整个页面的所有图片都重新定位一次. 3. 程序是等所有图片加载完成后再读取图片的尺寸,实际中肯定不能这样做. 4. 实际项目中,应该由后台程序给出图片尺寸值,在js代码中直接使用图片的width属性. 本程序思路: html结构: <body> <div id="

  • 详解javascript实现瀑布流列式布局

    本文介绍了javascript瀑布流列式布局的相关内容,分享给大家供大家参考,具体内容如下 JS原理 上面说了,列式布局简直算是完虐绝对式布局. 绝对式布局,简直就像10元/天 的搬砖工.而列式布局就是站在那看他搬砖的监工. 同样都是搬砖的,一个卖苦力,一个秀智商.简直了!!! 听了逼逼,我们来直面一下惨淡的人生. 列式布局的原理其实和绝对式布局没有太大的却别. 同样也有3个部分, 一是页面加载自适应,二是滑动加载,三是响应式布局. 分别讲解: 1.加载自适应 我们先看一下代码吧: var $

  • 解析javascript瀑布流原理实现图片滚动加载

    先科普下瀑布流吧 瀑布流,又称瀑布流式布局.是比较流行的一种网站页面布局,视觉表现为参差不齐的多栏布局,随着页面滚动条向下滚动,这种布局还会不断加载数据块并附加至当前尾部.最早采用此布局的网站是Pinterest,逐渐在国内流行开来.国内大多数清新站基本为这类风格,像美丽说.淘宝网都有使用. 这是我实现的一个效果,就是怎么滚动都加载不玩.就跟瀑布一样流啊流! 这里的实现方式我们只说Js实现方法 实现原理: 对容器中已有数据块元素进行第一次计算1 容器总宽度 2 列宽度  3 最小列数 ,得到列数

  • javascript瀑布流式图片懒加载实例解析与优化

    之前写过一版图片"懒加载"的文章,刚好周末在整理文件的时候,大概又看了一遍之前写的代码发现有很多可以优化的地方. 这篇文章主要就是结合上篇<javascript瀑布流式图片懒加载实例>再来看看图片"懒加载"的一些知识. 图片"懒加载"的主旨: 按照需要加载图片,也就是说需要显示的时候再加载图片显示,减少一次性加载的网络带宽开销. 先来看一段代码: var conf = { 'loadfirst': true, 'loadimg': t

  • 基于JavaScript实现瀑布流布局(二)

    本文实例讲解了JavaScript实现瀑布流布局详细代码,分享给大家供大家参考,具体内容如下 1.建立Html模版 想法是先用一个div container承载所有内容,然后div box用来放置图片,最后div box_border来当图片框,代码如下 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>瀑布流</title> </head

  • 基于JavaScript实现瀑布流布局

    本文实例讲解了原生JavaScript实现瀑布流布局详细代码,分享给大家供大家参考,具体内容如下 效果图: 具体代码: HTML <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <link rel="stylesheet" type="

  • js实现瀑布流的三种方式比较

    瀑布流是一种网站页面布局,视觉表现为参差不齐的多栏布局,随着页面滚动条向下滚动,这种布局还会不断加载数据块并附加至当前尾部.最早采用此布局的网站是Pinterest,逐渐在国内流行开来.国内大多数清新站基本为这类风格. 瀑布流特点: 1.琳琅满目:整版以图片为主,大小不一的图片按照一定的规律排列. 2.唯美:图片的风格以唯美的图片为主. 3.操作简单:在浏览网站的时候只需要轻轻滑动一下鼠标滚轮,一切的美妙的图片精彩便可呈现在你面前. 瀑布流布局实现方式: 1.传统多列浮动 · 各列固定宽度,并且

  • javascript实现瀑布流加载图片原理

    讲一下大概的原理吧,还是先上图:  功能描述: 根据不同菜单的属性值分别加载不同的数据 下拉滚动条到一定位置预加载图片,滚动条拉到最底下的时候渲染html: 鼠标移到菜单,切换各个图片列表: 鼠标移到图片列表上,显示详细信息:  技术实现方案: 先梳理一下从加载到显示的流程: 1. 加载数据 2. 拼接HTML写入到页面 3. 检查刚刚写入的HTML中的img是否全部加载完成,如果是,进入5.否则进入4 4. 等待图片加载完成 5. 计算每个元素的位置 一开始的时候最头疼的是如何定位的问题,后来

  • 详解javascript实现瀑布流绝对式布局

    瀑布流也应该算是流行几年了吧.首先是由Pinterest掀起的浪潮,然后国内设计如雨后春笋般,冒出很多瀑布流的例子,比如,蘑菇街,Mark之(不过最近涉黄,好像被喝茶了),还有淘宝的 "哇哦". 这些都是很棒的例子, 今天我们就聊一聊瀑布流. 一.绝对式布局: JS实现原理 其实瀑布式主要的难点就在于,如果将图片整齐的排列在对应的列下,以及什么时候开始刷新加载图片. 而图片整齐的排列的主要逻辑和算法即,先获取容器内可以放多少列,然后,通过计算,存放第一列的高度,再遍历剩下(除第一列的元

随机推荐