使用Macy.js实现瀑布流式布局以及上滑加载更多

<!doctype html>
<html lang="zh">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no, viewport-fit=cover">
<meta name="format-detection" content="telephone=no">
<meta http-equiv="X-UA-Compatible" content="IE=Edge, chrome=1">
<title>使用Macy.js实现瀑布流式布局以及上滑加载更多</title>
<style type="text/css">
*{margin:0;padding:0;font-size:4vw;line-height:1;}
ul{clear:both;display:block;margin:3vw 0 0 3vw;width:94vw;}
ul li{position:relative;list-style:none;}
ul li .title,ul li img{clear:both;display:block;width:100%;height:auto;}
ul li .title{padding:1.5vw 0;background:#07c160;color:#fff;text-align:center;}
.completed,.loading{clear:both;display:none;margin:3vw 0 6vw;text-align:center;}
</style>
</head>
<body>
<ul id="macy-container">
    <!-- 格式:<li><img src="图片URL"><span class="title">图片名称</span></li> -->
</ul>
<div class="loading">—— 正在加载 ——</div>
<div class="completed">—— 没有了 ——</div>
<script type="text/javascript" src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<script type="text/javascript" src="./macy.js"></script>
<script type="text/javascript">
var isLoading = false; // 是否正在加载数据
var isCompleted = false; // 是否已加载全部数据
var page = 1; // 当前是第几页
var offset = parseInt($(document).height() * 0.2);

// 初始化瀑布流插件
var macyInstance = Macy({
    container: '#macy-container', // 容器ID
    columns: 2, // 显示多少列
    margin: {
        x: parseInt(window.screen.width * 0.03), // 左右间距
        y: parseInt(window.screen.width * 0.03), // 上下间距
    },
    waitForImages: false, // 若为true,则等待页面上的所有图像加载后再运行。默认为false,它将在每次加载图像时运行
    mobileFirst: true, // 是否移动优先,默认为false
    trueOrder: false, // 设置为false将优先均衡每列的高度,而不是项目本身的顺序,默认为false
    breakAt: {
        // 当屏幕宽度小于等于720px时改为使用下面的配置
        720: {
            columns: 3, // 显示多少列
            margin: {
                x: parseInt(window.screen.width * 0.03), // 左右间距
                y: parseInt(window.screen.width * 0.03), // 上下间距
            },
        },
        // 当屏幕宽度小于等于1080px时改为使用下面的配置
        1080: {
            columns: 4, // 显示多少列
            margin: {
                x: parseInt(window.screen.width * 0.03), // 左右间距
                y: parseInt(window.screen.width * 0.03), // 上下间距
            },
        },
        // 当屏幕宽度小于等于1440px时改为使用下面的配置
        1440: {
            columns: 5, // 显示多少列
            margin: {
                x: parseInt(window.screen.width * 0.03), // 左右间距
                y: parseInt(window.screen.width * 0.03), // 上下间距
            },
        },
    },
});

/**
 * 获得demo图片
 *
 * @param int index 第几条记录
 * @return string 图片URL
 */
function getDemoImg(index) {
    var img = [
        'https://gd-hbimg.huaban.com/fb6baf4644b6dee51a99914972e60072d7c2efd622cfd-hCOVkZ_fw1200webp',
        'https://gd-hbimg.huaban.com/faf5f9847aeda79adc2e0023bfb9bb56847e95c4ad993-iQnMNs_fw1200webp',
        'https://gd-hbimg.huaban.com/f454d30da8df810bf3e5ac750d271cd80679c1cf4094d-5cfIx7_fw1200webp',
        'https://gd-hbimg.huaban.com/e8ccedf822e02813f96e55e64ab21ce062f7c1a6b2cbb-TKFlvz_fw1200webp',
        'https://gd-hbimg.huaban.com/e6d863ca202045e1949396c62811efc7a666a829760a9-XhMA6g_fw1200webp',
        'https://gd-hbimg.huaban.com/e165cef185873d382bc2b0c6ff83180f874f29b419dfd-qoMZvN_fw1200webp',
        'https://gd-hbimg.huaban.com/d9da0c7b8e89c263c16e95261771f667e2ae05e6bee97-oTHrOd_fw1200webp',
        'https://gd-hbimg.huaban.com/d8621039f5b9c0abfc1edca977ba9991b4bb66fd32e59-rygbjl_fw1200webp',
        'https://gd-hbimg.huaban.com/d17fb71cbd5728d3da366e54fa1bbc99cdf9d1c04ce75-8Fx4mV_fw1200webp',
        'https://gd-hbimg.huaban.com/c503b0300085016d701b1bb4aa384876cc28f46c2ef9a-WP6vjA_fw1200webp',
        'https://gd-hbimg.huaban.com/bf005a6afc22c7ad7f3483f5842a604a7223dbde5604b-OM7WRK_fw1200webp',
        'https://gd-hbimg.huaban.com/b6d025ac4ef7d6ab25230c1595508ca2abdcfe6175d9d-mFOqh9_fw1200webp',
        'https://gd-hbimg.huaban.com/b6a81e261021647b765143196c9d249911a8977258def-Qml4SD_fw1200webp',
        'https://gd-hbimg.huaban.com/b04e2b672d4c1aa2d70aa3d164f21c14a0b59edb4cba5-nQIQzL_fw1200webp',
        'https://gd-hbimg.huaban.com/ade0c6e1d1814c8525d9f2e06fb7aee767b4f80b61b03-mfuEcu_fw1200webp',
        'https://gd-hbimg.huaban.com/ac6686694f7b3166c26128adec56f06962d0f82916eee-OsvCyu_fw1200webp',
        'https://gd-hbimg.huaban.com/869d7da6e48dfcbdfd68322f9e6121781ae0a07b12440-ctm4Sa_fw1200webp',
        'https://gd-hbimg.huaban.com/75449290d5a19312e33f607c3832d4f66e63c9d2674d8-CMuBRU_fw1200webp',
        'https://gd-hbimg.huaban.com/6e806e86f400550af062a0a550dabc1c1fa77e3121e9a-QO5bAa_fw1200webp',
        'https://gd-hbimg.huaban.com/6a64eb0bd51f7a5e1e27d080f89b991f97577e5e4baad-Nr8gRw_fw1200webp',
        'https://gd-hbimg.huaban.com/5d371141f219c57752f552586a11aa81fe545bad3e8c0-eQe2CV_fw1200webp',
        'https://gd-hbimg.huaban.com/58ff0902c7928d3be3a9327c4f984a419a4579ff1af7d-gcYPbj_fw1200webp',
        'https://gd-hbimg.huaban.com/43dd4d78b8bf599dc015022cfc180c7066c37caaaf7df-Mp9QaO_fw1200webp',
        'https://gd-hbimg.huaban.com/43a4ba5ae2bc8d454f94de14d8e825cd20fdfb4adf8b8-5ReQvh_fw1200webp',
        'https://gd-hbimg.huaban.com/42b80c9cf61edaa6d73b91faee7302ab0b059f8c1b8a3-ZGvvD4_fw1200webp',
        'https://gd-hbimg.huaban.com/3e8b142316fa139244c592d3582dab216d243d882734c-94KnbB_fw1200webp',
        'https://gd-hbimg.huaban.com/1e589bbbc0a18988d6ad6323767b1beba5d26a68ae077-0wUf0V_fw1200webp',
        'https://gd-hbimg.huaban.com/1a86098a1b012bf28b88843fff46441c56c8b0b4a47c3-uXHCKe_fw1200webp',
        'https://gd-hbimg.huaban.com/0f5627cb52d09630555c6984fcdbba413bc19ed3780aa-GuY8C8_fw1200webp',
        'https://gd-hbimg.huaban.com/0baaa30f2c64c01aa7a9282c9aba829b7eaf35c24332a-tzFLxo_fw1200webp',
    ];

    return img[(index - 1) % img.length];
}

/**
 * 监听滑动事件(实现上滑加载更多)
 *
 * @return void
 */
function addScrollEventListener() {
    $(window).on('scroll', function() {
        // 同一时间只能执行一个加载数据操作
        if (isLoading) {
            return;
        }

        // 避免已加载全部数据仍继续加载
        if (isCompleted) {
            removeScrollEventListener();
            return;
        }

        var scrollTop = $(this).scrollTop(); // 滚动条距离顶部的高度
        var scrollHeight = $(document).height(); // 当前页面的总高度
        var clientHeight = $(this).height(); // 当前可视的页面高度

        // 距离顶部+当前高度>=文档总高度-offset,代表滑动到底部
        // 注:减去offset可以实现未到底就请求数据,而不是彻底到底部才请求,从而使体验更流畅
        if (scrollTop + clientHeight >= scrollHeight - offset) {
            // 加载下一页的数据
            page++;
            console.log('即将加载第' + page + '页的数据');
            loadData(page);
        }
    });
}

/**
 * 取消监听滑动事件
 *
 * @return void
 */
function removeScrollEventListener() {
    $(window).off('scroll');
}

/**
 * 显示提示
 *
 * @param string type 提示类型,可选值:loading|completed|none
 * @return void
 */
function displayTips(type) {
    if (type == 'loading') {
        $('.completed').hide();
        $('.loading').show();
    } else if (type == 'completed') {
        $('.loading').hide();
        $('.completed').show();
    } else {
        $('.loading').hide();
        $('.completed').hide();
    }
}

/**
 * 加载数据
 *
 * @param int page 要加载第几页的数据
 * @return void
 */
function loadData(page) {
    // 同一时间只能执行一个加载数据操作,并避免已加载全部数据仍继续加载
    if (isLoading || isCompleted) {
        return;
    }

    isLoading = true; // 标记正在加载数据
    displayTips('loading');

    // 延迟执行(模拟AJAX耗时请求数据)
    setTimeout(function() {
        var html = ''
        for (var i = 0; i < 10; i++) {
            var index = (page - 1) * 10 + i + 1;
            html += '<li><img src="' + getDemoImg(index) + '"><span class="title">第' + index + '条记录</span></li>';
        }
        $('#macy-container').append(html);

        // 由于追加了数据,需要重新计算瀑布流
        macyInstance.runOnImageLoad(function() {
            macyInstance.recalculate(true);
        }, true);

        isLoading = false; // 标记本次加载数据操作完成
        displayTips('none');

        // 最多加载10页(即已加载全部数据)
        if (page >= 10) {
            isCompleted = true; // 标记已加载全部数据
            displayTips('completed');
            removeScrollEventListener() // 由于已加载全部数据,不需要再监听滚动事件
        }

    }, 500);
}

$(function() {
    loadData(page); // 进入页面后先加载第1页的数据(page的初始值为1)
    addScrollEventListener(); // 监听滑动事件(实现上滑加载更多)
});
</script>
</body>
</html>

Copyright © 2024 码农人生. All Rights Reserved