一、图片的预加载
图片的预加载就是在加载 js 的时候,提前加载图片,加载完成之后(图片会存到浏览器缓存中),再将图片路径赋值给页面的图片。
图片预加载的实现原理:
1、先不给页面图片的src属性赋值
2、将图片的路径放在一个数组中;
3、创建一个image对象;
4、将该image对象的src属性设为即将要加载的图片的路径;
5、给该image对象设置加载完成事件,加载完成之后(图片会存到浏览器缓存中),再将该image对象的src属性值赋值给页面的图片。
举例:
<img src="" id="img" alt="加载失败!"/>
<script>
//使用远程路径加载图片,将图片的远程路径放在数组中
var str =
["https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=1298282578,487436402&fm=26&gp=0.jpg",
"https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=1259401293,3815682953&fm=26&gp=0.jpg"
];
var imgdata=document.querySelector("#img");
//创建一个image对象
var image=new Image();
image.src=str[0];
//图片加载完成事件 加载完成之后 将路径赋值给页面的图片
image.onload=function(){
imgdata.src=this.src;
}
</script>
二、图片的懒加载
当一个页面需要加载的图片过多时,为了缓解服务器压力,增强用户体验,可以使用图片的懒加载,即:优先加载可视区域的内容,其他部分等进入了可视区域再加载。
图片懒加载的实现原理:
1、设置图片src属性为同一张图片,或者先不给src属性赋值,同时自定义一个data-img(可以自定义属性名称)属性来存储图片的真实地址;
2、 判断图片是否在可视区域;
3、 当图片出现在可视区域时,再将data-img的值赋给该区域图片的src属性。
代码如下:
<head>
<meta charset="UTF-8">
<title></title>
<style>
* {
margin: 0;
padding: 0;
}
.box {
height: 1000px;
}
.imgbox {
width: 820px;
border-top: 1px solid #000000;
margin: 0 auto;
}
.imgbox > img {
width: 190px;
margin: 5px;
}
</style>
</head>
<body>
<div class="box">
</div>
<div class="imgbox">
<img data-img="https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=1578121069,3381500888&fm=15&gp=0.jpg"
src="./image/baseimg.png" alt=""/>
<img data-img="https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=1578121069,3381500888&fm=15&gp=0.jpg"
src="./image/baseimg.png" alt=""/>
<img data-img="https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=1578121069,3381500888&fm=15&gp=0.jpg"
src="./image/baseimg.png" alt=""/>
<img data-img="https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=1578121069,3381500888&fm=15&gp=0.jpg"
src="./image/baseimg.png" alt=""/>
<img data-img="https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=1578121069,3381500888&fm=15&gp=0.jpg"
src="./image/baseimg.png" alt=""/>
<img data-img="https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=1578121069,3381500888&fm=15&gp=0.jpg"
src="./image/baseimg.png" alt=""/>
<img data-img="https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=1578121069,3381500888&fm=15&gp=0.jpg"
src="./image/baseimg.png" alt=""/>
<img data-img="https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=1578121069,3381500888&fm=15&gp=0.jpg"
src="./image/baseimg.png" alt=""/>
</div>
<script>
var imgbox = document.querySelector(".imgbox");
window.onscroll = function () {
if (checkbool()) {
setTimeout(function () {
for (var i = 0; i < imgbox.children.length; i++) {
imgbox.children[i].src = imgbox.children[i].getAttribute("data-img");
}
}, 1000);
}
};
function checkbool() {
return imgbox.offsetTop - window.scrollY <= document.documentElement.clientHeight;
}
</script>
</body>
三、图片瀑布流加载的案例
瀑布流,又称瀑布流式布局。是比较流行的一种网站页面布局,视觉表现为参差不齐的多栏布局,随着页面滚动条向下滚动,这种布局还会不断加载数据块并附加至当前尾部。
创建图片时需要一个一个创建,否则无法动态获取元素的左边距和上边距;
先加载第一页的图片,滚动轴滑到底部,再加载第二批、第三批、、、
案例一:
使用图片的预加载,再将一次性计时器使用递归做成循环计时器,实现每张图片的延迟加载。(具体代码如下)
<head>
<meta charset="UTF-8">
<title></title>
<style>
*{
margin: 0;
padding: 0;
}
.box{
position: relative;
width: 1100px;
min-height: 200px;
border: 1px solid #000000;
margin: 0 auto;
}
.list{
position: absolute;
width: 100px;
height: auto;
margin: 5px;
opacity: 0;
transition: opacity .2s linear;
}
</style>
</head>
<body>
<div class="box">
</div>
<script>
//加载图片的远程路径
var str = [
"https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=1298282578,487436402&fm=26&gp=0.jpg",
"https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=1259401293,3815682953&fm=26&gp=0.jpg",
"https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=2784122952,3562453652&fm=15&gp=0.jpg",
"https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=2553781316,2986187814&fm=26&gp=0.jpg",
"https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=1578121069,3381500888&fm=15&gp=0.jpg"
];
var box = document.querySelector(".box");
var list = document.getElementsByClassName("list");
var srcIndex = 0;//获取图片路径随机值
var imgCount = 40;//默认加载图片的数量
var count = 0;
var showrow = 10;
var maxHeight = 0;
creatimage();
function creatimage() {
//新建一个Image对象
var beforeimg = new Image();
beforeimg.classList.add("list");
//设置图片索引随机值
srcIndex = parseInt(Math.random() * str.length);
beforeimg.src = str[srcIndex];
//图片预加载
beforeimg.onload = function () {
var that = this;
box.appendChild(this);
//这里实现延迟加载 使用一次性计时器 递归来实现
setTimeout(function () {
setimagestyle(that);
if (count >= imgCount - 1) {
return;
}
count++;
creatimage();
}, 100);
};
beforeimg.onerror = function () {
beforeimg.alt = "图片加载失败";
};
beforeimg = null;
}
//设置Image对象的相关样式
function setimagestyle(obj) {
obj.style.opacity = 1;
//图片的左偏移
obj.style.left = (count % showrow * 110) + "px";
var top = 0;
if (count < showrow) {
top = 0;
}
else {
//上一行同一位置的元素的offsetHeight 加上上一行同一位置的元素上边框到box上边框的距离
top = list[count - showrow].offsetHeight + list[count - showrow].offsetTop;
}
obj.style.top = top + "px";
//动态计算box最大高
var offset = obj.offsetHeight + top;
//var offset=obj.offsetHeight+top
if (offset >= maxHeight) {
maxHeight = offset;
}
box.style.height = maxHeight + 10 + 20 + "px"; //20是让box多20px的高
}
//滚动条事件
window.onscroll = function () {
//console.log(this.scrollY); //12.8
//console.log(document.documentElement.clientHeight); //714
//console.log(document.body.clientHeight); //739
var htmlH = document.documentElement.clientHeight;
var bodyH = document.body.clientHeight;
if (this.scrollY + htmlH >= bodyH) {
imgCount += 20;
count++;
creatimage();
}
};
</script>
</body>
案例二:
使用的本地图片,所以没有使用预加载
<head>
<meta charset="UTF-8">
<title></title>
<style>
* {
margin: 0;
padding: 0;
}
#box {
position: relative;
width: auto;
}
.list {
position: absolute;
width: 120px;
border: 4px solid #c0c0c0;
box-sizing: border-box;
}
.list > img {
width: 100%;
height: auto;
vertical-align: middle;
}
</style>
</head>
<body>
<div id="box">
</div>
<script>
//将图片名称存在数组里边
var defaul = 40; //定义默认显示值
var count = 0; //记录一行显示几个
var sleft = 0; //当前屏幕留下的空白值平分给每个元素的值
var boxh = 0; //记录box的高
var arr = ["3.jpg", "4.jpg", "5.jpg", "7.jpg", "12.jpg", "14.jpg", "17.jpg", "19.jpg", "20.jpg"];
var box = document.getElementById("box");
//动态获取创建的div
var list = document.getElementsByClassName("list");
//构建一个算法 计算count
proNum();
function proNum() {
count = Math.floor(this.innerWidth / 120);
sleft = (this.innerWidth - count * 120 - 25) / count;
}
/*
* 构建方法 创建元素添加到box里边
* */
for (var i = 0; i < defaul; i++) {
creatElement();
}
function creatElement() {
//创建div包img元素
var imgbox = document.createElement("div");
imgbox.className = "list";
//创建img元素
var img = new Image();
img.src = "./img/" + arr[Math.floor(Math.random() * 9)];
imgbox.appendChild(img);
box.appendChild(imgbox);
}
/*
* 添加一个加载完成事件
* */
window.onload = function () {
//设置list的left top 以及box的高 要注意offset值不对的问题,需要在浏览器加载完成后再获取
setOffset();
function setOffset() {
//for循环遍历list 设置每个list的left 和top
for (var i = 0; i < list.length; i++) {
//top值
if (i < count) {
list[i].style.top = "5px";
}
else {
list[i].style.top = (list[i - count].offsetHeight + list[i - count].offsetTop + 5) + "px";
}
//left值
list[i].style.left = (i % count) * (sleft + 120) + "px";
//box 的高
if (list[i].offsetHeight + list[i].offsetTop >= boxh) {
boxh = list[i].offsetHeight + list[i].offsetTop + 10;
}
box.style.height = boxh + "px";
}
}
/*
* 添加浏览器的滚动条事件
* */
this.onscroll = function () {
if (this.scrollY + this.innerHeight >= document.documentElement.scrollHeight) {
defaul += count; //每次在原基础上多一行
for (var i = defaul - count; i < defaul; i++) {
creatElement();
}
setOffset();
}
};
/*
* 浏览器窗口发生变化事件
* */
var time = null;
this.onresize = function () {
if(time)clearTimeout(time);
time = setTimeout(function () {
//浏览器窗口发生变化后,重新计算count、sleft、box高、list的left和top
proNum();
boxh=0;
setOffset();
},300)
}
}
</script>
</body>