当前位置:网站首页>瀑布流布局
瀑布流布局
2022-07-25 14:59:00 【盖玥希圈外男友(섭소우)】
目录
需求
所谓瀑布流布局,就是含有若干个等宽的列,每一列分别放置图片、视频等,放置的元素都是等宽的,因此可能是不等高的。新的元素到来时,会插入高度较低的那一列,这样形成参差的、视觉上像瀑布一样的布局。
这里简化一下,只要两列等宽布局展示图片即可。
思路
两列布局,直接使用flex布局实现即可。不过,这里不能设置align-items为center,如果设置了将会使图片列居中显示,不符合瀑布流的视觉效果。我设置left和right两列,两列的宽度相等,结构和样式基本就写完了。
然后写JavaScript。其逻辑是,判断当前left和right的高度(我使用clientHeight),如果左边<=右边,则放入左边,否则放入右边。遍历所有的图片,按照这个逻辑放入即可。
代码实现
html部分
<!-- 瀑布流父容器 -->
<div class="container">
<!-- 两列等宽布局 -->
<div class="col left"></div>
<div class="col right"></div>
</div>css部分
.container {
width: 700px;
background-color: aliceblue;
margin: auto;
/* flex布局 */
display: flex;
align-items: flex-start;
}
.col {
flex-basis: 350px;
}
.col img {
/* 固定图片的宽度 */
width: 100%;
}JavaScript部分
// 获取三个元素
let container = document.getElementsByClassName('container')[0]
let left = document.getElementsByClassName('col')[0]
let right = document.getElementsByClassName('col')[1]
// 插入图片
function initImg() {
for (let i = 1; i < 27; i++) {
let img = new Image();
img.src = "./pictures/" + i + ".jpg"
if (left.clientHeight <= right.clientHeight) {
left.appendChild(img)
} else {
right.appendChild(img)
}
}
}
initImg()如代码所示,获取了父元素和左右两列,然后遍历每一张图片,依次判断插入即可。看上去很完美,但是真的如此吗?
实现效果

看上去貌似很完美,也有瀑布的样子。但当拉到页面底部发现:

左边的一大块都是空的,全部放在了右边。这显然不对,因为按照逻辑,左边更短,应该加在左边才对。
问题和修正
问题就在于,img的加载是个异步的过程。再看刚才的for循环:
// 插入图片
function initImg() {
for (let i = 1; i < 27; i++) {
let img = new Image();
img.src = "./pictures/" + i + ".jpg"
if (left.clientHeight <= right.clientHeight) {
left.appendChild(img)
} else {
right.appendChild(img)
}
}
}new了Image对象后,指定了其src,然后立刻判断左右两边的高度。这时,img还没有加载完毕。然而,for循环不会等待它加载完毕。下一张图片产生后,立刻也会判断,但此时上一张图片还没有放到页面上,所以左右的高度很可能就是错误的,从而产生了错误的判断。这就出现了上图中,右列出现了很多很多图片,而左列空白的样子。
解决办法就是,把这个循环写成异步的,只有上一张图片加载完毕后,才去判断下一张图片。
很容易想到,使用Promise完成异步判断。但是对于循环中的Promise,很难清楚地通过then的变化来推进。于是,我决定采用async和await。
这就需要再封装一个方法,这个方法返回Promise,在Promise中加载某一张图片。然后再遍历所有图片,使用async/await,依次调用这个方法,就能得到结果了。
而在Promise中,我们在什么时候调用resolve呢?这就需要监听img的onload事件,设置onload事件的回调函数,在回调函数中调用resolve即可。
经过分析,再次完善代码:
// 加载第index张图片
function loadIndexImg(index) {
return new Promise((resolve, reject) => {
// 当前加载的图片
let img = new Image();
img.src = './pictures/' + index + '.jpg'
img.onload = () => {
if (left.clientHeight <= right.clientHeight) {
left.appendChild(img)
} else {
right.appendChild(img)
}
resolve();
}
})
}
// 插入图片
async function initImg() {
// 要在加载完并插入图片后才去判断下一张,因此采用async/await
for (let i = 1; i <= 26; i++) {
await loadIndexImg(i)
}
}
initImg()可以看到,在initImg中,依次调用loadIndexImg,并且是异步调用。在图片加载完成后再去加载下一张图片,效果应该就可以了。
修正后效果

效果很好!!!
总结
本文实现了简单的两列瀑布流布局,其中需要用到Promise等异步操作。
边栏推荐
- Leetcode combination sum + pruning
- LeetCode_字符串_中等_151.颠倒字符串中的单词
- Copy files / folders through Robocopy
- 45padding won't open the box
- (原创)自定义一个滚屏的RecyclerView
- Gameframework making games (I)
- Kibana operation es
- QT connect, signal, slot and lambda comparison
- [nuxt 3] (XI) transmission & module
- 006 operator introduction
猜你喜欢

流程控制(上)

oracle_12505错误解决方法

43 box model

IP address classification, which determines whether a network segment is a subnet supernetwork

45padding不会撑开盒子的情况

SSH服务器拒绝了密码

String type time comparison method with error string.compareto

Splice a field of the list set into a single string

Leo-sam: tightly coupled laser inertial odometer with smoothing and mapping

Leetcode combination sum + pruning
随机推荐
阿里云技术专家邓青琳:云上跨可用区容灾和异地多活最佳实践
Add the jar package under lib directory to the project in idea
006 operator introduction
awk从入门到入土(24)提取指令网卡的ip
"How to use" agent mode
Gameframework making games (II) making UI interface
Raft of distributed consistency protocol
Overview of cloud security technology development
06. Neural network like
Jmeter的随机数函数怎么用
awk从入门到入土(23)awk内置变量ARGC、ARGC--命令行参数传递
[C topic] Li Kou 88. merge two ordered arrays
MySQL sort
awk从入门到入土(20)awk解析命令行参数
"Ask every day" briefly talk about JMM / talk about your understanding of JMM
MySQL 45 talks about | 06 global locks and table locks: Why are there so many obstacles to adding a field to a table?
Niuke multi school E G J L
MySQL 45讲 | 06 全局锁和表锁 :给表加个字段怎么有这么多阻碍?
37 element mode (inline element, block element, inline block element)
[MySQL series] - how much do you know about the index