原生JavaScript实现响应式瀑布流懒加载图片布局
part.1 项目简介
编辑器:Atom
版本管理:Git
代码托管:Github
目录结构:
part.2 项目布局
<body>
<h2>响应式瀑布流懒加载效果</h2>
<div class="container" id="theContainer">
<div class="box">
<div class="inner-box">
<img src="yys/cube.gif" data-src="yys/1.jpg" alt="">
</div>
</div>
<div class="box">
<div class="inner-box">
<img src="yys/cube.gif" data-src="yys/2.jpg" alt="">
</div>
</div>
<div class="box">
<div class="inner-box">
<img src="yys/cube.gif" data-src="yys/3.jpg" alt="">
</div>
</div>
<div class="box">
<div class="inner-box">
<img src="yys/cube.gif" data-src="yys/4.jpg" alt="">
</div>
</div>
<div class="box">
<div class="inner-box">
<img src="yys/cube.gif" data-src="yys/5.jpg" alt="">
</div>
</div>
<div class="box">
<div class="inner-box">
<img src="yys/cube.gif" data-src="yys/6.jpg" alt="">
</div>
</div>
<div class="box">
<div class="inner-box">
<img src="yys/cube.gif" data-src="yys/7.jpg" alt="">
</div>
</div>
<div class="box">
<div class="inner-box">
<img src="yys/cube.gif" data-src="yys/8.jpg" alt="">
</div>
</div>
</div>
</body>
part.2 样式
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
body{
background: #ccc;
}
h2{
text-align: center;
padding-left: 20px;
margin: 40px 0;
}
.container{
width: 90%;
margin: 0 auto;
position: relative;
}
.container::after{
content: "";
display: block;
clear: both;
}
.box{
float: left;
padding: 10px;
margin: 1%;
position: absolute;
}
.inner-box{
background: white;
padding: 5px;
}
/*极小屏幕*/
@media only screen and (min-width: 768px) {
.box{
width: 50%;
}
.box img{
width: 100%;
}
}
/*小屏幕*/
@media only screen and (max-width: 768px) {
.box{
width: 100%;
}
.box img{
width: 100%;
}
}
/*中等屏幕*/
@media only screen and (min-width: 992px) {
.box{
width: 25%;
}
.box img{
width: 100%;
}
}
part.3 瀑布流实现函数
function waterFall(oParentId){
//用于保存每列高度的数组
var colHeights = [];
//所有Box的数组
var Boxes = getAllBoxes(oParentId);
//列数
var colNum = getCol();
for(var i=0;i<Boxes.length;i++){
//当前图片的高度
var oBoxHeight = Boxes[i].offsetHeight;
//当前图片的宽度
var oBoxWidth = Boxes[i].offsetWidth;
if(i<colNum){
//第一行图片直接排列
Boxes[i].style.top = 0+'px';
Boxes[i].style.left = i*oBoxWidth+'px';;
colHeights[i] = oBoxHeight;
}else{
//从第二行开始,图片追加到高度最小的一列
var minHeight = Math.min.apply(null,colHeights); //最小列的高度
var minHeightCol = colHeights.indexOf(minHeight);//最小列
//使用绝对定位,确定图片的位置
Boxes[i].style.top = minHeight+'px';
Boxes[i].style.left = minHeightCol*oBoxWidth+'px';
//更新列高
colHeights[minHeightCol]+=oBoxHeight;
}
}
}
part.4 懒加载
//懒加载首屏数据
function lazyLoad(){
var boxes = getAllBoxes('theContainer');
for(var j=0;j<boxes.length;j++){
var oImg = new Image();
image = boxes[j].children[0].children[0];
oImg.src =image.getAttribute("data-src");
oImg.onload=(function(){
image.src = oImg.src;
waterFall('theContainer');
})();
}
}
//懒加载新数据
function getNewData(aData){
aData.forEach(function(item){
//给获取到的数据添加DOM结构
var outer = document.createElement('div');
var inner = document.createElement('div');
var image = document.createElement('img');
var parent = document.getElementById('theContainer');
outer.className = 'box';
inner.className = 'inner-box';
image.src='yys/cube.gif';
inner.appendChild(image);
outer.appendChild(inner);
parent.appendChild(outer);
//懒加载新数据
var oImg = new Image();
oImg.src =item;
oImg.onload=function(){
image.src = oImg.src;
waterFall('theContainer');
}
});
}
part.5 事件监听
window.onload=function(){
//页面加载完毕,开始懒加载图片
lazyLoad();
}
window.onresize=function(){
//改变窗口大小时,更新瀑布流状态
waterFall('theContainer');
}
window.onscroll=function(){
//监听屏幕滚动事件
var _scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
var _clientHeight = document.documentElement.clientHeight || document.body.clientHeight;
var _scrollHeight = document.documentElement.scrollHeight || document.body.scrollHeight;
//判断屏幕是否滚动到底部
if(_scrollTop+_clientHeight == _scrollHeight){
getNewData(imgData);
waterFall('theContainer');
}
}
part.6 工具函数
//获取容器内所有box
function getAllBoxes(parentId){
var oParent = document.getElementById(parentId);
var aBoxes = oParent.getElementsByClassName('box');
return aBoxes;
}
//获取当前屏幕下box的列数
function getCol(){
var windowWidth = document.documentElement.clientWidth || document.body.clientWidth;
if(windowWidth<768){
return 1;
}else if (windowWidth<992) {
return 2;
}else{
return 4;
}
}