瀑布流布局
文章目录
- 瀑布流布局
- 前言
- 1. 背景
- 2. 点⬇️🔗去体验
- 效果如下图所示:
- 一、初版waterfall布局和问题暴露?
- 1.效果图如下:
- 2.暴露问题如下图所示:
- 第一张问题图:
- 第二张问题图:
- 3.HTML代码如下:
- 4.JS代码如下:
- 二、初版waterfall布局问题的排查和解决
- 1.排查问题
- 2.解决问题
- 第一种解决方法:设置块级作用域(行不通)
- 代码修改如下图所示:
- 修改后如下图所示(依然有插入顺序问题):
- 第二种解决方法:改变每一列高度的获取方式(成功了)
- 代码修改如下图所示:
- 图1如下(waterfall布局正常渲染)
- 图2如下(waterfall布局正常渲染)
- 3.完整代码 👇方🔗获取
- 总结(完整代码文件点击下方🔗,晚些更新进阶版)
前言
起初我看网上有很多处理waterfall的处理方案,但是我都没去仔细的去阅读📖
(主要是我相信我自己也可以做出来,事实如此我做出来了)。
后面也可能会对当前的版本进行二次优化
。学习一下别人的优秀想法💡。
⚠️⚠️⚠️:
提供这个容易理解的版本,后续会发布精简版本或者附加功能版本
(功能包括:图片懒加载、触底加载数据、展示的虚拟列表优化、响应式等功能。
1. 背景
为什么突然要去尝试写一个瀑布流布局?
首先
,很早之前我就看到【小红书】主站就采用了这种 waterfall布局进行的展示。
其次
,负责这块内容的同学是我前一个组的同事(哈哈哈哈哈😂)。
然后
,我就大概去调试了一下【小红书】主站上的瀑布流,第一感觉:那是相当的丝滑,很牛逼,很高大上;
最后
,waterfall布局也可以搭配很多其他的功能,例如:触底加载,图片懒加载,Dom结构懒加载等。
- 【小红书】主战的waterfall布局他使用的是
绝对定位 + Css
的样式进行开发的。这种waterfall布局的优势
:就是可以避免当前的网页一直被重绘。古德古德!!💪💪
2. 点⬇️🔗去体验
waterfall体验🤌
效果如下图所示:
一、初版waterfall布局和问题暴露?
1.效果图如下:
2.暴露问题如下图所示:
- 在首页中也可以看到错误的顺序。
- 初版构思的waterfall布局,并
没有按照最小的长度的盒子的顺序插入
,而是一个比较乱的状态
。
第一张问题图:
第二张问题图:
3.HTML代码如下:
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>waterFall</title><style>#water-fall-main {display: flex;gap: 8px;position: relative;width: 100%;justify-content: space-around;}.water-fall-columns {width: 250px;/* border: 1px solid red; */display: flex;flex-direction: column;align-items: center;gap: 8px;}.water-fall-item {width: 232px;}</style>
</head><body><div id="water-fall-main"></div>
</body></html>
4.JS代码如下:
//获取瀑布流的主元素const waterFallMain = document.querySelector('#water-fall-main')const createDomContainer = []const setCurrentPageColumns = (width) => {const currentOutterWidth = widthreturn Math.floor(currentOutterWidth / 250)}const setRangeWidth = () => {const height = Math.floor(Math.random() * 450)return height > 225 ? height : 200}const setRandomWaterItemNumber = () => {const number = Math.floor(Math.random() * 100)return number > 25 ? number : 50}const setRandomColor = () => {const colorArr = ['#f39999', '#7f5555', '#94eca1', '#dd9757', '#98f2b0', '#75e1ef', '#5e47e8', '#c652ef',]return colorArr[Math.floor(Math.random() * colorArr.length)]}//第一次进入页面渲染的盒子const defaultRender = () => {const columnsNumber = setCurrentPageColumns(document.body.clientWidth)for (let index = 1; index < columnsNumber; index++) {const div = document.createElement('div')div.className = 'water-fall-columns'createDomContainer.push(div)waterFallMain.appendChild(div)}const domArrLength = createDomContainer.map(container => container.offsetHeight);const numbersItem = setRandomWaterItemNumber()for (let index = 0; index < numbersItem; index++) {const domContent = document.querySelectorAll('.water-fall-columns')const div = document.createElement('div')const height = setRangeWidth()div.style.height = height + 'px'div.style.backgroundColor = setRandomColor()div.className = 'water-fall-item'div.innerText = index + 1let resultLength = domArrLength.reduce((pre, cur, curIndex) => {return pre > cur ? cur : pre;}, domArrLength[0])let lastIndex = domArrLength.indexOf(resultLength)const allBox = document.querySelectorAll('.water-fall-columns')allBox.forEach((v, k) => {if (k === lastIndex) {v.appendChild(div)domArrLength[k] = v.offsetHeight}})}}
二、初版waterfall布局问题的排查和解决
1.排查问题
- 首先我通过上面的位置错误,可以显而易见的发现是
每个盒子的高度获取
或者插入盒子的位置
, 二者其中一个存在一定的问题。- 然后经过排查,发现通过dom.offsetHeight这个属性获取盒子的时候,并不能返回当前盒子的高度,而且会出现
前一个盒子的offsetHeight居然在遍历的过程中影响到后面的盒子高度(偶尔发生)
,所以就导致了出现上面的情况。
2.解决问题
从排查的问题的结果中发现,是因为每一列的高度计算出现了问题!!!!!!!所以这个时候就好办了。
第一种解决方法:设置块级作用域(行不通)
因为是获取高度出现的问题,有没有一种可能🤔:是没有块级作用域导致
的问题?
我紧接着就进行了尝试。
代码修改如下图所示:
修改后如下图所示(依然有插入顺序问题):
头部的图是这样,尾部的图也是与前端一致的,所以果断放弃了往这方面思考🤔
第二种解决方法:改变每一列高度的获取方式(成功了)
因为是要计算每一列的高度,所以我从原来获取插入后的高度===》插入一个元素就在当前列添加这个元素的高度,实现一个累加的效果。
代码修改如下图所示:
图1如下(waterfall布局正常渲染)
图2如下(waterfall布局正常渲染)
3.完整代码 👇方🔗获取
点我跳转
总结(完整代码文件点击下方🔗,晚些更新进阶版)
从开始接触这个功能 ➡️➡️ 构思解决方案 ➡️➡️ 解决方案验证 ➡️➡️ 方案基本实现 ➡️➡️ 问题发现 ➡️➡️
解决问题。整个流程下来呢,合计不超过1.5d。更多的是思考需要的时间会更加的多。
完整的代码请点击👉🔗
希望大家都可以找到自己感兴趣的事情,💪💪💪!!!!!