JavaScript实现瀑布流布局详解

 更新时间:2022年07月25日 10:38:06   作者:盖玥希圈外男友(섭소우)  
这篇文章主要为大家详细介绍了JavaScript瀑布流的实现方法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助

需求

所谓瀑布流布局,就是含有若干个等宽的列,每一列分别放置图片、视频等,放置的元素都是等宽的,因此可能是不等高的。新的元素到来时,会插入高度较低的那一列,这样形成参差的、视觉上像瀑布一样的布局。

这里简化一下,只要两列等宽布局展示图片即可。

思路

两列布局,直接使用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等异步操作。

到此这篇关于JavaScript实现瀑布流布局详解的文章就介绍到这了,更多相关JS瀑布流布局内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • JavaScript中播放音频文件的几种常用方法

    JavaScript中播放音频文件的几种常用方法

    JS可以用来播放多种声音文件,包括常见的mp3、wav等格式,这篇文章主要给大家介绍了关于JavaScript中播放音频文件的几种常用方法,需要的朋友可以参考下
    2023-10-10
  • webuploader分片上传的实现代码(前后端分离)

    webuploader分片上传的实现代码(前后端分离)

    这篇文章主要介绍了webuploader分片上传的实现代码(前后端分离),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-09-09
  • JavaScript其他类型的值转换为布尔值的规则详解

    JavaScript其他类型的值转换为布尔值的规则详解

    在JavaScript中,所有的值在逻辑上下文中都会被转换为布尔类型(Boolean),理解这些转换规则对开发者来说至关重要,尤其是在条件判断、短路运算、逻辑非(!)等场景下,正确掌握布尔转换可以避免潜在的bug,本文将详细介绍 JavaScript 其他类型的值是如何转换为布尔值的
    2025-04-04
  • 利用Plupload.js解决大文件上传问题, 带进度条和背景遮罩层

    利用Plupload.js解决大文件上传问题, 带进度条和背景遮罩层

    本篇文章主要介绍了c#+Plupload.js解决大容量文件上传问题, 带进度条和背景遮罩层,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
    2017-03-03
  • JavaScript实现公告栏上下滚动效果

    JavaScript实现公告栏上下滚动效果

    这篇文章主要为大家详细介绍了JavaScript实现公告栏上下滚动效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-03-03
  • 面试中常考的JavaScript中简单类型数据转换盘点

    面试中常考的JavaScript中简单类型数据转换盘点

    我们都知道,JS是弱类型语言,变量的类型是可以改变的,本文我们只讨论es6之前的简单数据类型的显示转换String,Number,Boolean这3种,有需要的可以参考下
    2024-12-12
  • javascript各种复制代码收集

    javascript各种复制代码收集

    javascript各种形式的复制代码效果,有直接复制url,复制文本框中的内容、隐藏表单中的内容,复制span中的内容
    2008-09-09
  • JavaScript改变CSS样式的方法汇总

    JavaScript改变CSS样式的方法汇总

    JavaScript修改CSS有4种方法:1.修改节点style(内联样式);2.改变节点class或id;3.写入新的css;4.替换页面中的样式表。今天主要给大家介绍下前2种,因为后两种个人不是很推荐大家使用
    2015-05-05
  • JavaScript this调用规则说明

    JavaScript this调用规则说明

    我希望通过这些来使你们理解各种函数调用方式的不同,让你的JavaScript代码远离bugs。
    2010-03-03
  • JS前端接口防止重复请求的三种实现方案

    JS前端接口防止重复请求的三种实现方案

    前段时间心血来潮,想把项目的前端都做一下接口防止重复请求的处理,虽然大部分的接口处理我们都是加了loading的,但又不能确保真的是每个接口都加了的,下面就来总结一下这次的防重复请求的实现方案,需要的朋友可以参考下
    2024-03-03

最新评论