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


Posted in Javascript onMarch 10, 2016

先科普下瀑布流吧

瀑布流,又称瀑布流式布局。是比较流行的一种网站页面布局,视觉表现为参差不齐的多栏布局,随着页面滚动条向下滚动,这种布局还会不断加载数据块并附加至当前尾部。最早采用此布局的网站是Pinterest,逐渐在国内流行开来。国内大多数清新站基本为这类风格,像美丽说、淘宝网都有使用。

这是我实现的一个效果,就是怎么滚动都加载不玩。就跟瀑布一样流啊流!

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

这里的实现方式我们只说Js实现方法

实现原理:

对容器中已有数据块元素进行第一次计算1 容器总宽度 2 列宽度  3 最小列数 ,得到列数后,用一个数组存放盒子所有高度,找出最小高度。之后根据序列号更新高度;看着有些拗口,实现起来就很简单了。

对于滚动加载:即滚动到哪个高度后,需要去加载数据,其实这个就是列的最小高度值,这样当前滚动值和最小高度值比较一下即可判断出来,是否要触发加载数据;就是写一个函数,用来判断是否达到加载图片条件,如果达到,就开始加载。比如获得最后一张图片的offsetTop,可视区高度,滚动距离,也就是当图片的offsetTop小于可视区高度和滚动距离之和的情况下,此时就应该加载了,不过条件可以随便定,也可以等滚动到图片的一半时候在触发加载条件,如图所示:

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

先上HTML CSS代码

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>waterfall</title>
 <script src="script.js"></script>
 <style>
  * {
   margin: 0;
   padding: 0;
  }
  body {
   background: yellow;
  }
  #container {

  }
  #container .pin {
   padding-left: 15px;
   padding-top: 15px;
   float: left;
  }
  #container .div-box {
   float: left;
   border: 1px solid #ccc;
   box-shadow: 0 0 5px #bbb;
   background: #fff;
   padding: 12px;
   border-radius: 9px;
  }
  #container .div-box img {
   width: 300px;
  }
  #container .div-box p {
   text-align: center;
   font-size: 20px;
   font-weight: bold;
   color: red;
  }
 </style>
 <script>
  
 </script>
</head>
<body>
 <div id="container">
  <div class="pin">
   <div class="div-box">
    <img src="img/1.jpg" alt="">
    <p>白超华-博客园</p>
   </div>
  </div>
  <div class="pin">
   <div class="div-box">
    <img src="img/2.jpg" alt="">
    <p>白超华-博客园</p>
   </div>
  </div>
  <div class="pin">
   <div class="div-box">
    <img src="img/3.jpg" alt="">
    <p>白超华-博客园</p>
   </div>
  </div>
  <div class="pin">
   <div class="div-box">
    <img src="img/4.jpg" alt="">
    <p>白超华-博客园</p>
   </div>
  </div>
  <div class="pin">
   <div class="div-box">
    <img src="img/5.jpg" alt="">
    <p>白超华-博客园</p>
   </div>
  </div>
  <div class="pin">
   <div class="div-box">
    <img src="img/6.jpg" alt="">
    <p>白超华-博客园</p>
   </div>
  </div>
  <div class="pin">
   <div class="div-box">
    <img src="img/7.jpg" alt="">
    <p>白超华-博客园</p>
   </div>
  </div>
  <div class="pin">
   <div class="div-box">
    <img src="img/8.jpg" alt="">
    <p>白超华-博客园</p>
   </div>
  </div>
  <div class="pin">
   <div class="div-box">
    <img src="img/9.jpg" alt="">
    <p>白超华-博客园</p>
   </div>
  </div>
  <div class="pin">
   <div class="div-box">
    <img src="img/10.jpg" alt="">
    <p>白超华-博客园</p>
   </div>
  </div>
  <div class="pin">
   <div class="div-box">
    <img src="img/1.jpg" alt="">
    <p>白超华-博客园</p>
   </div>
  </div>
  <div class="pin">
   <div class="div-box">
    <img src="img/2.jpg" alt="">
    <p>白超华-博客园</p>
   </div>
  </div>
  <div class="pin">
   <div class="div-box">
    <img src="img/3.jpg" alt="">
    <p>白超华-博客园</p>
   </div>
  </div>
  <div class="pin">
   <div class="div-box">
    <img src="img/4.jpg" alt="">
    <p>白超华-博客园</p>
   </div>
  </div>
  <div class="pin">
   <div class="div-box">
    <img src="img/5.jpg" alt="">
    <p>白超华-博客园</p>
   </div>
  </div>
  <div class="pin">
   <div class="div-box">
    <img src="img/6.jpg" alt="">
    <p>白超华-博客园</p>
   </div>
  </div>
 </div>
