JavaScript:实现瀑布流
一、前言:
瀑布流现在是一个非常常用的布局方式了,尤其在购物平台上,例如蘑菇街,淘宝等等。
二、流程:
1、在html文件中写出布局的元素内容;
2、在css文件中整体对每一个必要的元素进行样式和浮动设置;
3、在js文件中动态实现布局,每一个滚动时,都要刷新布局。
三、思想:
实现瀑布流,就是每次当前一列的图片显示完全后,接着要显示下一列时,先找出最短的一列,然后将图片填充上,以此类推...
四、代码:
waterFlow.html:
<!DOCTYPE html> <html lang="zh-en"> <head> <meta charset="UTF-8"> <title>瀑布流效果</title> <link rel="stylesheet" href="waterFlow.css"> <script src="waterFlow.js" type="text/javascript"></script> </head> <body> <!--父盒子--> <div id="main"> <!--子盒子--> <div class="box"> <div class="pic"> <img src="images/0.png"> <div> <span>喜欢:666</span> <span>收藏:999</span> </div> </div> </div> <div class="box"> <div class="pic"><img src="images/1.png" alt=""></div> </div> <div class="box"> <div class="pic"><img src="images/2.png" alt=""></div> </div> <div class="box"> <div class="pic"><img src="images/3.png" alt=""></div> </div> <div class="box"> <div class="pic"><img src="images/4.png" alt=""></div> </div> <div class="box"> <div class="pic"><img src="images/5.png" alt=""></div> </div> <div class="box"> <div class="pic"><img src="images/6.png" alt=""></div> </div> <div class="box"> <div class="pic"><img src="images/7.png" alt=""></div> </div> <div class="box"> <div class="pic"><img src="images/8.png" alt=""></div> </div> <div class="box"> <div class="pic"><img src="images/9.png" alt=""></div> </div> <div class="box"> <div class="pic"><img src="images/10.png" alt=""></div> </div> <div class="box"> <div class="pic"><img src="images/11.png" alt=""></div> </div> <div class="box"> <div class="pic"><img src="images/12.png" alt=""></div> </div> <div class="box"> <div class="pic"><img src="images/13.png" alt=""></div> </div> <div class="box"> <div class="pic"><img src="images/14.png" alt=""></div> </div> <div class="box"> <div class="pic"><img src="images/15.png" alt=""></div> </div> <div class="box"> <div class="pic"><img src="images/16.png" alt=""></div> </div> <div class="box"> <div class="pic"><img src="images/17.png" alt=""></div> </div> <div class="box"> <div class="pic"><img src="images/18.png" alt=""></div> </div> <div class="box"> <div class="pic"><img src="images/19.png" alt=""></div> </div> <div class="box"> <div class="pic"><img src="images/20.png" alt=""></div> </div> <div class="box"> <div class="pic"><img src="images/21.png" alt=""></div> </div> <div class="box"> <div class="pic"><img src="images/22.png" alt=""></div> </div> <div class="box"> <div class="pic"><img src="images/23.png" alt=""></div> </div> </div> </body> </html>
waterFlow.css:
*{ padding: 0; margin: 0; } #main{ /*定位*/ position: relative; } .box{ float: left; /*内边距*/ padding: 15px 0 0 15px; /*background-color: red;*/ } .pic{ border:1px solid #dddddd; padding: 10px; background-color: white; border-radius: 5px; } .pic img{ width: 165px; }
waterFlow.js:
// === 值比较 类型比较 function $(id) { return typeof id === 'string' ? document.getElementById(id) : id } // 当窗口加载完毕 window.onload = function () { // 瀑布流布局 WaterFall('main', 'box'); // 滚动加载盒子 window.onscroll = function () { if(CheckWillLoad()){ // 具备滚动的条件 // 造数据 var dataArr = [{'src': '10.png'},{'src': '11.png'},{'src': '13.png'},{'src': '15.png'},{'src': '17.png'},{'src': '19.png'},{'src': '21.png'},{'src': '23.png'}]; // 遍历 for(var i=0; i<dataArr.length; i++){ // 创建子盒子 var newBox = document.createElement('div'); newBox.className = 'box'; $('main').appendChild(newBox); var newPic = document.createElement('div'); newPic.className = 'pic'; newBox.appendChild(newPic); var newImg = document.createElement('img'); newImg.src = 'images/' + dataArr[i].src; newPic.appendChild(newImg); } // 重新实现瀑布流布局 WaterFall('main', 'box'); } } }; // http://blog.sina.com.cn/s/blog_966e43000101bplb.html // 瀑布流布局 function WaterFall(parent, child) { // ------ 父盒子居中 // 1.1 拿到所有的子盒子 var allBox = document.getElementsByClassName(child); // 1.2 求出其中一个盒子的宽度 var boxWidth = allBox[0].offsetWidth; // 1.3 求出页面的宽度 var clientWidth = document.body.clientWidth; // 1.4 求出列数 var cols = Math.floor(clientWidth / boxWidth); // 1.5 父盒子居中 css赋值都是String类型 $(parent).style.width = boxWidth * cols + 'px'; $(parent).style.margin = '0 auto'; // ------ 子盒子的定位 // 1.1 定义高度数组 var heightArr = []; // 1.2 遍历所有的盒子 for(var i=0; i<allBox.length; i++){ // 1.2.1 取出单个盒子的高度 var boxHeight = allBox[i].offsetHeight; // 1.2.2 判断 if(i < cols){ // 第一行 heightArr.push(boxHeight); }else{ // 剩余的行 // 取出数组中最矮的盒子的高度 var minBoxHeight = Math.min.apply(this, heightArr); // 取出数组中最矮的盒子的索引 var minBoxIndex = GetMinBoxIndex(heightArr, minBoxHeight); // 子盒子定位 allBox[i].style.position = 'absolute'; allBox[i].style.top = minBoxHeight +'px'; allBox[i].style.left = boxWidth * minBoxIndex + 'px'; // 更新数组中最矮盒子的高度 heightArr[minBoxIndex] += boxHeight; } } // console.log(heightArr, minBoxHeight, minBoxIndex); } // 获取最矮盒子的索引 function GetMinBoxIndex(arr, value) { for(var i=0; i<arr.length; i++){ if (arr[i] == value) return i; } } // 判断是否具备加载条件 function CheckWillLoad() { // 1.1 获取最后的一个盒子 var allBox = document.getElementsByClassName('box'); var lastBox = allBox[allBox.length - 1]; // 1.2 求出高度的一半 + 头部偏离的高度 var lastBoxDis = lastBox.offsetHeight * 0.5 + lastBox.offsetTop; // 1.3 求出页面的高度 JS存在兼容性问题 ---> 标准模式 混杂模式 var clientHeight = document.body.clientHeight || document.documentElement.clientHeight; // 1.4 求出页面偏离浏览器的高度 var scrollTopHeight = document.body.scrollTop; // 1.5 判断返回 return lastBoxDis <= clientHeight + scrollTopHeight; }
五、效果图:
程序猿神奇的手,每时每刻,这双手都在改变着世界的交互方式!