image.png

思路

求两个距离 A:浏览器底边距离BODY顶部的距离/这种是图片完全显示在浏览器窗口中 如果想图片刚露头就加载则不要加{图片盒子.offsetHeight}

  1. - 图片距离body的上偏移,offset(图片盒子).top+图片盒子.offsetHeight
  2. - 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>