首页 > 编程语言 >瀑布流布局 不到30行代码实现(JavaScript + absolute)支持懒加载

瀑布流布局 不到30行代码实现(JavaScript + absolute)支持懒加载

时间:2022-12-07 16:35:08浏览次数:38  
标签:布局 style JavaScript dom 30 height width let absolute

最后效果


@

目录


前言

瀑布流 网站页面布局
瀑布流,又称瀑布流式布局。是比较流行的一种网站页面布局,视觉表现为参差不齐的多栏布局,随着页面滚动条向下滚动,这种布局还会不断加载数据块并附加至当前尾部。最早采用此布局的网站是Pinterest,逐渐在国内流行开来。国内大多数清新站基本为这类风格。

简单来说: 瀑布流式布局其实式一种网页的样式效果,简单来说就是一种单个宽度固定单个图片高度根据内容适应多个块自动换行,但是紧凑拼在一起的效果。既可以使用纯css快速的达到这种样式效果,也可以通过JavaScript辅助,实现更丰富合理的效果


一、使用css实现瀑布流布局

1.flex 布局

使用flex布局,将容器设置为flex布局,设置主轴方向为列方向,允许换行,容器设定固定高度(这样才会自动换列),然后子元素设置宽度为对应比例,在某一列填满时会自动往下一列填充,并且每一列元素填充十分紧凑****使用flex布局实现的基础的瀑布式布局
优化方向:使用order属性优化排序方向

2.column-count 多栏布局

类似的还有使用 多栏布局,使用column-count属性,设置多栏布局,效果跟flex布局类似,排列方向也是从上到下,从左到右

3.grid 网格布局

二、结合JavaScript的瀑布流布局实现

1.推荐原因

瀑布流式布局经常被使用在图片的展示页面,大量的图片资源加载,如果只用css样式的话必须一次性加载所有图片,我们期待的是瀑布流懒加载结合在一起,在滚动视图的同时,不断加载下面的内容

2.实现步骤

如果需要结果的话可以直接跳到文章最后

a.初步实现:结合JavaScript实现瀑布流

原理:

  1. 子元素绝对定位
  2. 通过javascript设置偏移量

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="./index.css">
</head>

<body>
    <div id="app"></div>
    <!-- <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script> -->
    <!-- <script src="./src/vue.min.js"></script> -->
    <script src="./util.js"></script>
    <script src="./index.js"></script>
</body>

</html>

css 代码:

html {
    background-color: black;
}

#app {
    position: relative;
    width: 100%;
    margin: auto;
}

.item {
    position: absolute;
    border-radius: 20px;
    border: 10px solid black;
    box-sizing: border-box;
    text-align: center;
    color: white;
}

utils.js 代码:

const randomImgSize = [	// 这里是模拟各种尺寸的图片
    {
        width:1920,
        height:1080
    },{
        width:640,
        height:720
    },{
        width:720,
        height:680
    },{
        width:720,
        height:1920
    },{
        width:900,
        height:600
    },{
        width:400,
        height:300
    },{
        width:2048,
        height:1920
    },{
        width:700,
        height:900
    },{
        width:1600,
        height:900
    },{
        width:200,
        height:200
    }
]

function randomColor(){
    let r = Math.floor(Math.random() * 255)
    let g = Math.floor(Math.random() * 255)
    let b = Math.floor(Math.random() * 255)
    return `rgb(${r},${g},${b})`
}

