JS原生瀑布流效果实现


Posted in Javascript onApril 26, 2019

今天早起看了慕课的瀑布流,的确讲的十分详细,也十分的好,我在博客里也就只能给代码加些注释,和说一下思路。建议大家去看一下慕课的瀑布流教程,非常详细,每一个细节都讲的非常好,只要懂JS的基础代码,看起来应该不是多大问题,里面没有太难得方法,但自己写不出来还是因为思路上有问题,下面就详细说一下几个重点方法的代码,建议大家去慕课详细学习
HTML 和CSS没有太难得地方

<div id="main">//一个main包含了整个页面内容,box用来做一个外容器,img作为图片容器
  <div class="box">
   <div class="pic">
    <img src="img/0.jpg">
   </div>
  </div>
  <div class="box">
   <div class="pic">
    <img src="img/0.jpg">
   </div>
  </div>
 <div>
//CSS
 //这里面的填充用padding值,因为offsetHeight是包括一个padding而不包括margin的方便以后高度的测量
*{
 margin: 0px;
 padding: 0px;
}
#main{
 position: relative;//在main上设置相对定位,在JS给box设置绝对定位,来控制图片位置
}
.box{
 padding: 15px 0 0 15px; 
 float: left;
}
.pic{
 padding: 10px;
 border: 1px solid #ccc;
 border-radius:5px;
 box-shadow: 0 0 5px #ccc;
}
.pic img{
 width: 168px;//瀑布流统一宽度但不同一高度,高度为自适应就好
 height: auto;
}

JS代码

在我们写JS代码之前,我们需要搞明白我们需要什么方法,是否需要封装起来调用,我们第一步要干什么,
那么我们第一步要干什么呢?我们做瀑布流首先要做的是获取到所有小部件也就是box,我们无论做什么处理都是对box的处理或者img的处理,所以要获取到所有的box,所以我们可以把它封装起来

//根据class获取元素
function getByClass(parent,clsName){//传入父元素和想要的class
 var boxArr=new Array//用来存储获取到所有class为box的元素,可以用对象的方式也可以用[]创建
 oElements=parent.getElementsByTagName('*');//取出所有子元素
 for (var i = 0; i < oElements.length; i++) {//我们需要遍历所有的子元素
  if(oElements[i].className==clsName)//如果我们找到了相应的子元素
   boxArr.push(oElements[i]);//取出传过来相等的className
   //push是数组自带的方法
 };
 return boxArr;返回数组
}

这样我们就得到了我们想要的class,之后该怎么办呢,先从一个box下手,我们需要取得第一排到底有多少个元素,因为之前我们并没有确定我们main的宽度,所以是自适应的也就是说我们把页面缩小,我们每一排的元素也会相应的减少,为了能让瀑布流的代码有更好的应用性,让不同尺寸的图片都可以应用,所以,我们需要手动计算一排究竟可以放多少张图片呢,那如何计算呢?
我们可以算出页面总宽在box的宽,就OK了

 var oBoxW=oBoxs[0].offsetWidth;//box的宽,提到了里面计算了padding的值
  var clos=Math.floor(document.documentElement.clientWidth/oBoxW)//求列数
  这样我们就求出了列数,无论图片的宽度如何变,我们都可以算出来
  floor是用来取整数的,因为我们的px是没有浮点数类型的避免计算错误,所以取整
  oparent.style.cssText='width:'+oBoxW*clos+'px; margin :0 auto';
  设置main的宽度

我们已经取得了列数之后呢我们第一排的图片肯定是一排宽度相等,长度不一是吧,也就是说,我们第二排的图片需要接上第一排图片的后边,我们不能一排一排操作,但我们可以一个一个操作,怎么操作呢,我们可以取到第一排高度最小的将下一张图片,也就是如果第一排7个,那下一个就是第八个,把第八个图片放在最小高度的图片上,如何实现呢,我们先试想一下,我们首先需要求出第一排中最小,我们有一个Math.min求最小,但是呢我们这个函数无法传入用数组,只能是具体的数怎么半呢,apply来扩展作用域
用代码展示下

var hArr=[];//每一列高度的值
 for (var i = 0; i < oBoxs.length; i++) {
  if(i<clos){//先记录好第一排高度
   hArr.push(oBoxs[i].offsetHeight);//放进去
  }else{//如果到达第二排,就开始计算
   var minH=Math.min.apply(Math,hArr);最小值计算
   //为什么可以呢,本来不能传数组,我们通过apply绑定作用域在Math上,也就是说还是执行这个函数但是,apply第二个参数需要是数组,所以间接地把参数变成了数组传进去,也就是说我们还是用了Math函数但值变成了数组里的值。
   //console.log(minH)
   var index=getMinhIndex(hArr,minH)//获取索引
   oBoxs[i].style.position="absolute";我们就可以找到,传入数组和最小值
   oBoxs[i].style.top=minH+"px";那下一张图片的高度救球出来了
   oBoxs[i].style.left=oBoxW*index+"px";左边的距离就是索引乘以元素的宽
   hArr[index]+=oBoxs[i].offsetHeight;//我们添加了一个图片后需要刷新数组里的高度,再去寻找下一个最小的,再向他的下面添加图片,一次循环
  }
 };
