思路
求两个距离 A:浏览器底边距离BODY顶部的距离/这种是图片完全显示在浏览器窗口中 如果想图片刚露头就加载则不要加{图片盒子.offsetHeight}
- 图片距离body的上偏移,offset(图片盒子).top+图片盒子.offsetHeight
- utils.offset(lazyImgbox).top + lazyImgbox.offsetHeight
B:图片所在盒子底边框距离BODY顶部的距离【和滚动条滚动没关系,页面布局完成,他的位置就固定下来的】
浏览器窗口的高度+scrollTop(滚动卷去的高度 随着浏览器滚动需要不断变化的值)
- 浏览器窗口的高度=document.documentElement.clientHeight
- 卷去的高度=document.documentElement.scollTop
监听滚动事件 window.onscroll B<=A的距离 图片加载
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="./css/reset.min.css">
<style>
/* 当img没有src这个属性 display:none*/
/* img:not([src]){display:none} 这个在reset.min.css中有*/
/* 再增加当图片的src为空时也不显示img */
img[src=""] {
display: none;
}
.lazyImgBox {
box-sizing: border-box;
width: 300px;
height: 500px;
margin: 1000px 0;
background: url("./img/default.gif") no-repeat center center #eee;
}
.lazyImgBox img {
width: 100%;
height: 100%;
/* 为了后期图片显示有动画效果 */
opacity: 0;
transition:opacity .1s ease 0s;
}
</style>
</head>
<body>
<div class="lazyImgBox">
<img src="" alt="" data-src="./img/1.jpg">
</div>
<script src="./js/utils.js"></script>
</body>
</html>
JS
<script>
let lazyImgbox = document.querySelector('.lazyImgBox'),
img = lazyImgbox.querySelector('img'),
Html = document.documentElement;
//B:图片所在盒子底边距离BODY顶端的距离
//cH:浏览器可视窗口一屏幕的高度
//A:浏览器底边框距离BODY顶端的距离
let B = utils.offset(lazyImgbox).top + lazyImgbox.offsetHeight,
cH = Html.clientHeight;
A = 0;
//=》已经处理过了,则其余都不在处理
window.onscroll = function () {
if(img.isload) return;
A = cH + Html.scrollTop;
// 延迟加载图片 是图片完全出现在可视窗口中(B<=A)
if (B <= A) {
//问题;当我们把图片加载出来(或者地址不存在没加载,但是也处理了) 但是对着浏览器继续滚动,B<=A的条件一直成立 会一致触发延迟加载操作 =》在第一次处理完成后,后续即使在符合条件我们也不处理了
lazy();
}
};
// 进行图片延迟加载的
function lazy() {
let trueSrc = img.getAttribute('data-src');
let tempImg = new Image;
tempImg.src = trueSrc;
// onload能触发证明加载成功
tempImg.onload = function () {
img.src = trueSrc;
img.offsetHeight;//=>先让上面显示的样式渲染(触发一次回流),再让下面透明度的样式改变,这样就能着到动画效果了
utils.css(img,'opacity','1')
};
img.removeAttribute('data-src');
tempImg = null;
img.isload = true;//=>无论成功还是失败 都标识一下 当前图片已经处理过了
};
</script>