</body>
</html>

JS代码,每行都有注释

window.onload = function(){
 var data = {     //模拟后台数据 的一个JSON格式的文件
  "data":[
   {"src":"1.jpg"},
   {"src":"2.jpg"},
   {"src":"3.jpg"},
   {"src":"4.jpg"},
   {"src":"5.jpg"},
  ]
 };
 window.onscroll = function(){
  if(checkScroll()){   //判断是否具备滚动加载得条件
   var oParent = document.getElementById('container');
   for(var i=0; i<data.data.length; i++){
    var div1 = document.createElement('div'); //创建div元素
    div1.className = 'pin';     //设置class
    oParent.appendChild(div1);
    var div2 = document.createElement('div');//创建div元素
    div2.className = 'div-box';
    div1.appendChild(div2);
    var imgs = document.createElement('img');//创建img元素
    imgs.style.width = '300px';
    imgs.src = 'img/'+data.data[i].src; //设置读取路径
    div2.appendChild(imgs);
    var p = document.createElement('p');//创建p元素
    p.innerHTML = '白超华-博客园';
    div2.appendChild(p);
   }
   waterfall('container','pin');  //--注意 别忘了这句,当滚动时候就执行
  }
 }
 waterfall('container','pin');
}
function waterfall(parent, box){
 var oParent = document.getElementById(parent);//获取父级对象
 var aBox = getByClass(oParent,box);//获取所有class为pin的盒子的集合
 var boxWidth = aBox[0].offsetWidth;//获取一个盒子的宽
 var pageWidth = document.body.clientWidth||document.documentElement.clientWidth;//获取可视区宽
 var cols = Math.floor(pageWidth/boxWidth);//获得列数
 var arrH = [];//用于存放盒子的高

 for(var i=0; i<aBox.length; i++){
  if(i<cols){//当小于第一列个数的时候
   arrH.push(aBox[i].offsetHeight);
  } else {
   var minH = Math.min.apply(null,arrH);//得到数组中盒字的最小高度minH;
   var index = getMinIndex(arrH,minH);

   aBox[i].style.position = 'absolute';//设置绝对定位
   aBox[i].style.top = minH+'px';//设置top,就是最小高度
   aBox[i].style.left = aBox[0].offsetWidth*index+'px';//设置left,就是一个盒子的宽*index索引数
   arrH[index]+=aBox[i].offsetHeight; //更新新添加盒字后的列高
  }
 }
}
//通过父级获取class
function getByClass(parent, classname){
 var aClass = parent.getElementsByTagName('*');
 var arr = [];

 for(var i=0; i<aClass.length; i++){
  if(aClass[i].className == classname){
   arr.push(aClass[i]);
  }
 }
 return arr;
}
//最小值的索引index
function getMinIndex(arr,val){
 for( i in arr){
  if(arr[i] == val){
   return i;
  }
 }
}
//
function checkScroll(){
 var oParent = document.getElementById('container');
 var aBox = getByClass(oParent,'pin');
 var lastBoxHeight = aBox[aBox.length-1].offsetTop;// 当滚到到这个距离时候就开始加载
 var scrollTop=document.documentElement.scrollTop||document.body.scrollTop;//兼容的滚动距离
 var documentHeight = document.documentElement.clientHeight; //页面高度
 if(lastBoxHeight<scrollTop+documentHeight){
  return true;
 }
}

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