function getMinhIndex (arr,val){
 for(var i in arr){//在其中找到最小值,返回索引
  if(arr[i]==val){
   return i;
  }
 }
}

以上就大体做出了一个瀑布流的样式,就差拖动滚动条加载了,这里面肯定需要后台的支持,在慕课上,老师做了一个伪处理,这里建议看慕课视频,有图解十分清楚,我用语言或图片不太好表达

var dataInt={"data":[{"src":'0.jpg'},{"src":'1.jpg'},{"src":'2.jpg'},{"src":'3.jpg'}]}//我们自己写一个json数据
 window.onscroll=function(){
  if(checkScrollSlide){
   var oparent=document.getElementById("main")
   //将数据快渲染到当前页面尾部
   for (var i = 0; i < dataInt.data.length; i++) {//添加
    var oBox=document.createElement("div");
    oBox.className="box";
    oparent.appendChild(oBox);
    var opic=document.createElement('div');
    opic.className='pic';
    oBox.appendChild(opic);
    var oimg=document.createElement('img');
    oimg.src='img/'+dataInt.data[i].src;//将数据加进去
    opic.appendChild(oimg)
   }
   waterfall('main','box');//一会看完整代码,这就是刚才那些的封装
  }

 }
 function checkScrollSlide(){//检测是否具备加载数据块的条件
 var oparent=document.getElementById('main');
 var oBoxs=getByClass(oparent,'box')
 var lastBoxH=oBoxs[oBoxs.length-1].offsetTop+Math.floor(oBoxs[oBoxs.length-1].offsetHeight/2)求出最后一个图片的一半距离页面顶端的距离
 var scrollTop=document.body.scrollTop||document.documentElement.scrollTop;
 var height=document.body.clientHeight||document.documentElement.clientHeight;
 return(lastBoxH<scrollTop+height)?true:false;//如果页面距离顶部(包括滚轮)的距离比滚轮加页面距离小,那么就返回true
}

完整JS代码

window.onload=function(){
 waterfall('main','box');
 //json
 var dataInt={"data":[{"src":'0.jpg'},{"src":'1.jpg'},{"src":'2.jpg'},{"src":'3.jpg'}]}
 window.onscroll=function(){
  if(checkScrollSlide){
   var oparent=document.getElementById("main")
   //将数据快渲染到当前页面尾部
   for (var i = 0; i < dataInt.data.length; i++) {
    var oBox=document.createElement("div");
    oBox.className="box";
    oparent.appendChild(oBox);
    var opic=document.createElement('div');
    opic.className='pic';
    oBox.appendChild(opic);
    var oimg=document.createElement('img');
    oimg.src='img/'+dataInt.data[i].src;
    opic.appendChild(oimg)
   }
   waterfall('main','box');
  }

 }
}
function waterfall(parent,box){
 //将main下所有class为box的元素取出来
 var oparent=document.getElementById(parent);
 var oBoxs=getByClass(oparent,box)
 //console.log(oBox.length)
 //计算整个页面的列数(页面宽/box宽)
 var oBoxW=oBoxs[0].offsetWidth;
 //console.log(oBoxW);
 var clos=Math.floor(document.documentElement.clientWidth/oBoxW)//求列数
 //console.log(clos)
 //设置main的宽
 oparent.style.cssText='width:'+oBoxW*clos+'px; margin :0 auto';
 var hArr=[];//每一列高度的值
 for (var i = 0; i < oBoxs.length; i++) {
  if(i<clos){
   hArr.push(oBoxs[i].offsetHeight);
  }else{
   var minH=Math.min.apply(Math,hArr);
   //console.log(minH)
   var index=getMinhIndex(hArr,minH)//索引
   oBoxs[i].style.position="absolute";
   oBoxs[i].style.top=minH+"px";
   oBoxs[i].style.left=oBoxW*index+"px";
   hArr[index]+=oBoxs[i].offsetHeight;//更改数组
  }
 };
 //console.log(hArr)
}
//根据class获取元素
function getByClass(parent,clsName){
 var boxArr=new Array//用来存储获取到所有class为box的元素
 oElements=parent.getElementsByTagName('*');//取出所有子元素
 for (var i = 0; i < oElements.length; i++) {
  if(oElements[i].className==clsName)
   boxArr.push(oElements[i]);//取出传过来相等的className
 };
 return boxArr;
}
function getMinhIndex (arr,val){
 for(var i in arr){
  if(arr[i]==val){
   return i;
  }
 }
}
function checkScrollSlide(){//检测是否具备加载数据块的条件
 var oparent=document.getElementById('main');
 var oBoxs=getByClass(oparent,'box')
 var lastBoxH=oBoxs[oBoxs.length-1].offsetTop+Math.floor(oBoxs[oBoxs.length-1].offsetHeight/2)
 var scrollTop=document.body.scrollTop||document.documentElement.scrollTop;
 var height=document.body.clientHeight||document.documentElement.clientHeight;
 return(lastBoxH<scrollTop+height)?true:false;
}

