小白请看! 大厂面试题 :如何用JS实现瀑布流

423 阅读4分钟

前言

今天我们来聊聊,阿里面试题:如何用JS实现瀑布流式页面布局。而瀑布流式页面布局在很多软件中都有使用,例如淘宝,小红书等。

如下:

微信图片_20231030141223.jpg 微信图片_20231030085919.jpg 屏幕截图 2023-10-30 084716.png

那瀑布流是什么呢?

瀑布流(Waterfall Flow)是一种在网页设计和移动应用界面中常见的布局风格。瀑布流布局的主要特点是以多列的形式展示内容,其中每一列中的内容垂直排列,并且在不同列之间以不规则的方式进行排列,当一行图片排满之后,下一行图片将插入到上一行最矮的图片下面,以填充可用的空间。这种布局方式通常用于展示图片、新闻、社交媒体帖子、产品列表等多媒体和多项内容。

瀑布流的优点

  1. 吸引人眼:瀑布流式布局通常以不规则的方式展示内容,这可以吸引用户的注意力。由于内容以多个不同大小和形状的块呈现,用户更有可能浏览整个页面,以查看感兴趣的内容。
  2. 适应不同屏幕尺寸:瀑布流布局能够自适应不同屏幕尺寸,因为它会自动调整列数和块的大小以适应可用的空间。这使得网站在桌面、平板和移动设备上都能够提供良好的用户体验。
  3. 提高用户参与度:由于内容以紧凑的方式呈现,用户更有可能与页面上的多个元素互动,如点击链接、分享内容或留下评论。这可以提高用户的参与度和互动。
  4. 节省空间:瀑布流布局可以有效地利用页面空间,以容纳大量内容,而不会显得拥挤。这对于新闻、博客和社交媒体等内容丰富的网站非常有用。

效果实现

  • 实现瀑布流式页面布局需要准备大量图片,我这里下载了40张图片,图片越多效果越好
  • 编写HTML + CSS代码,给图片添加样式和布局
  • 编写JS代码,根据自己的浏览器以及窗口大小,读取用户屏幕第一行放了多少张图 操作下一张图,找到上一行最矮的高度,将图片排放到其下方

HTMl + CSS

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>js瀑布流</title>
  <style>
    *{
      margin: 0;
      padding: 0;
    }
    #container{
      position: relative;
    }
    .box{
      float: left;
      padding: 5px;
    }
    .box-img{
      width: 150px;      //给装图片的容器设置阴影,使图片更好看
      padding: 5px;
      border: 1px solid #ccc;
    }
    img{
      width: 100%;
    }
  </style>
</head>

<body>
  <div id="container">

    <div class="box">
      <div class="box-img">
        <img src="./img/1.jpg" alt="">
      </div>
    <div>     //此处省略剩下的39个box,代码一样
  <div>      
  
<body>
  
  • container容器来装所有图片,box放入每张图片
  • * { margin: 0; padding: 0; }: 这是通用的CSS样式规则,它将所有HTML元素的默认外边距(margin)和内边距(padding)都设置为0。
  • img设置了所有图片的宽度为100%,跟box-img高度一致
  • .box{ float: left; padding: 5px; }让图片同行显示

JS

// 读取用户屏幕第一行放了多少张图
// 操作下一张图,找到上一行最矮的高度,将图片排放到其下方
imgLocation('container', 'box');

function imgLocation(parent, content) {
  // 获取包含图片的容器元素
  var cparent = document.getElementById(parent);

  // 获取所有包含图片的子元素
  var ccontent = getChildElement(cparent, content);

  // 获取单张图片的宽度
  var imgWidth = ccontent[0].offsetWidth;

  // 计算一行可以容纳多少张图片
  var num = Math.floor(document.documentElement.clientWidth / imgWidth);

  // 设置容器的宽度,以容纳整数倍的图片宽度
  cparent.style.cssText = `width: ${imgWidth * num}px`;

  // 用数组存储每一列的高度
  var BoxHeightArr = [];

  // 遍历图片元素
  for (var i = 0; i < ccontent.length; i++) {
    if (i < num) {
      // 如果是第一行的图片,直接记录它们的高度
      BoxHeightArr[i] = ccontent[i].offsetHeight;
    } else {
      // 对于后续行的图片
      // 找到最矮的列的高度
      var minHeight = Math.min.apply(null, BoxHeightArr);
      // 找到最矮的列的索引
      var minIndex = BoxHeightArr.indexOf(minHeight);

      // 设置当前图片的位置为绝对定位
      ccontent[i].style.position = 'absolute';
      // 设置当前图片的顶部位置为最矮列的高度
      ccontent[i].style.top = minHeight + 'px';
      // 设置当前图片的左侧位置为与最矮列对齐
      ccontent[i].style.left = ccontent[minIndex].offsetLeft + 'px';

      // 更新最矮列的高度,以包含当前图片的高度
      BoxHeightArr[minIndex] = BoxHeightArr[minIndex] + ccontent[i].offsetHeight;
    }
  }

  console.log(num);
}

function getChildElement(parent, content) {
  // 获取指定类名的子元素
  var contentArr = [];
  var allContent = parent.getElementsByTagName('*');
  for (var i = 0; i < allContent.length; i++) {
    if (allContent[i].className == content) {
      contentArr.push(allContent[i]);
    }
  }
  return contentArr;
  // 此行的代码不会执行,因为 return 之后的代码不会被执行
}

  1. 通过imgLocation函数实现了瀑布流式的布局,首先计算一行可以容纳多少张图片,然后遍历图片,找到每张图片应该放置的位置。
  2. getChildElement函数用于获取指定类名的子元素,用于从容器中提取包含图片的子元素。
  3. 最终,页面中的图片会被动态排列,以适应用户屏幕的大小,从而创建瀑布流效果

最后的效果就是这样啦

屏幕截图 2023-10-30 084716.png

今天的内容就到这啦,如果你觉得小编写的还不错的话,或者对你有所启发,请给小编一个辛苦的赞吧