<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0">
    <title>图片懒加载</title>

    <!-- IMPORT CSS -->
    <!-- <link rel="stylesheet" href="css/reset.min.css"> -->
    <!-- <link rel="stylesheet" href="css/index.css"> -->

    <style>

/* reset.min.css */
@charset "utf-8";
 
body, h1, h2, h3, h4, h5, h6, hr, p, blockquote, dl, dt, dd, ul, ol, li, button, input, textarea, th, td {
    margin: 0;
    padding: 0
}

body {
    font-size: 12px;
    font-style: normal;
    font-family: "\5FAE\8F6F\96C5\9ED1", Helvetica, sans-serif
}

small {
    font-size: 12px
}

h1 {
    font-size: 18px
}

h2 {
    font-size: 16px
}

h3 {
    font-size: 14px
}

h4, h5, h6 {
    font-size: 100%
}

ul, ol {
    list-style: none
}

a {
    text-decoration: none;
    background-color: transparent
}

a:hover, a:active {
    outline-width: 0;
    text-decoration: none
}

table {
    border-collapse: collapse;
    border-spacing: 0
}

hr {
    border: 0;
    height: 1px
}

img {
    border-style: none
}

img:not([src]) {
    display: none
}

svg:not(:root) {
    overflow: hidden
}

html {
    -webkit-touch-callout: none;
    -webkit-text-size-adjust: 100%
}

input, textarea, button, a {
    -webkit-tap-highlight-color: rgba(0, 0, 0, 0)
}

article, aside, details, figcaption, figure, footer, header, main, menu, nav, section, summary {
    display: block
}

audio, canvas, progress, video {
    display: inline-block
}

audio:not([controls]), video:not([controls]) {
    display: none;
    height: 0
}

progress {
    vertical-align: baseline
}

mark {
    background-color: #ff0;
    color: #000
}

sub, sup {
    position: relative;
    font-size: 75%;
    line-height: 0;
    vertical-align: baseline
}

sub {
    bottom: -0.25em
}

sup {
    top: -0.5em
}

button, input, select, textarea {
    font-size: 100%;
    outline: 0
}

button, input {
    overflow: visible
}

button, select {
    text-transform: none
}

textarea {
    overflow: auto
}

button, html [type="button"], [type="reset"], [type="submit"] {
    -webkit-appearance: button
}

button::-moz-focus-inner, [type="button"]::-moz-focus-inner, [type="reset"]::-moz-focus-inner, [type="submit"]::-moz-focus-inner {
    border-style: none;
    padding: 0
}

button:-moz-focusring, [type="button"]:-moz-focusring, [type="reset"]:-moz-focusring, [type="submit"]:-moz-focusring {
    outline: 1px dotted ButtonText
}

[type="checkbox"], [type="radio"] {
    box-sizing: border-box;
    padding: 0
}

[type="number"]::-webkit-inner-spin-button, [type="number"]::-webkit-outer-spin-button {
    height: auto
}

[type="search"] {
    -webkit-appearance: textfield;
    outline-offset: -2px
}

[type="search"]::-webkit-search-cancel-button, [type="search"]::-webkit-search-decoration {
    -webkit-appearance: none
}

::-webkit-input-placeholder {
    color: inherit;
    opacity: .54
}

::-webkit-file-upload-button {
    -webkit-appearance: button;
    font: inherit
}

.clearfix:after {
    display: block;
    height: 0;
    content: "";
    clear: both
}


/* index.css */
        html,
body {
    background: #D6D7DB;
}

.container {
    box-sizing: border-box;
    margin: 20px auto;
    width: 760px;
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
}

.container .column {
    box-sizing: border-box;
    width: 240px;
}

.card {
    margin-bottom: 10px;
    padding: 5px;
    background: #FFF;
    box-shadow: 3px 3px 10px 0 #222;
}

.card a {
    display: block;
}

.card a .lazyImageBox {
    /* height: xxx;  如果是需要进行图片延迟加载,在图片不显示的时候,我们要让盒子的高度等于图片的高度,这样才能把盒子撑开(服务器返回给我们的数据中,一定要包含图片的高度和宽度) */
    background: url("../images/default.gif") no-repeat center center #F4F4F4;
    overflow: hidden;
}