我的瀑布流图

JS原生瀑布流效果实现

以上所述是小编给大家介绍的JS原生瀑布流效果实现详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
JavaScript对象、属性、事件手册集合方便查询
Jul 04 Javascript
Javascript 实现的数独解题算法网页实例
Oct 15 Javascript
Javascript中浮点数相乘的一个解决方法
Jun 03 Javascript
jQuery之Deferred对象详解
Sep 04 Javascript
jquery实现图片水平滚动效果代码分享
Aug 26 Javascript
jquery做个日期选择适用于手机端示例
Jan 10 Javascript
微信公众号菜单配置微信小程序实例详解
Mar 31 Javascript
Angular.js中下拉框实现渲染html的方法
Jun 18 Javascript
webpack配置sass模块的加载的方法
Jul 30 Javascript
js 发布订阅模式的实例讲解
Sep 10 Javascript
vue-cli配置文件——config篇
Jan 04 Javascript
antd配置config-overrides.js文件的操作
Oct 31 Javascript
Vue基于vuex、axios拦截器实现loading效果及axios的安装配置
Apr 26 #Javascript
详解auto-vue-file:一个自动创建vue组件的包
Apr 26 #Javascript
vue组件间的参数传递实例详解
Apr 26 #Javascript
详解VUE前端按钮权限控制
Apr 26 #Javascript
微信小程序开发之点击按钮退出小程序的实现方法
Apr 26 #Javascript
js最实用string(字符串)类型的使用及截取与拼接详解
Apr 26 #Javascript
微信小程序实现的绘制table表格功能示例
Apr 26 #Javascript
You might like
swfupload 多文件上传实现代码
2008/08/27 PHP
php将数据库中所有内容生成静态html文档的代码
2010/04/12 PHP
PHP实现服务器状态监控的方法
2014/12/09 PHP
老生常谈PHP面向对象之解释器模式
2017/05/17 PHP
Mootools 1.2教程 滑动效果(Slide)
2009/09/15 Javascript
javascript开发随笔一 preventDefault的必要
2011/11/25 Javascript
JavaScript面向对象知识串结(读JavaScript高级程序设计(第三版))
2012/07/17 Javascript
ajax处理php返回json数据的实例代码
2013/01/24 Javascript
jquery移动listbox的值原理及代码
2013/05/03 Javascript
通过javascript把图片转化为字符画
2013/10/24 Javascript
javascript中Object使用详解
2015/01/26 Javascript
JS+CSS实现分类动态选择及移动功能效果代码
2015/10/19 Javascript
微信小程序 连续旋转动画(this.animation.rotate)详解
2017/04/07 Javascript
vue环境搭建简单教程
2017/11/07 Javascript
node中IO以及定时器优先级详解
2019/05/10 Javascript
微信小程序与公众号卡券/会员打通的问题
2019/07/25 Javascript
简单了解常用的JavaScript 库
2020/07/16 Javascript
Python写的服务监控程序实例
2015/01/31 Python
Python中splitlines()方法的使用简介
2015/05/20 Python
使用memory_profiler监测python代码运行时内存消耗方法
2018/12/03 Python
Python 实现遥感影像波段组合的示例代码
2019/08/04 Python
对python 树状嵌套结构的实现思路详解
2019/08/09 Python
wxPython电子表格功能wx.grid实例教程
2019/11/19 Python
Python如何实现小程序 无限求和平均
2020/02/18 Python
Python标准库:内置函数max(iterable, *[, key, default])说明
2020/04/25 Python
Python 删除List元素的三种方法remove、pop、del
2020/11/16 Python
windows下python 3.9 Numpy scipy和matlabplot的安装教程详解
2020/11/28 Python
请用Java实现列出某个目录下的所有文件
2013/09/23 面试题
致跳高运动员广播稿
2014/01/13 职场文书
全陪导游欢迎词
2014/01/17 职场文书
房地产项目策划书
2014/02/05 职场文书
奥巴马开学演讲稿
2014/05/15 职场文书
森林防火宣传标语
2014/06/27 职场文书
科学发展观标语
2014/10/08 职场文书
2015年党员个人工作总结
2015/05/13 职场文书
Java8中接口的新特性使用指南
2021/11/01 Java/Android