效果展示:
瀑布流布局是网页设计常见的一种布局,一般用于图片多列展示。列宽固定,图片根据自身高度自适应交错排列。
特点:
- 等宽不等高,多列布局;
- 随着页面滚动条向下滚动,不断加载数据块并附加至当前尾部;
- 每行排满后,新的图片添加到后面
- 窗口尺寸改变,重新计算布局
优点
- 节省空间:降低页面的复杂
- 对于 触屏设备非常友好:通过向上滑动浏览,交互方式更符合直觉
- 良好的视觉体验:浏览时不会被页面整整齐齐的高度影响,参差不齐,降低浏览的疲劳
缺点
- 内容总长度 无法掌握
- 数据过多时,容易造成页面 加载的负荷
- 再次加载时 很难定位上一次浏览的内容
理想效果:
- 列宽固定,图片根据自身高度自适应交错排列;
- 排列规则:第一行图片按顺序排满一行,后面的图片按照规则放在高度最小的列下面;
- 图片触底更新,按需加载;
- 窗口大小改变,自适应图片的列数;
- 最底部对齐;
实现方法
一、纯CSS实现(multi-column 多列布局)
用到属性
column-count : 定义列数
column-gap :列与列之间的间隔
特点
顺序只能是 从上到下, 再左到右
缺点
由于排列顺序是先 从上到下, 再左到右,只能用于数据固定, 无法动态的加载追加,对于滚动到底部加载新数据则无法实现。
4.注意点:
有时候页面会出现在前几列的最后一个元素的内容被自动断开,一部分在当前列尾,一部分在下一列的列头。这时候子元素可以用 break-inside设置为不被截断 avoid来控制,像下面这样
break-inside: avoid; // 不被截断 默认值是auto,会被截断
5、实现思路:
- 外层盒子定义列数和列间距
- 每项 item 设置 break-inside: avoid; 让它不被截断
二、flex布局实现
实现思路:
- 将最外层元素设置为 display: flex,即横向排列。
- 设置 flex-flow:column wrap 使其换行。
- 设置 height: 100vh 填充屏幕的高度,来容纳子元素。
- 每一列的宽度可用 calc 函数来设置,即 width: calc(100%/3 - 20px)。分成等宽的 3 列减掉左右两边的 margin 距离。
缺点:
不能动态添加数据
三、JS绝对定位实现(不推荐使用)
原理:
精确计算每个子元素绝对定位到瀑布流它应该去的地方,需要后期一些优化,并不推荐使用
缺点:
- 计算量大,较复杂
- 会有高度塌陷问题
- 子元素因为设置了 absolute并不会占高,页面可滚动的话又会产生另外的问题
- 如果在移动端中会做适配,当前的绝对定位的高度单位在代码实现若为px 并不会自动换算
- 当视口的窗口resize改变,需要重新计算元素的位置,若会不断触发事件,性能消耗大,加载也慢,这是不可取的
关键数据:
- 列的数量
- 图片宽度固定
- 间隙
- 容器宽度
实现思路:
1、创建图片容器、元素
2、绝对定位设置每张图片的位置
- 子元素全部设置成绝对定位
- 找到所有列中>最小的位置
- 计算子元素定位时的 top 以及left
- 修改子元素的样式,设置position为absolute ,以及设置top ,left
- 每次插入的位置选择所有列高度最小 的位置,依次循环
3、监听窗口改变,重新设置图片位置
定义数据和ui样式
数据设计
imgsArr_c 是 增加height属性后的新图片数组
图片预处理
列宽 = 整个容器的宽度 / 列数
图片宽度 = 列宽 - (间隔 * 2)
实现图片按原始比例缩放:图片高度 = 图片宽度 * (原始图片高度 / 原始图片宽度)
若加载失败则设置图片高度与宽度一致,加载成功则按原始比例动态计算图片高度
加载图片
懒加载,预加载,压缩图片
这里需要注意的是,vue 中数据的变化到 DOM 的重新渲染是一个异步过程。vue 中当 data 改变后,并不是立即渲染到页面上的,而是先放到事件队列上。然后,在下一个的事件循环中,Vue 刷新事件队列并执行实际 (已去重的) 工作。这就导致了,数据改变后挂载在 dom 上可能会存在一定的延迟,所以数据改变后立刻去获取 dom 元素可能拿到的不是最新的值而是改变前的值。
所以,使用 $nextTick 来对解决这个问题,$nextTick 的作用就是在下次 dom 更新循环结束后执行其 callback。在修改 imgsArr_c 之后使用这个方法,才能保证排列的元素是更新后的。
设置图片行内样式宽高
设置瀑布流
设置图片的高度,top,left
第一行:
- top = 0
- left = 索引 * 列宽
第二行往后的 n 行:
- 拿到当前高度最低的列高 minHeight,返回其索引 minIndex
- Math.min.apply(null, arr),表示获取数组中最小的值
- top = 最小列的高度值
- left = 最小列的索引 * 列宽
- 更新最小列高度 = 原来的高度 + 新加的图片高度
增加图片间隔在 top 和 列高 都要加
调用预加载图片函数
拿到视口大小
到此,JS实现瀑布流实现完成。
以下是优化部分:
触底更新图片
图片懒加载
在Vue中JS定位实现瀑布流
注意点:axios获取数据,不可在其他方法中拿到,但模板可以使用
四、CSS瓦片布局实现
基于Grid 布局实现的,除了火狐浏览器其他都不支持,兼容性差,Pass掉了。
Vue中瀑布流布局与图片加载优化的实现_vue.js_脚本之家
用 vue 实现瀑布流_vue 瀑布流_hhhqzh的博客-CSDN博客
实现瀑布流布局的四种方法_Smile_zxx的博客-CSDN博客