图片瀑布流实现
实现思路:图片宽度一定,高度不同,下一行的第一张图片放在高度最小的图片的下方,以此类推。
实现代码:
html代码:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>js实现瀑布流效果</title> <link href="css/index.css" rel="stylesheet"> <script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script> </head> <body> <div id="container"> <div class="box"> <div class="pic"> <img src="images/01.jpg"> </div> </div> <div class="box"> <div class="pic"> <img src="images/02.jpg"> </div> </div> <div class="box"> <div class="pic"> <img src="images/03.jpg"> </div> </div> <div class="box"> <div class="pic"> <img src="images/04.jpg"> </div> </div> <div class="box"> <div class="pic"> <img src="images/05.jpg"> </div> </div> <div class="box"> <div class="pic"> <img src="images/06.jpg"> </div> </div> <div class="box"> <div class="pic"> <img src="images/01.jpg"> </div> </div> <div class="box"> <div class="pic"> <img src="images/02.jpg"> </div> </div> <div class="box"> <div class="pic"> <img src="images/03.jpg"> </div> </div> <div class="box"> <div class="pic"> <img src="images/04.jpg"> </div> </div> <div class="box"> <div class="pic"> <img src="images/05.jpg"> </div> </div> <div class="box"> <div class="pic"> <img src="images/06.jpg"> </div> </div> </div> <script src="js/index.js"></script> </body> </html>
JavaScript代码:
var parent = document.getElementById('container'); function WaterFall() { imgLocation('box'); const data = [{'img':'01.jpg'},{'img':'02.jpg'},{'img':'03.jpg'}, {'img':'04.jpg'},{'img':'05.jpg'},{'img':'06.jpg'},{'img':'07.jpg'}, {'img':'08.jpg'},{'img':'09.jpg'},{'img':'10.jpg'},{'img':'11.jpg'}, {'img':'12.jpg'},{'img':'13.jpg'},{'img':'14.jpg'},{'img':'15.jpg'}, {'img':'16.jpg'},{'img':'17.jpg'},{'img':'01.jpg'},{'img':'02.jpg'}, {'img':'03.jpg'},{'img':'04.jpg'},{'img':'05.jpg'},{'img':'06.jpg'}, {'img':'07.jpg'},{'img':'08.jpg'},{'img':'09.jpg'},{'img':'10.jpg'}, {'img':'11.jpg'},{'img':'12.jpg'},{'img':'13.jpg'},{'img':'14.jpg'}, ]; window.addEventListener('scroll',()=>{ if (checkLoading('box')){ //加载新的图片 data.map((current)=>{ const newBox = document.createElement('div'); newBox.className = 'box'; parent.appendChild(newBox); const newPic = document.createElement('div'); newPic.className = 'pic'; newBox.appendChild(newPic); const newImg = document.createElement('img'); newImg.src = 'images/'+current.img; newPic.appendChild(newImg); }); imgLocation('box'); } }); } function checkLoading(child){ const content = getChilds(child); const lastTop = content[content.length - 1].offsetTop; const scrollTop = document.body.scrollTop || document.documentElement.scrollTop; const pageTop = document.body.clientHeight || document.documentElement.clientHeight; if ((scrollTop + pageTop > lastTop) ||(scrollTop == 0 && lastTop < pageTop)){ return true; } } function imgLocation(child){ const content = getChilds(child); const imgWidth = content[0].offsetWidth; const num = Math.floor(document.body.clientWidth / imgWidth); //让图片灵活居中 parent.style.cssText = 'width:'+ imgWidth * num + 'px;margin:0 auto;'; //计算图片的高度 const heightArr = []; [].map.call(content,(current,index)=>{ if (index < num){ heightArr.push(current.offsetHeight); } else { //得到图片的最小高度 const minHeight = Math.min(...heightArr); //得到最小高度的序列号 const minIndex = getMinIndex(minHeight,heightArr); current.style.position = 'absolute'; current.style.top = minHeight + 'px'; current.style.left = content[minIndex].offsetLeft + 'px'; //更新最小的高度 heightArr[minIndex] += current.offsetHeight; } }); } //将父级元素下的所有符合条件的子元素获取 function getChilds(child){ const childArr = []; const tagsAll = parent.getElementsByTagName('*'); [].map.call(tagsAll,(current)=>{ if (current.className == child){ childArr.push(current); } }); return childArr; } function getMinIndex(minHeight,heightArr){ for (const i in heightArr){ if (minHeight == heightArr[i]){ return i; } } } window.addEventListener('load',WaterFall());
结果:运行成功。
编程的时候出现的报错:
报错1:Uncaught TypeError: Cannot read property 'getElementsByTagName' of null
原因:页面的加载顺序问题,将script添加到body的后面
报错2:HTMLCollection []问题
原因:在获取container下的所有节点的时候,const tagsAll = parent.getElementsByTagName('*'); 得到的是HTMLCollection,它不是数组,会动态改变。
所以采用以下编程方法:
[].map.call(tagsAll,(current)=>{ if (current.className == child){ childArr.push(current); }
待完善的:
窗口大小改变的时候,在不用刷新的情况下图片自动更改适应瀑布流
使用ajax请求图片数据
在点击相应的图片的时候,背景变暗,被点击的图片被放大。
异步请求数据的时候,如果未知图片的高度,怎么办?
移动端的优化。