index.js 代码

   		// 创建元素函数
       function generateBlock(size,color){
           let dom = document.createElement('div')
           dom.setAttribute('class','item')
           dom.style.width = '240px'			// 这里默认写死宽度,后面会优化
           dom.style.height = `${240/size.width * size.height}px`		// 由于这里没有图片资源,高度模拟计算
           // 图片资源的话不需要直接width:100% 高度会自适应
           dom.style.backgroundColor = color
           // 颜色也是随机生成而已
           document.getElementById('app').appendChild(dom)
           return dom
       }
       // 元素统计数组
       let domArr = []
       // 元素高度数组
       let heightArr = new Array(4)	// 创建对应列数,存储每一列高度,用来设置偏移量
       heightArr.fill(0)
       // 常规不考虑高度不整齐逻辑
       randomImgSize.forEach(ele=>{
           let dom =generateBlock(ele,randomColor())
           domArr.push(dom)		// 通过transform 属性可以一次设置,不用设置left和top,不过也一样
           dom.style.transform =  `translate(${(domArr.length-1)%4 * 100}%, ${heightArr[domArr.length%4]}px)`
           heightArr[domArr.length%4] += dom.offsetHeight
       })

实现内容:

  1. 初步实现瀑布流布局,正确计算每一个块(图片)的正确位置

  2. 每个块只是死板的按照从左到右,从上到下的顺序,可以优化:下一个块生成位置为当前列最低高度位置,自动填补进去

  3. 没有实现懒加载

    基础的js结合实现瀑布流

b.稍微优化:每次自动填补到高度最低

index.js

        // 创建元素函数
        function generateBlock(size,color){
            let dom = document.createElement('div')
            dom.setAttribute('class','item')
            dom.style.width = '240px'
            dom.style.height = `${240/size.width * size.height}px`
            dom.style.backgroundColor = color
            document.getElementById('app').appendChild(dom)
            return dom
        }
        // 元素统计数组
        // let domArr = []
        // 元素高度数组
        let heightArr = new Array(4)
        heightArr.fill(0)
        // 常规不考虑高度不整齐逻辑
        // randomImgSize.forEach(ele=>{
        //     let dom =generateBlock(ele,randomColor())
        //     domArr.push(dom)
        //     dom.style.transform =  `translate(${(domArr.length-1)%4 * 100}%, ${heightArr[domArr.length%4]}px)`
        //     heightArr[domArr.length%4] += dom.offsetHeight
        // })

        // 考虑高度不整齐逻辑
        randomImgSize.forEach(ele=>{
            let dom =generateBlock(ele,randomColor())
            let minHeight=  Math.min(...heightArr)
            let minHeightIndex = heightArr.indexOf(minHeight)
            dom.style.transform =  `translate(${minHeightIndex * 100}%, ${minHeight}px)`
            heightArr[minHeightIndex] += dom.offsetHeight
        })

实现效果:
优化高度填充对比

  1. 可以看到效果对比之前还是要好很多,不会出现极高或者极低的情况,而且代码还简化了,不需要数组来缓存元素,直接通过长度为4 的高度数组,查询应该插入到哪个列
  2. 对应列的偏移量:x为 100% * 对应列下标,y为对应列下标高度
  3. 但是宽度还是写死的,而且没有实现懒加载

b.最终结果 (不到三十行代码)支持懒加载

index.js

		// 响应式
        const columns = 3
        let tempArr = new Array(columns)  // 创建数组用来缓存高度
        tempArr.fill(0)
        function create(){
            let observer = new IntersectionObserver(callback)
            function callback(entries){
                if(entries[0].isIntersecting){  // 如果已进入视图,停止监听,并且生成新的元素
                    observer.unobserve(dom)
                    create()
                }
            }
            function generateBlock(size,color){
                let dom = document.createElement('div')
                dom.setAttribute('class','item')
                dom.style.width = `${Math.floor(100/columns)}%`         // 宽度为百分比
                dom.style.height = `${300/size.width * size.height}px`  // 300为默认高度
                dom.style.backgroundColor = color
                document.getElementById('app').appendChild(dom)
                return dom
            }
            let donSizeIndex = Math.floor(Math.random() * randomImgSize.length) // 随机生成大小(模拟不同尺寸的图片)
            let dom =generateBlock(randomImgSize[donSizeIndex],randomColor())   // 生成随机块
            let minHeight=  Math.min(...tempArr)                                // 找到对应列最小高度的值
            let minHeightIndex = tempArr.indexOf(minHeight)                     // 找到对应列最小高度的下标
            dom.style.transform =  `translate(${minHeightIndex*100}%, ${minHeight}px)`      // 根据下标进行变换,变换宽度为偏移多少个下标,上下为该下标所有高度
            tempArr[minHeightIndex] += dom.offsetHeight         // 对应下标增加高度
            observer.observe(dom)   // 观察该元素用作懒加载
        }
        create()

