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瀑布流布局内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • js瀑布流布局的实现

    本文实例为大家分享了js实现瀑布流布局的具体代码,供大家参考,具体内容如下 原理: 1.瀑布流布局,要求进行布局的元素等宽,然后计算元素的宽与浏览器的宽度之比,得到需要布置的列数. 2.创建一个数组,长度为列数,数组元素为每一列已布置元素的总高度.(一开始为0). 3.将未布置的元素,依次布置到高度最小的那一列,然后更新这一列的高度,就得到了瀑布流布局 实现 布局 <body> <div id="content"> <div id="box&qu

  • 如何用JS实现网页瀑布流布局

    前言: 瀑布流 又称瀑布流式布局,是比较流行的一种网站页面布局方式.即多行等宽元素排列,后面的元素依次添加到其后,等宽不等高,根据图片原比例缩放直至宽度达到我们的要求,依次按照规则放入指定位置. 什么是瀑布流布局: 先看效果: 图片多行等宽元素排列,后面的元素依次添加到其后,等宽不等高,根据图片原比例缩放直至宽度达到我们的要求,依次按照规则放入指定位置. 为了方便理解,在此先给上html.css代码 不完整html代码: <div id="container"> <d

  • 一行JavaScript代码如何实现瀑布流布局

    写在前面 一行 JavaScript 代码究竟可以完成什么布局?今天我们就来用一行 JavaScript 代码完成经典布局的一种,瀑布流布局. 所谓的瀑布流布局就是比较流行的一种网站页面布局,视觉表现为参差不齐的多栏布局,随着页面滚动条向下滚动,这种布局还会不断加载数据块并附加至当前尾部. 瀑布流的特点: 琳琅满目: 整版以图片为主,大小不一的图片按照一定的规律排列. 唯美: 图片的风格以唯美的图片为主. 操作简单: 在浏览网站的时候,只需要轻轻滑动一下鼠标滚轮,一切的美妙的图片精彩便可呈现在你

  • JavaScript实现瀑布流布局的3种方式

    前言 今天逛闲鱼的时候观察到每一行的高度不是相同的,经了解才知道原来这是一种瀑布流布局,感觉挺有意思,于是决定研究一下,在网上也找了一些方案,实现瀑布流大概有3种方式. 一.JS 实现瀑布流 思路分析 1.瀑布流布局的特点是等宽不等高. 2.为了让最后一行的差距最小,从第二行开始,需要将图片放在第一行最矮的图片下面,以此类推. 3.父元素设置为相对定位,图片所在元素设置为绝对定位.然后通过设置 top 值和 left 值定位每个元素. 代码实现 <!DOCTYPE html> <html

  • js实现九宫格布局效果

    本文实例为大家分享了js实现九宫格布局效果的具体代码,供大家参考,具体内容如下 效果 代码如下: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <style type="text/css"> *{ margin: 0; padding: 0; } #container{ width: 1200

  • JS实现动画中的布局转换

    在用JS编写动画的时候,经常用会到布局转换,即在运动前将相对定位转为绝对定位,然后执行动画函数.下面给大家分享一个运用原生JS实现的布局转换的Demo,效果如下: 以下是代码实现,欢迎大家复制粘贴及吐槽. <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <titl

  • JavaScript圣杯布局与双飞翼布局实现案例详解

    目录 一.圣杯布局和双飞翼布局的功能介绍 二.圣杯布局 高度如何自适应屏幕高度 圣杯布局思路 圣杯布局代码 三.双飞翼布局 双飞翼布局的思路 双飞翼布局的代码 圣杯布局和双飞翼布局的区别 四.圣杯布局和双飞翼布局面试问题 一.圣杯布局和双飞翼布局的功能介绍 圣杯布局和双飞翼布局是三栏布局中的两种布局方式,他们实现的效果是相同的,区别就是实现方法. header和footer各自占领屏幕所有宽度,高度固定: 中间的outer是一个三栏布局: 三栏布局中left和right不变,center填充其他

  • JavaScript实现瀑布流布局详解

    目录 需求 思路 代码实现 实现效果 问题和修正 修正后效果 总结 需求 所谓瀑布流布局,就是含有若干个等宽的列,每一列分别放置图片.视频等,放置的元素都是等宽的,因此可能是不等高的.新的元素到来时,会插入高度较低的那一列,这样形成参差的.视觉上像瀑布一样的布局. 这里简化一下,只要两列等宽布局展示图片即可. 思路 两列布局,直接使用flex布局实现即可.不过,这里不能设置align-items为center,如果设置了将会使图片列居中显示,不符合瀑布流的视觉效果.我设置left和right两列

  • jQuery实现瀑布流布局详解(PC和移动端)

    瀑布流布局已成为当今非常普遍的图片展示方式,无论是PC还是手机等移动设备上.这种布局图片的样式大概分为三种:等高等宽.等宽不等高.等高不等宽,接下来我们就最为普遍的等宽不等高形式来作为示例. 我们用百度图片作为范例: 这就是PC端比较常见的瀑布流布局方式,接下来我们审查下元素看看百度图片里面是如何布局: 可以看到,它里面实际是若干个等宽的列容器,通过计算将图片push到不同的容器里.而本文介绍的展示方法是通过定位的方式,虽然最后布局展示的方式不同,但之前的算法都比较类似. 动手 首先我们将如下样

  • 微信小程序通过js实现瀑布流布局详解

    前言 瀑布流 - 小程序中数据列表或者图片展示难免高度不一,而我们一般固定宽度,让其高度自适应,并无缝对接.如下图: 瀑布流的两种做法: css: 在父元素上使用column-count: 2也可以做到两列排版.但column-count: 2是左右两列排版,如果碰巧出现左边累计高度过多大于右边累计高度的话,右边会出现大片空白区域.点击前往 js(推荐): 判断左右两边的累计高度,那边的高度小,便往那边添加(需要动态获取节点元素的高度进行计算).下面用的就是此种方法: 准备工作 我们需要用到 a

  • 基于JavaScript表单脚本(详解)

    什么是表单? 一个表单有三个基本组成部分: 表单标签:这里面包含了处理表单数据所用CGI程序的URL以及数据提交到服务器的方法. 表单域:包含了文本框.密码框.隐藏域.多行文本框.复选框.单选框.下拉选择框和文件上传框等. 表单按钮:包括提交按钮.复位按钮和一般按钮:用于将数据传送到服务器上的CGI脚本或者取消输入,还可以用表单按钮来控制其他定义了处理脚本的处理工作. JavaScript与表单间的关系:JS最初的应用就是用于分担服务器处理表单的责任,打破依赖服务器的局面,尽管目前web和jav

  • JavaScript数据结构链表知识详解

    最近在看<javascript数据结构和算法>这本书,补一下数据结构和算法部分的知识,觉得自己这块是短板. 链表:存储有序的元素集合,但不同于数组,链表中的元素在内存中不是连续放置的.每个元素由一个存储元素本身的节点和一个指向下一个元素的引用(也称指针或链接)组成. 好处:可以添加或移除任意项,它会按需扩容,且不需要移动其他元素. 与数组的区别: 数组:可以直接访问任何位置的任何元素: 链表:想要访问链表中的一个元素,需要从起点(表头)开始迭代列表直到找到所需的元素. 做点小笔记. funct

  • JavaScript里 ==与===区别详解

    1.对于string,number等基础类型,==和===是有区别的 1)不同类型间比较,==之比较"转化成同一类型后的值"看"值"是否相等,===如果类型不同,其结果就是不等 2)同类型比较,直接进行"值"比较,两者结果一样 2.对于Array,Object等高级类型,==和===是没有区别的 进行"指针地址"比较 3.基础类型与高级类型,==和===是有区别的 1)对于==,将高级转化为基础类型,进行"值&quo

  • 基于JavaScript实现瀑布流布局(二)

    本文实例讲解了JavaScript实现瀑布流布局详细代码,分享给大家供大家参考,具体内容如下 1.建立Html模版 想法是先用一个div container承载所有内容,然后div box用来放置图片,最后div box_border来当图片框,代码如下 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>瀑布流</title> </head

  • JavaScript String 对象常用方法详解

    字符串是不可变的.字符串方法,不会改变原有字符串的内容,而是返回一个新字符串. charAt():返回在指定位置的字符. concat():连接两个字符串文本,并返回一个新的字符串. indexOf(): indexOf() 方法返回指定值在字符串对象中首次出现的位置. match(): 使用正则表达式与字符串相比较. replace(): 被用来在正则表达式和字符串直接比较,然后用新的子串来替换被匹配的子串. slice(): 摘取一个字符串区域,返回一个新的字符串. split(): 通过分

  • JavaScript hasOwnProperty() 函数实例详解

    hasOwnProperty()函数用于指示一个对象自身(不包括原型链)是否具有指定名称的属性.如果有,返回true,否则返回false. 该方法属于Object对象,由于所有的对象都"继承"了Object的对象实例,因此几乎所有的实例对象都可以使用该方法. IE 5.5+.FireFox.Chrome.Safari.Opera等主流浏览器均支持该函数. 语法 object.hasOwnProperty( propertyName ) 参数 参数 描述 propertyName Str

  • 基于JavaScript实现瀑布流布局

    本文实例讲解了原生JavaScript实现瀑布流布局详细代码,分享给大家供大家参考,具体内容如下 效果图: 具体代码: HTML <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <link rel="stylesheet" type="

随机推荐