什么是瀑布流
瀑布流又称瀑布流式布局,是比较流行的一种网站页面布局方式。视觉表现为参差不齐的多栏布局,最早采用此布局的是网站是 Pinterest,后逐渐在国内流行。
链接文章:浅谈瀑布流
什么是懒加载
懒加载其实就是延迟加载,是一种对网页性能优化的方式。
比如当访问一个页面的时候,优先显示可视区域的图片,而不一次性加载所有图片,当需要显示的时候再发送图片请求,避免打开网页时加载过多资源。
什么时候用懒加载
当页面中需要一次性载入很多图片的时候,往往都是需要用懒加载的。
懒加载原理
链接文章:js实现图片懒加载原理
<img>
标签有一个属性是src
,用来表示图像的URL
,当这个属性的值不为空时,浏览器就会根据这个值发送请求;如果没有src属性,就不会发送请求。
那可不可以这样想,图片一开始不设置src,当需要的时候再设置?
可以。
我们先不给< img >设置src,把图片真正的URL放在另一个属性data-src
中,在需要的时候也就是图片进入可视区域的之前,将URL取出放到src中。
涉及的知识点:
(1) 图片距离顶部的高度:img.offsetTop
(2) 当前窗口的高度:window.innerHeight
(3) 滚动条滚动的高度:document.body.scrollTop || document.documentElement.scrollTop
加载图片的判断条件:
图片距离顶部的距离 < 浏览器滚动条滚动的高度 + 浏览器窗口的高度
图片懒加载、瀑布流效果 示例
案例1:div模拟图片加载
为了更直观看到效果,没有放入真正的图片,而是用div去模拟图片;创建div,然后设置随机高度模拟不同图片的高度。
(注意:以下说的图片皆是div模拟的图片,以背景形式展示图片)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="./js/jquery-3.2.1.js"></script>
<style>
div {
position: absolute;
width: 200px;
color: white;
}
</style>
</head>
<body>
<script>
class WaterFall{
constructor() {
}
//生成div,每次执行这个函数都生成20个div,用来模拟图片
// 每次生成20张div
createDiv(){
for(let i=0; i<20; i++){
let div = document.createElement("div");
div.innerHTML = i;
let rnd = Math.round(Math.random()*300+50);//生成50~350的随机数
div.style.height = rnd + "px";
div.date_src = "url(./img/" + i + ".jpg)";
div.style.backgroundSize = "200px" + " " + rnd + "px";
document.body.appendChild(div);
}
this.change();
}
change(){
let oArrDiv = document.getElementsByTagName("div");//获取所有的div
//计算的是窗口显示大小变化时,显示的几个div(每个div宽度200px,间隔10px),所以,n代表的是一行最多排几个div
let n = Math.floor(window.innerWidth/210);//innerwidth 返回窗口的文档显示区的宽度。
let arrH = [];//记录之前对应每列div的高度和
//遍历所有div,根据窗口大小安排一行几个div;
//因为图片高度随机,所以第一次把div模拟的图片放上去后,计算每一列的总高度;
//在最短的列下面添加新的div,位移left值以该列index计算,top值以每列高度加上垂直间距10来计算。
for(let i=0; i<oArrDiv.length; i++){
//图片距离顶部的距离 < 浏览器滚动条滚动的高度 + 浏览器窗口的高度
if(oArrDiv[i].offsetTop < document.documentElement.scrollTop + document.documentElement.clientHeight){
this.loadImg(oArrDiv[i]);//加载图片
}
//除了第一行上传图片的top为0外,其余图片都需要进行判断,在最小高度列下面添加新的图片,top=该列此时高度+垂直间距10px。
//在首行排列完后,arrH[i]就已经代表每列的总高度,而arrH.length则代表窗口最大容纳div数。
//如果arrH.length==当前窗口水平容纳的最大div数,说明不是第一行。
if(arrH.length == n){
let index = this.findMin(arrH);//寻找最小高度的一列,然后返回这一列的序列号
oArrDiv[i].style.left = 200*index + 10*index + "px";//然后计算这列水平方向的距离
oArrDiv[i].style.top = arrH[index] + 10 + "px";//然后计算这列垂直方向的距离。在前面对应每列div的高度总和的基础上,把新的垂直间距也加上。
arrH[index] += oArrDiv[i].offsetHeight + 10;//然后,更新该列的总高度,把这一列新添加的元素的高度也加上
}else{
//第一行
oArrDiv[i].style.top = "0" + "px";
oArrDiv[i].style.left = 200*i + 10*i + "px";//因为每个div的宽度都是200px,所以此处将每个div距离为10px(div绝对定位)
arrH[i] = oArrDiv[i].offsetHeight;//offsetHeight只读属性,返回该元素的像素高度。
//所以,此时arrH[i]记录图片初始高度
}
}
}
//找到最小高度列
findMin(arrH){
let index = 0;
for(let i=0; i<arrH.length; i++){
if(arrH[index]>arrH[i]){
index = i;
}
}
return index;
}
// 滚动条如果超过400,则自动加载,重新创建新的div出来
moveScroll(){
let top = 0;//用来记录垂直方向滚动的值
let that = this;
window.onscroll = function(){
top = document.body.scrollTop || document.documentElement.scrollTop;
// console.log("top:",top);
if(top > 400){
that.createDiv();
// console.log("top>400")
// console.log("网页被卷去的高:",document.body.scrollTop)
// console.log("要获取当前页面的滚动条纵坐标位置,用:",document.documentElement.scrollTop)
}
}
}
loadImg(oDiv){
//如果此div的属性不存在,说明未被加载
if(oDiv.src == null){
oDiv.style.backgroundImage = oDiv.date_src;
}
}
}
let wf = new WaterFall();
wf.createDiv();
// wf.createDiv();
wf.moveScroll();
// console.log("浏览器窗口的内部高度:",window.innerHeight)
// console.log("表示HTML文档所在窗口的当前高度:",document.documentElement.clientHeight)
// console.log("Document对象的body属性对应HTML文档的<body>标签:",document.body.clientHeight)
// console.log("网页被卷去的高:",document.body.scrollTop)
// console.log("要获取当前页面的滚动条纵坐标位置,用:",document.documentElement.scrollTop)
</script>
</body>
</html>