图片懒加载(图片延迟加载):当图片不在浏览器可视区域中时(即我们此时看不见图片),我们可以先不请求图片资源,当图片出现在浏览器可视区域中时再加载资源。
实现思路
1.结构中,我们用一个盒子包裹着图片(在图片不展示的时候,可以占据着这个位置,并且设置默认的背景图或者背景颜色)
2.最开始,img的src中不设置任何的图片地址,把图片的真实地址设置给自定义属性true-img(最开始不展示图片:可以让图片隐藏)
3.当浏览器窗口完全展示到图片位置的时候,我们再去加载真实图片,并且让其显示出来(第一屏幕中的图片一般都会延迟加载,来等待其它资源先加载完)
单张图片懒加载
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
* {
padding: 0;
margin: 0;
}
html,body {
width: 100%;
height: 100%;
}
#box {
width: 300px;
height: 200px;
margin: 800px auto;
}
img {
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<div id="box">
<img src="img/default.jpg" true-img="img/1.jpg" alt="">
</div>
</body>
</html>
<script src="utils.js"></script>
<script>
var box=document.getElementById('box');
var img=document.getElementsByTagName("img")[0];
function check(){
//滚动条一滚动就触发window.onscroll,为了避免重复加载图片,给img加一个flag属性,成功加载图片后将其值设为true
if(img.flag){
return;
}
let boxH=box.offsetHeight;//当前图片盒子的总高度
let boxT=utils.offset(box).top;//获取当前图片盒子距离body的上偏移量
let winH=utils.win('clientHeight');//获取当前浏览器的可视区域的高度(一屏高)
let winT=utils.win('scrollTop');//获取当前浏览器滚动条的卷曲的高度
//图片盒子下边框与浏览器可视区域的下边框重合时,图片完全显示
//早一些显示图片:winH+winT >= boxT
if(winH+winT >= boxH+boxT){
let trueImg=img.getAttribute("true-img");
//let newImg=document.createElement('img');//创建一个img标签
let newImg=new Image;//动态创建一个img标签用来检测当前图片的真实路径是否有效
newImg.arc=trueImg;//把真实的路径给检测的img去请求
//如果请求到了图片,onload才会执行(如果当前路径是正确的,那onload对应的函数就会执行)
newImg.onload=function(){
img.src=trueImg;
img.flag=true;
fadeIn(img);//渐入
}
//如果请求失败,onerror执行(如果当前路径是错误的,那onerror对应的函数就会执行)
newImg.onerror=function(){
//可以给当前图片附一张默认的加载错误图片
img.src='img/10.jpg';
img.flag=true;
}
}
function fadeIn(img){
img.style.opacity=0.01;
let opacity=Number(img.style.opacity);
let timer=setInterval(()=>{
opacity+=0.01;
img.style.opacity=opacity;
if(opacity>=1){
clearInterval(timer);
}
},17);
}
}
window.onscroll=check;
</script>
多张图片懒加载
<head>
<style>
* {
padding: 0;
margin: 0;
}
div {
margin: 500px auto;
width: 300px;
}
img {
display: block;
margin: auto;
width: 300px;
height: 200px;
margin-bottom: 10px;
}
</style>
</head>
<body>
<div>
<img src="./img/default.jpg" trueImg = "./img/1.jpg" alt="">
<img src="./img/default.jpg" trueImg = "./img/2.jpg" alt="">
<img src="./img/default.jpg" trueImg = "./img/3.jpg" alt="">
<img src="./img/default.jpg" trueImg = "./img/4.jpg" alt="">
<img src="./img/default.jpg" trueImg = "./img/5.jpg" alt="">
<img src="./img/default.jpg" trueImg = "./img/6.jpg" alt="">
</div>
<script src="utils.js"></script>
<!-- <script src="">
//如果写了src,内部所有代码都会失效
</script> -->
<script>
var imgs=document.getElementsByClassName("bg");//具有映射关系
let winH = utils.win('clientHeight'); // 当前屏幕的高度(浏览器可视区域高度)
// 此方法每执行一次,就会把每一个图片都判断一下要不要显示
function dealy(){
//当函数执行的时候,循环每一张图片,然后判断每一张图片是否需要加载
for (var i = 0; i < imgs.length; i++) {
dealyImg(imgs[i])
}
}
function dealyImg (img){
/* if(img.flag){
return;
} */
let curH = img.offsetHeight; // 图片的自身高度
let curT = utils.offset(img).top; // 图片相对于body的上偏移量
let winT = utils.win('scrollTop'); // 浏览器滚动条卷去的高度
if(winH+winT >= curH+curT){
let address = img.getAttribute('trueImg');
let newImg = new Image;
newImg.src = address;
newImg.onload = function(){
img.src = address;
// img.flag=true;
img.className="";
newImg = null;
fadeIn(img);
}
}
}
function fadeIn(img) {
img.style.opacity = 0.05;
let cur = parseFloat(img.style.opacity);
let timer = setInterval(function () {
cur += 0.05;
img.style.opacity = cur;
if (cur >= 1) {
clearInterval(timer)
}
}, 50)
};
dealy(); // 页面初始化的时候,要把第一屏的图片展示出来
window.onscroll = dealy;
</script>
utils.js
let utils=(function(){
/* 获取盒子距离body的偏移量 */
function offset(ele) {
let left = ele.offsetLeft;
let top = ele.offsetTop;
let parent = ele.offsetParent;
while (parent !== document.body) {
left += parent.offsetLeft + parent.clientLeft;
top += parent.offsetTop + parent.clientTop;
parent = parent.offsetParent;
}
return {
left,
top
}
}
/* 设置或者获取浏览器的某些属性 */
function win(attr,value){
if(value==undefined){
return document.documentElement[attr] || document.body[attr];
}
document.documentElement[attr]=value;
document.body[attr]=value;
}
return {
offset,
win
}
})();