.card a .lazyImageBox img {
    width: 100%;
    opacity: 0;
    transition: opacity .3s;
}

.card a p {
    margin-top: 5px;
    color: #000;
    font-size: 12px;
    line-height: 20px;
}

.loadMore {
    height: 100px;
}
    </style>
</head>

<body>
    <div class="container clearfix">
        <div class="column">
            <!-- <div class="card">
                <a href="#">
                    <div class="lazyImageBox" style="height: 180px;">
                        <img src="" alt="" lazy-image="images/1.jpg">
                    </div>
                    <p>泰勒·斯威夫特(Taylor Swift),1989年12月13日出生于美国宾州,美国歌手、演员。2006年出道,同年发行专辑《泰勒·斯威夫特》,该专辑获得美国唱片业协会的白金唱片认证</p>
                </a>
            </div> -->
        </div>
        <div class="column"></div>
        <div class="column"></div>
    </div>
    <div class="loadMore"></div>

    <!-- IMPORT JS -->
    <!-- <script src="js/LazyImage.min.js"></script> -->
    <script>
        let waterfallModule = (function () {
    // 获取需要操作的DOM元素
    let container = document.querySelector('.container'),
        columns = container.querySelectorAll('.column'),
        loadMore = document.querySelector('.loadMore'),
        observe = null;
    columns = Array.from(columns);

    // 基于AJAX从服务器端获取数据
    const queryData = () => {
        return new Promise(resolve => {
            let xhr = new XMLHttpRequest;
            xhr.open('GET', './data.json');
            xhr.onreadystatechange = () => {
                if (xhr.readyState === 4 && (xhr.status >= 200 && xhr.status < 300)) {
                    let data = JSON.parse(xhr.responseText);
                    resolve(data);
                }
            };
            xhr.send(null);
        });
    };

    // 页面中的数据绑定
    const bindHTML = data => {
        data = data.map(item => {
            let AW = 230,
                BW = item.width,
                BH = item.height,
                AH = AW / (BW / BH);
            item.width = AW;
            item.height = AH;
            return item;
        });
        for (let i = 0; i < data.length; i += 3) {
            let group = data.slice(i, i + 3);
            group.sort((a, b) => a.height - b.height);
            columns.sort((a, b) => b.offsetHeight - a.offsetHeight);
            group.forEach((item, index) => {
                let card = document.createElement('div');
                card.className = 'card';
                card.innerHTML = `<a href="${item.link}">
                    <div class="lazyImageBox" style="height: ${item.height}px;">
                        <img src="" alt="" lazy-image="${item.pic}">
                    </div>
                    <p>${item.title}</p>
                </a>`;
                columns[index].appendChild(card);
            });
        }
    };
 
    // 图片延迟加载
    const singlelazy = lazyImageBox => {
      
        let imgObj = lazyImageBox.querySelector('img'),
            trueImg = imgObj.getAttribute('lazy-image'); 
        imgObj.src =  trueImg; 
        imgObj.onload = () => {
            imgObj.style.opacity = 1;
        }
    }   

    const lazyAllImage = () => { 
         
        // 创建监听器 
        let ob = new IntersectionObserver(changes =>{ 
            // 循环每一个 盒子的item
            changes.forEach(item=>{
                let {isIntersecting,target} = item;
                // 显示完成就加载图片
                if(isIntersecting){
                    // 加载图片
                    singlelazy(target);
                    // 监听完成以后 移除监听
                    ob.unobserve(target);
                }
            })
        },{
            threshold:[1]
        });

        // 监听所有的图片的占位盒子
        let lazyImageBoxs = container.querySelectorAll('.lazyImageBox');
      
        [].forEach.call(lazyImageBoxs,lazyImageBox=>{ 
            ob.observe(lazyImageBox);
        })
    }

    return {
        async init() {
            let data = await queryData();
            bindHTML(data);
            //  图片延迟加载
            lazyAllImage();
        }
    };
 
})();
waterfallModule.init();

    </script>
</body>

</html>