瀑布流布局

内容

多个等宽的图片进行穿插排序成六列,并且在目前显示的最后一张图片显示之后,再进行下拉时能够在进行加载其他图片,每次下拉显示20-30张图片。

实验原理

计算每个图片,并利用定位使下面的图片插入最小高度的图片下面
监听窗口与滚动条高度变化,利用懒加载使其不断地展示图片

html

<!DOCTYPE html>
<html lang="zh-CN">
<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>demo12</title>
    <link rel="stylesheet" href="./css/demo12.css">
</head>
<body>
    <div class="waterfall" id="container"></div>
    <script src="./js/demo12.js"></script>
</body>
</html>

css

<style>
* {
    margin: 0;
    padding: 0;
}
.waterfall {
    width: 100%;
    display: flex;
    flex-wrap: wrap;
    position: relative;
}
.item {
    width: 240px;
    background-color: #ccc;
    position: absolute;
    vertical-align: top;
}
</style>

js

<script>
let imgs1=[
    {path:'https://ts3.cn.mm.bing.net/th?id=OIP-C.Rq5h9rKa8uBoUxtGTCCVRQHaKd&w=210&h=297&c=8&rs=1&qlt=90&o=6&dpr=2&pid=3.1&rm=2', width:200, height:284},
    {path:'https://ts3.cn.mm.bing.net/th?id=OIP-C.atTl-J5TF3GE5FWfRtTIygHaJ8&w=215&h=289&c=8&rs=1&qlt=90&o=6&dpr=2&pid=3.1&rm=2', width:200, height:270},
    {path:'https://ts3.cn.mm.bing.net/th?id=OIP-C.QFdwl07_aviM1ch2KpyyFgHaEo&w=316&h=197&c=8&rs=1&qlt=90&o=6&dpr=2&pid=3.1&rm=2', width:200, height:125},
    {path:'https://ts1.cn.mm.bing.net/th?id=OIP-C.nfC2tVNM9TgwQ5QuqECd6wHaFj&w=288&h=216&c=8&rs=1&qlt=90&o=6&dpr=2&pid=3.1&rm=2', width:200, height:150},
    {path:'https://ts2.cn.mm.bing.net/th?id=OIP-C.pgBMw_lMOYSOCZIDQ896NAHaLF&w=204&h=305&c=8&rs=1&qlt=90&o=6&dpr=2&pid=3.1&rm=2', width:200, height:300},
    {path:'https://ts1.cn.mm.bing.net/th?id=OIP-C.1-wFaNNsH_OCBFvGCfloWgHaJ4&w=216&h=288&c=8&rs=1&qlt=90&o=6&dpr=2&pid=3.1&rm=2', width:200, height:267},
    {path:'https://ts1.cn.mm.bing.net/th?id=OIP-C.ebfLNO07a781ncjScj7u6wHaLs&w=198&h=314&c=8&rs=1&qlt=90&o=6&dpr=2&pid=3.1&rm=2', width:200, height:318},
    {path:'https://tse4-mm.cn.bing.net/th/id/OIP-C.uNxOyVhFHzUweInZEahy-QHaFj?w=231&h=180&c=7&r=0&o=5&dpr=2&pid=1.7',width:200,height:156},
    {path:'https://tse2-mm.cn.bing.net/th/id/OIP-C.XXrW8aTA10CkicQuGceNjgHaE7?w=263&h=180&c=7&r=0&o=5&dpr=2&pid=1.7',width:200,height:137},
    {path:'https://tse2-mm.cn.bing.net/th/id/OIP-C.mQBvGOCQDvosB6SXXIljfwHaE0?w=304&h=197&c=7&r=0&o=5&dpr=2&pid=1.7',width:200,height:130},
    {path:'https://tse3-mm.cn.bing.net/th/id/OIP-C.pVMgoYOCp9YQ3BnH1AhuggHaE7?w=296&h=197&c=7&r=0&o=5&dpr=2&pid=1.7',width:200,height:135},
    {path:'https://tse1-mm.cn.bing.net/th/id/OIP-C.YTQX73HsbhdnueV0dzYPpAHaEW?w=314&h=184&c=7&r=0&o=5&dpr=2&pid=1.7',width:200,height:120},
    {path:'https://tse4-mm.cn.bing.net/th/id/OIP-C.ivx7EPOK5Y3d4J_Z2OlydgHaE7?w=260&h=180&c=7&r=0&o=5&dpr=2&pid=1.7',width:200,height:140},
    {path:'https://tse1-mm.cn.bing.net/th/id/OIP-C.h02sipGoXVxrZGX27e2hoQHaE3?w=234&h=180&c=7&r=0&o=5&dpr=2&pid=1.7',width:200,height:154},
    {path:'https://tse4-mm.cn.bing.net/th/id/OIP-C.4eNrKDHGVHrdX45iP22r6AHaEK?w=283&h=180&c=7&r=0&o=5&dpr=2&pid=1.7',width:200,height:125},
    {path:'https://tse1-mm.cn.bing.net/th/id/OIP-C.hNu5gDicpIJY8yCE-hM2EwHaNK?w=115&h=184&c=7&r=0&o=5&dpr=2&pid=1.7',width:200,height:320},
    {path:'https://tse3-mm.cn.bing.net/th/id/OIP-C.MfAU3E769jbMcGoA-WrbHwHaEK?w=294&h=180&c=7&r=0&o=5&dpr=2&pid=1.7',width:200,height:123},
    {path:'https://tse2-mm.cn.bing.net/th/id/OIP-C.lE3uaNuJUHCapn4EnEPFbgHaE8?w=267&h=180&c=7&r=0&o=5&dpr=2&pid=1.7',width:200,height:135},
    {path:'https://tse4-mm.cn.bing.net/th/id/OIP-C.OjgEXcW8FmAnIoO0bwTldwHaEK?w=297&h=183&c=7&r=0&o=5&dpr=2&pid=1.7',width:200,height:124},
    {path:'https://tse2-mm.cn.bing.net/th/id/OIP-C.y8bP8drHeoVXB53aMIQhIQAAAA?w=189&h=190&c=7&r=0&o=5&dpr=2&pid=1.7',width:200,height:202},
]
// 获取容器元素
let container = document.getElementById('container')
// 造图片
function createImg(imgItem) {
    let img = new Image()
    img.setAttribute('data-src',imgItem.path) 
    img.height = imgItem.height
    img.className = 'item'
    img.src = ''
    img.alt = 'loading...'
    return img
}
// 图片标签上树
function loadImg(imgArr) {
    let nodeImgArr = []
    for(let i = 0; i < imgArr.length; i++) {
        container.appendChild(createImg(imgArr[i]))
    }
    // 上树完成之后  就布局
    waterfall()
}
 // 瀑布流布局
