index.html

<! DOCTYPEhtml>
<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>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        html.body {
            width: 100%;
            height: 100%;
        }

        .box {
            width: 70%;
            display: flex;
            justify-content: space-between;
            margin: auto;
        }

        .column {
            width: 230px;
        }

        .card {
            width: 220px;
            margin: 10px;
        }
    </style>
</head>

<body>
    <! -- Waterfall flow -->
    <div class="box">
        <div class="column">
            <div class="card">
                <! -- <img style="width: 200px; height: 100px;" src="./images/1.jpg" alt=""> -->
            </div>
        </div>
        <div class="column">
          
        </div>
        <div class="column">
           
        </div>
        <div class="column">
            
        </div>
    </div>
    <script src="./node_modules/axios/dist/axios.js"></script>
    <script src="1.js"></script>
</body>

</html>
Copy the code

1.js

// Delay request data
const getData = function getData() {
    return new Promise((resolve, reject) = > {
        axios.get('./data.json').then((res) = > {
            setTimeout(() = > {
                resolve(res)
            }, 1000)})})}const state = function state() {
    this.state = {};
}
let vue = new state();

getData().then((res) = > {
    vue.state.datalist = res.data;
    / / initialization
    initdata();
    / / lazy loading
    lazyload();
})

/ / initialization
const initdata = function initdata() {
    let { datalist } = vue.state;
    // Set the height according to the scale
    datalist.map((item, i) = > {
        let { height, width } = item,
            w = 230,
            h = (w * height) / width;
        item.w = 230 + 'px';
        item.h = h + 'px';
    })

    for (let index = 0; index < datalist.length; index = index + 4) {
        let group = datalist.slice(index,index+4),
            columns = Array.from(document.getElementsByClassName('column'));
        // Sort from smallest to largest
        group.sort((a,b) = > {
            return a.h - b.h
        })
        // Container sort
        columns.sort((a,b) = > {
            return b.offsetHeight - a.offsetHeight
        })
        group.forEach((item,i) = > {
            let cart = document.createElement('div');
            cart.className = 'card';
            cart.style.height = `${item.h}`;
            cart.innerHTML = cart.innerHTML + `
                <img style="width: ${item.w}; height:${item.h};" src=''  img-data='${item.pic}'></img>
            `columns[i].append(cart); }}})// Images load lazily
const lazyload = function lazyload(){
    let imgs = Array.from(document.getElementsByTagName('img')),
        config = {
            threshold: [1]};const Callback = function Callback(e){
        e = Array.from(e);
        e.forEach((item,i) = > {
            let {isIntersecting,target} = item;
            if(isIntersecting){
                // Display the image
                target['src'] = target.getAttribute("img-data"); imgsob.unobserve(target); }})}// Bind listener events
    let imgsob = new IntersectionObserver(Callback,config);
    imgs.forEach((item,i) = >{ imgsob.observe(item); })}Copy the code

IntersectionObserver

Developer.mozilla.org/zh-CN/docs/…

{threshold:[0,1]} @3 */ config :{threshold:[0,1] //
let Callback = function Callback(e){
    e = Array.from(e);
    e.forEach((item,i) = > {
        let {isIntersecting,target} = item;
        if(isIntersecting){
            // Display the image
            target['src'] = target.getAttribute("img-data");
            / / cancelimgsob.unobserve(target); }})}let ob = new IntersectionObserver(Callback,config);
ob.observe(target);
Copy the code