原生JS实现照片瀑布流与懒加载
2017-08-27 本文已影响1358人
八宝君
什么是瀑布流和懒加载
瀑布流是目前比较流行的一种网站页面布局,会在网页上呈现参差不齐的多栏布局,页面向下滚动,网页就会不断加载数据块并附加至当前页面尾部。
它的好处就是按需加载:
根据我们每行图片的最小高度来动态的加载图片
1.首屏加载的是减少向http请求次数
2.减少浏览器以及服务器的内存负荷
demo2.gif效果图是这样滴
首先看一下布局:
// html部分 img标签部分发布的时候就变成了![]了,,不知道怎么改
<div id="container">
<div class="box">
<div class="box-img">
![](images/0.jpg)
</div>
</div>
<div class="box">
<div class="box-img">
![](images/1.jpg)
</div>
</div>
<div class="box">
<div class="box-img">
![](images/2.jpg)
</div>
</div>
<div class="box">
<div class="box-img">
![](images/3.jpg)
</div>
</div>
<div class="box">
<div class="box-img">
![](images/4.jpg)
</div>
</div>
<div class="box">
<div class="box-img">
![](images/5.jpg)
</div>
</div>
<div class="box">
<div class="box-img">
![](images/6.jpg)
</div>
</div>
<div class="box">
<div class="box-img">
![](images/7.jpg)
</div>
</div>
<div class="box">
<div class="box-img">
![](images/8.jpg)
</div>
</div>
<div class="box">
<div class="box-img">
![](images/9.jpg)
</div>
</div>
<div class="box">
<div class="box-img">
![](images/10.jpg)
</div>
</div>
<div class="box">
<div class="box-img">
![](images/11.jpg)
</div>
</div>
</div>
// CSS部分
*{
margin: 0;
padding: 0;
}
#container{
position: relative;
}
.box{
float: left;
padding: 5px;
}
.box-img{
padding: 5px;
border: 1px solid #ccc;
box-shadow: 0 0 5px #ccc;
border-radius: 5px;
}
.box-img img{
width: 230px;
height: auto;
}
JS部分的逻辑
首先我们得秉承着多人协作的思想来写,因为代码不一定只是给一个人看到,所以为了避免全局污染,要用函数模块化封装的的思想。如果直接写在全局,一个项目可能有多个模块函数,命名变量名的时候并不知道其他人的命名,可能会导致bug。所以全局部分只写怎么来用这个封装好了的函数。
window.onload = function () {
imgLocation('container', 'box');
// 模仿数据
var imgData = {"data": [{"src":"24.jpg"},{"src":"25.jpg"},{"src":"26.jpg"},{"src":"27.jpg"},{"src":"28.jpg"}]};
window.onscroll = function () {
if (checkFlag()) {
var cparent = document.getElementById("container");
for (var i =0; i<imgData.data.length; i++) {
var ccontent = document.createElement('div');
ccontent.className = 'box';
cparent.appendChild(ccontent);
var boxImg = document.createElement('div');
boxImg.className = 'box-img';
ccontent.appendChild(boxImg);
var img = document.createElement("img");
img.style.cssText = 'opacity: 0; transform:scale(0)';
img.src = "images/" + imgData.data[i].src + "";
boxImg.appendChild(img);
(function(img){ // 自执行程序闭包
setTimeout(function(){
img.style.cssText="opacity:1;transform:scale(1)";
},1000); // 这里的时间自定,我是为了测试才写的1000
})(img);
}
imgLocation('container', 'box');
}
}
};
首先我们得定位图片的位置
function imgLocation(parent, content) {
// 将parent下面的所有content全部取出
var cparent = document.getElementById(parent);
var ccontent = getChildElement(cparent, content);
// 完善图片布局
var imgWidth = ccontent[0].offsetWidth; // 图片的宽度
var num = Math.floor(document.documentElement.clientWidth / imgWidth); // 横排的显示个数
cparent.style.cssText = "width:" + imgWidth * num + "px;margin: 0 auto"; // 给父级添加宽度
// 计算图片的高度
var boxHeightArr = [];
for (var i=0; i<ccontent.length; i++) {
if(i < num) {
boxHeightArr[i] = ccontent[i].offsetHeight;
console.log(boxHeightArr);
} else {
var minHeight = getMin(boxHeightArr); //最小的高度
var minIndex = getMinheightLocation(boxHeightArr, minHeight);
ccontent[i].style.position = 'absolute';
ccontent[i].style.top = minHeight + 'px';
ccontent[i].style.left = ccontent[minIndex].offsetLeft + 'px';
boxHeightArr[minIndex] = boxHeightArr[minIndex] + ccontent[i].offsetHeight; // 更新最小高度
}
}
}
这里面有三个函数,一个是得到图片最小高度的函数getMin(arr)
,为什么要得到最小高度?因为我们计算第一排最小高度的图片之后,第二排的图片排序是这样的,第一张排在第一排的最小高度图片下,第二张排在第一排倒数第二高度图片下,依次排完第二排,后面的图片排序都是按照这样来排。
function getMin(arr) { // 得到图片的最小高度
for(var i=0, ret=arr[0]; i<arr.length; i++) {
ret = Math.min(ret, arr[i]); // 依次将最小值赋值给ret,ret始终最小
}
return ret;
}
还有一个函数是得到最小高度图片索引getMinheightLocation
:
function getMinheightLocation(boxHeightArr, minHeight) { // 得到图片最小高度的序列号
for (var i in boxHeightArr) {
if ( boxHeightArr[i] === minHeight) {
return i;
}
}
}
要得到索引位置,才能将图片排在这个索引位置下。
另外一个是得到子集空间的函数,一开始就强调要用模块化的思想来做,我们要做的是函数之外,全局部分才用html
里的id值,函数只通过传参来得到里面的东西。
function getChildElement(cparent, content) { // 得到子集空间
var contentArr = [];
var allcontent = cparent.getElementsByTagName('*'); // 获取到所有的元素
for (var i=0; i<allcontent.length; i++ ) {
if (allcontent[i].className === content) {
contentArr.push(allcontent[i]);
}
}
return contentArr;
}
关于懒加载
懒加载的思想是 页面的高度 + 滚动的高度 > 最后一张图片距离浏览器顶部的高度,然后就开始加载图片。
function checkFlag() {
var cparent = document.getElementById('container');
var ccontent = getChildElement(cparent, "box");
// 数组最后一个元素的高度距离顶部的距离
var lastContentHeight = ccontent[ccontent.length-1].offsetTop;
var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
var pageHeight = document.documentElement.clientHeight || document.body.scrollHeight;
if(lastContentHeight < scrollTop + pageHeight){
return true;
}
}