function waterfall() {
    // 得到所有图片和定义的间距
    let items =  document.getElementsByClassName('item')
    let padNum = 10
    // 确定有多少列
    let itemWidth =items[0].offsetWidth
    let columns =6
    // 定义一个映射高度数组 * 核心
    let heightArr = []
    for (var i = 0; i < items.length; i++) {
        if (i < columns) {
            // 表示是第一行
            items[i].style.top = 0
            items[i].style.left = i * (itemWidth + padNum) + 'px'
            items[i].src = items[i].dataset['src']
            heightArr.push(items[i].offsetHeight)
            // 更新高度
        }else{
            // 表示第二行开始了
            // 要得到最小高度  以及最小高度所在的索引
            let minHeight = Math.min(...heightArr)
            let heightIdx = heightArr.findIndex((item, index) => item === minHeight)
            // items[i]是否在可视区域
            items[i].style.top = minHeight + padNum + 'px'
            items[i].style.left = heightIdx * (itemWidth + padNum) + 'px'
            // 判断是否在视口内
            if(isInViewPort(items[i])) {
                items[i].src = items[i].dataset['src']
            }
            // 更新高度
            heightArr[heightIdx] += (items[i].clientHeight + padNum)
        }
    }
}
window.onload=function(){
    // 当这个图片数组已经渲染过了之后   就不需要再加载了
    loadImg(imgs1)
}
 // 监听尺寸变化
window.onresize = function() {
    waterfall()
    if(touchBottom()) {
        loadImg(imgs1)
    }
}
window.onscroll = function(){
    waterfall()
    if(touchBottom()) {
        loadImg(imgs1)
    }
} 
 // 获取视口宽度 方法 -- 兼容
function getClient() {
    return {
        width: window.innerWidth || document.documentElement.clientHeight || document.body.clientHeight,
        height: window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight
    }
}
 // 判断元素是否在视窗内
function isInViewPort(element){
    const viewWidth = window.innerWidth || document.documentElement.clientWidth;
    const viewHeight = window.innerHeight || document.documentElement.clientHeight;
    const {
        top,
        right,
        bottom,
        left,
    }=element.getBoundingClientRect();
    return(
        // top >= 0 &&
        // left >= 0 &&
        // right <= viewWidth &&
        // bottom <= viewHeight
        top >= 0 && (top + 30) <= viewHeight
    );
}
 // 获取滚动值  方法  -- 兼容
function getScrollTop() {
    return window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
}
 // 判断页面是否触底  //页面卷去高度 + 浏览器可视窗口的高度 >= 整个页面的高度
function touchBottom() {
    return getScrollTop() + getClient().height + 10 >= document.body.scrollHeight
}
</script>

样式

瀑布流布局

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值