Javascript 相关文章推荐
javascript编程起步(第五课)
Jan 10 Javascript
cookie的复制与使用记住用户名实现代码
Nov 04 Javascript
jQuery实现图片上传和裁剪插件Croppie
Nov 29 Javascript
原生js实现百叶窗效果及原理介绍
Apr 12 Javascript
全面解析node 表单的图片上传
Nov 21 Javascript
javascript实现圣旨卷轴展开效果(代码分享)
Mar 23 Javascript
Vue 使用中的小技巧
Apr 26 Javascript
详解vue指令与$nextTick 操作DOM的不同之处
Aug 02 Javascript
Vue中对iframe实现keep alive无刷新的方法
Jul 23 Javascript
基于JavaScript实现表格隔行换色
May 08 Javascript
javascript实现简单页面倒计时
Mar 02 Javascript
vue项目proxyTable配置和部署服务器
Apr 14 Vue.js
javascript实现可键盘控制的抽奖系统
Mar 10 #Javascript
基于javascript制作微信聊天面板
Aug 09 #Javascript
关于Bootstrap弹出框无法调用问题的解决办法
Mar 10 #Javascript
TypeScript Type Innference(类型判断)
Mar 10 #Javascript
JavaScript File分段上传
Mar 10 #Javascript
ES6中非常实用的新特性介绍
Mar 10 #Javascript
ES6的新特性概览
Mar 10 #Javascript
You might like
?繁体转换的class
2006/10/09 PHP
几种有用的变型 PHP中循环语句的用法介绍
2012/01/30 PHP
解析PHP中常见的mongodb查询操作
2013/06/20 PHP
php面向对象中static静态属性与方法的内存位置分析
2015/02/08 PHP
php进程daemon化的正确实现方法
2018/09/06 PHP
JSON.parse 解析字符串出错的解决方法
2010/07/08 Javascript
js中eval详解
2012/03/30 Javascript
判断一个变量是数组Array类型的方法
2013/09/16 Javascript
jquery 实现密码框的显示与隐藏示例代码
2013/09/18 Javascript
js将字符串转成正则表达式的实现方法
2013/11/13 Javascript
深入理解JavaScript中的对象
2015/06/04 Javascript
静态页面html中跳转传值的JS处理技巧
2016/06/22 Javascript
百度多文件异步上传控件webuploader基本用法解析
2016/11/07 Javascript
详解如何去除vue项目中的#——History模式
2017/10/13 Javascript
vue+node+webpack环境搭建教程
2017/11/05 Javascript
详解微信小程序实现WebSocket心跳重连
2018/07/31 Javascript
解决layui前端框架 form表单,table表等内置控件不显示的问题
2018/08/19 Javascript
解决vue+element 键盘回车事件导致页面刷新的问题
2018/08/25 Javascript
vue如何进行动画的封装
2018/09/26 Javascript
Vue 后台管理类项目兼容IE9+的方法示例
2019/02/20 Javascript
JS实现audio音频剪裁剪切复制播放与上传(步骤详解)
2020/07/28 Javascript
vue中如何添加百度统计代码
2020/12/19 Vue.js
python批量提交沙箱问题实例
2014/10/08 Python
Python异常对代码运行性能的影响实例解析
2018/02/08 Python
Python文件监听工具pyinotify与watchdog实例
2018/10/15 Python
python开发准备工作之配置虚拟环境(非常重要)
2019/02/11 Python
python 缺失值处理的方法(Imputation)
2019/07/02 Python
python读写配置文件操作示例
2019/07/03 Python
Python常用模块logging——日志输出功能(示例代码)
2019/11/20 Python
世界上最大的专业美容用品零售商:Sally Beauty
2017/07/02 全球购物
大专生的学习自我评价
2013/12/04 职场文书
业务部门经理岗位职责
2014/02/23 职场文书
听课评语大全
2014/04/30 职场文书
学校周年庆活动方案
2014/08/22 职场文书
2015年护士医德医风自我评价
2015/03/03 职场文书
Nginx location 和 proxy_pass路径配置问题小结
2021/09/04 Servers