javascript实例学习之五——瀑布流布局
瀑布流布局的特征:
1,各列的高度参差不齐
2,页面向下滚动时,自动请求和加载新数据
目前,瀑布流布局的主流实现方式有两种:
1,基于浮动,每一列是一个ul,这些ul都向左浮动,这种方法的好处是布局容易,加载较为复杂;
2,基于绝对定位,只有一个ul,所有item都加入该ul中,ul相对定位,item绝对定位,所有图片的宽度已知,所有图片的高度信息使用一个数组记录所有图片的高度(即offsetHeight信息)。
一、基于浮动的瀑布流布局
基于浮动瀑布流布局的html页面
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>瀑布流布局</title> </head> <style> *{margin:0;padding:0;} ul>li{list-style: none} #div1{width:750px;margin:20px auto;overflow: hidden;} ul{width:237px;margin:5px;float:left;} </style> <body> <div id="div1"> <ul> <li> <img src="./images/feed/1.jpg" alt=""> <p>1111111111</p> </li> <li> <img src="./images/feed/2.jpg" alt=""> <p>1111111111</p> </li> <li> <img src="./images/feed/2.jpg" alt=""> <p>1111111111</p> </li> </ul> <ul> <li> <img src="./images/feed/2.jpg" alt=""> <p>22222222222</p> </li> <li> <img src="./images/feed/3.jpg" alt=""> <p>22222222222</p> </li> <li> <img src="./images/feed/3.jpg" alt=""> <p>22222222222</p> </li> </ul> <ul> <li> <img src="./images/feed/3.jpg" alt=""> <p>3333333333</p> </li> <li> <img src="./images/feed/1.jpg" alt=""> <p>3333333333</p> </li> <li> <img src="./images/feed/1.jpg" alt=""> <p>3333333333</p> </li> </ul> </div> <script src="./js/jquery-2.1.4.min.js"></script> <script src="./js/feed.js"></script> </body> </html>
基于浮动瀑布流布局的js代码
//获取元素相对于屏幕的距离 function getTop(obj) { var top = 0; while (obj) { top += obj.offsetTop; obj = obj.offsetParent; } return top; } document.addEventListener('DOMContentLoaded', function() { var aUls = document.getElementsByTagName('ul'); var flag = true; //添加数据 function addNext(uls, jsonObj) { if (jsonObj['code']) { //说明jsonObj['code']等于0,数据发送完毕,没有更新的数据 flag = true; } console.log(flag); var realData = jsonObj['list']; for (var i = 0; i < realData.length; i++) { var curData = realData[i]; for (var j = 0; j < curData['src'].length; j++) { var oLi = document.createElement('li'); oLi.innerHTML = '<img src="' + curData['src'][j] + '"><p>' + curData['title'][j] + '</p>'; uls[i].appendChild(oLi); } } } window.addEventListener('scroll', function() { //可视区域(视口)的高度 var viewHeight = document.documentElement.clientHeight; //滚动条滚动的高度(隐藏在上方的高度) var scrollY = document.documentElement.scrollTop || document.body.scrollTop; for (var i = 0; i < aUls.length; i++) { var aLi = aUls[i].getElementsByTagName('li'); var lastLi = aLi[aLi.length - 1]; //判断最后一个是否进入可视区 if (getTop(lastLi) < viewHeight + scrollY && flag) { //将flag置为false,否则有几个ul,就会连续触发几次 flag = false; //发送ajax请求 //理论上应当发送ajax请求,这里省略,直接赋予数值 // $.ajax({ // }); var data = { code: 0, list: [{ src: ['./images/feed/3.jpg', './images/feed/2.jpg', './images/feed/2.jpg'], title: ['222222222222', '222222222222', '222222222222'] }, { src: ['./images/feed/1.jpg', './images/feed/2.jpg', './images/feed/3.jpg'], title: ['333333333333', '333333333333', '333333333333'] }, { src: ['./images/feed/2.jpg', './images/feed/1.jpg', './images/feed/1.jpg'], title: ['111111111111', '111111111111', '111111111111'] }] }; addNext(aUls, data); } } }, false); }, false);
核心思想
监听window的scroll函数,将最后一个列表项的top值和(滚动隐藏高度+视口高度)相比较,判断加载时机
二、基于决定定位的瀑布流布局
基于浮动瀑布流布局的html页面
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>基于绝对定位的瀑布流布局</title> <style> * { margin: 0; padding: 0; } ul>li { list-style: none; } .div1 { margin: 20px auto; width: 730px; position: relative; } li{ position:absolute; } </style> </head> <body> <div class="div1"> <ul> <li> <img src="./images/feed/1.jpg" alt=""> <p>11111111111</p> </li> <li> <img src="./images/feed/3.jpg" alt=""> <p>11111111111</p> </li> <li> <img src="./images/feed/2.jpg" alt=""> <p>11111111111</p> </li> <li> <img src="./images/feed/2.jpg" alt=""> <p>11111111111</p> </li> <li> <img src="./images/feed/1.jpg" alt=""> <p>11111111111</p> </li> <li> <img src="./images/feed/1.jpg" alt=""> <p>11111111111</p> </li> <li> <img src="./images/feed/3.jpg" alt=""> <p>11111111111</p> </li> <li> <img src="./images/feed/1.jpg" alt=""> <p>11111111111</p> </li> <li> <img src="./images/feed/2.jpg" alt=""> <p>11111111111</p> </li> </ul> </div> <script src="./js/jquery-2.1.4.min.js"></script> <script src="./js/jquery-2.1.4.min.js"></script> <script src="./js/feed2.js"></script> </body> </html>
基于浮动瀑布流布局的js代码
//获取元素相对于屏幕的距离 function getTop(obj) { var top = 0; while (obj) { top += obj.offsetTop; obj = obj.offsetParent; } return top; } var aHeight = { L: [], C: [], R: [] }; function refreshUl(aLis) { for (var i = 0; i < aLis.length; i++) { var tmp = i % 3; switch (tmp) { case 0: aLis[i].style.left = "5px"; aHeight['L'].push(aLis[i].offsetHeight); var step = Math.floor(i / 3); var curHeight = 0; for (var k = 0; k < step; k++) { curHeight += aHeight['L'][k] + 5; } aLis[i].style.top = curHeight + 'px'; break; case 1: aLis[i].style.left = "247px"; aHeight['C'].push(aLis[i].offsetHeight); var step = Math.floor(i / 3); var curHeight = 0; for (var k = 0; k < step; k++) { curHeight += aHeight['C'][k] + 5; } aLis[i].style.top = curHeight + 'px'; break; case 2: aLis[i].style.left = "489px"; aHeight['R'].push(aLis[i].offsetHeight); var step = Math.floor(i / 3); var curHeight = 0; for (var k = 0; k < step; k++) { curHeight += aHeight['R'][k] + 5; } aLis[i].style.top = curHeight + 'px'; break; } } } $(function() { var oUl = document.getElementsByTagName('ul')[0]; var aLis = oUl.getElementsByTagName('li'); //使用数组记录每个元素的高度 console.log('li个数:'+aLis.length); var flag = true; refreshUl(aLis); //下滑加载部分的代码 window.addEventListener('scroll', function() { var aLis = oUl.getElementsByTagName('li'); var lastLi = aLis[aLis.length - 1]; var viewHeight = document.documentElement.clientHeight || document.body.clientHeight; var scrollY = document.documentElement.scrollTop || document.body.scrollTop; if (getTop(lastLi) < viewHeight + scrollY &&flag) { var data = { 'code': 0, 'liData': { 'src': ['./images/feed/1.jpg', './images/feed/1.jpg', './images/feed/1.jpg'], 'title': ['5555555555', '5555555555', '5555555555'] } } if (data['code'] == 0) { //说明已经没有更多数据 flag = false; } var srcData = data['liData']['src']; var titleData = data['liData']['title']; for (var i = 0; i < srcData.length; i++) { var curLi = document.createElement('li'); curLi.innerHTML = '<img src="' + srcData[i] + '"><p>' + titleData[i] + '</p>'; oUl.appendChild(curLi); } aLis = oUl.getElementsByTagName('li'); console.log('aLis个数2:'+aLis.length); refreshUl(aLis); } }, false); });