实现效果:
在这里插入图片描述
实现比较简单其实,主要是javascript操作样式,设置对应transform属性,通过全局设置一个高度数组,每次添加元素时获取每一列高度,选取最小高度列,将元素偏移量设置正常,并且通过intersectionObserver对象,监听与视口交叉事件,每次触发时,生成新的元素

同理可以拓展到加载图片..等等


总结

以上就是今天要的结合JavaScript实现图片瀑布流式布局+懒加载的实现过程,本文仅仅简单介绍了瀑布流布局相关设计思路,如果需要增加其他功能可以在该demo的基础上进行修改

觉得有帮助的话,点赞关注支持一下,b站前端同名分享号:猿油站

标签:布局,style,JavaScript,dom,30,height,width,let,absolute
From: https://www.cnblogs.com/zm-blogs/p/16963490.html

相关文章

  • Javascript-极速入门指南-3-jQuery使用教程
    内容概要jQuery类库类库jQuery简介jQuery的宗旨:Writeless,domore写的更少做的更多jQuery的特点为: 1.加载速度快 2.选择器更多更好用 3.一行代码走天下......
  • 现代javascript教程 数组
    array字面量或者构造函数声明数组newArray(100),长度100的空获取数组长度,是一个属性,arr.length获得元素,通过索引值,arr[0]修改数组,arr[0]=0用alert方法打印数组,会......
  • JavaScript Promises, async/await
    newPromise()的时候,传一个executor给Promise.letpromise=newPromise(function(resolve,reject){//thisfunctionwillexecutesimmediately})这个函数......
  • 12306抢票神器,助力远在他乡想回家的你
    目录​​背景​​​​修改配置文件:TickerConfig​​​​开始运行:pythonrun.pyr​​​​分析源码​​​​拭目以待 ​​背景每逢佳节倍思亲,年关将近,思乡的情绪是不是愈发......
  • JavaScript中 FileReader 对象详解
    1.概念:FileReader对象允许Web应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区即buffer)的内容,使用File或Blob对象指定要读取的文件或数据。2.属性:FileR......
  • SBT30100VFCT-ASEMI低压降肖特基SBT30100VFCT
    编辑:llSBT30100VFCT-ASEMI低压降肖特基SBT30100VFCT型号:SBT30100VFCT品牌:ASEMI封装:TO-220F正向电流:30A反向电压:100V引线数量:3芯片个数:2芯片尺寸:94MIL漏电流:20ua......
  • javaScript_01_按照key排序
     javaScript_01_按照key排序前言Object.keys()与Objetc.values()实现按key排序前言最近做一个小程序项目需要用到腾讯地图的api,在计算sig的时候需要将参数按照......
  • javascript - 判定输入浮点数是否合法
    方法借鉴其他作者,我进行了错误汇总并完善,记录以备后用;首先建立一个功能函数,用于检查输入浮点数是否合法:functionCheckValueError(theFloat){}//返回True表示错误,返回F......
  • JavaScript入门⑦-DOM操作大全
    JavaScript入门系列目录JavaScript入门①-基础知识筑基JavaScript入门②-函数(1)基础{浅出}JavaScript入门③-函数(2)原理{深入}执行上下文JavaScript入门④-万物皆......
  • DCDC直流隔离升压12V24V48V转600V800V1100V2500V3000V高压稳压输出电源模块
    特点●效率高达 80%●2*2英寸标准封装●单双电压输出●价格低●大于600V高压,稳压输出●工作温度:-40℃~+85℃●阻燃封装,满足UL94-V0要求●温度特性好●可直接......