解析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 相关文章推荐
JS自动倒计时30秒后按钮才可用(两种场景)
Aug 31 Javascript
javascript常用经典算法实例详解
Nov 25 Javascript
AngularJS封装指令方法详解
Dec 12 Javascript
javascript容错处理代码(屏蔽js错误)
Jan 20 Javascript
JQuery中Ajax的操作完整例子
Mar 07 Javascript
vue2中filter()的实现代码
Jul 09 Javascript
最实用的JS数组函数整理
Dec 05 Javascript
JS排序算法之冒泡排序,选择排序与插入排序实例分析
Dec 13 Javascript
vue 中引用gojs绘制E-R图的方法示例
Aug 24 Javascript
新版小程序登录授权的方法
Dec 12 Javascript
Vue中的情侣属性$dispatch和$broadcast详解
Mar 07 Javascript
JavaScript实现汉字转换为拼音及缩写的方法示例
Mar 28 Javascript
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
PHP的栏目导航程序
2006/10/09 PHP
使用 MySQL 开始 PHP 会话
2006/12/21 PHP
php 特殊字符处理函数
2008/09/05 PHP
php小技巧之过滤ascii控制字符
2014/05/14 PHP
php中单个数据库字段多列显示(单字段分页、横向输出)
2014/07/28 PHP
PHP实现的oracle分页函数实例
2016/01/25 PHP
轻松掌握php设计模式之访问者模式
2016/09/23 PHP
摘自百度的图片轮换效果代码
2007/11/19 Javascript
修改file按钮的默认样式实现代码
2013/04/23 Javascript
JavaScript 和 Java 的区别浅析
2013/07/31 Javascript
js、css、img等浏览器缓存问题的2种解决方案
2013/10/23 Javascript
javascript中attribute和property的区别详解
2014/06/05 Javascript
每天一篇javascript学习小结(Array数组)
2015/11/11 Javascript
如何使用Bootstrap创建表单
2017/03/29 Javascript
JS实现数组按升序及降序排列的方法
2017/04/26 Javascript
node.js中EJS 模板快速入门教程
2017/05/08 Javascript
Mui使用jquery并且使用点击跳转新窗口的实例
2017/08/19 jQuery
Angularjs过滤器实现动态搜索与排序功能示例
2017/12/13 Javascript
vue :src 文件路径错误问题的解决方法
2018/05/15 Javascript
vue将单页面改造成多页面应用的方法
2018/11/25 Javascript
Vue使用Proxy监听所有接口状态的方法实现
2019/06/07 Javascript
在Python中使用M2Crypto模块实现AES加密的教程
2015/04/08 Python
Django中STATIC_ROOT和STATIC_URL及STATICFILES_DIRS浅析
2018/05/08 Python
Python 实现文件读写、坐标寻址、查找替换功能
2019/09/11 Python
如何关掉pycharm中的python console(图解)
2019/10/31 Python
Ubuntu中配置TensorFlow使用环境的方法
2020/04/21 Python
python基于Kivy写一个图形桌面时钟程序
2021/01/28 Python
使用CSS3制作版头动画效果
2020/12/24 HTML / CSS
《高尔基和他的儿子》教学反思
2014/04/09 职场文书
2014年党课学习材料
2014/05/11 职场文书
和谐家庭演讲稿
2014/05/24 职场文书
五好家庭申报材料
2014/12/20 职场文书
平遥古城导游词
2015/02/03 职场文书
师德师风主题教育活动总结
2015/05/07 职场文书
教师节表彰会主持词
2015/07/06 职场文书
python解决12306登录验证码的实现
2021/04/18 Python