vue+js实现瀑布流图片

554 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第6天,点击查看活动详情

前言

掘友们,大家好啊,这篇文章小编主要给大家讲述一下瀑布流的实现流程,后续会更新瀑布流+懒加载,实现图库式网页的展示效果。

什么是瀑布流

在代码实现之前,我们需要了解下什么是瀑布流。瀑布流是当今网站比较流行的一种网页布局,其布局展示有特性,参差不齐,可以根据页面的滚动,加载相应的信息。这种布局常适用于图片信息网站,用于图片的加载展示,有很好的展示效果,瀑布流特点就是定宽不定高。

代码实现

这里小编是在vue项目中实现的,道理都很简单,下边是源码。

vue

<template>
  <div id="pubuliu">
    <div v-for="(item, index) in imageList" :key="index">
      <img :class="['item', `item${index}`]" :src="item" alt="" />
    </div>
  </div>
</template>

js

imageList中的数据是图片数据,大家可以更换新的测试一下。

获取父元素的总宽度,再根据元素的宽度,分布式排列,每一行只能设置排列几个元素,添加到数组中,通过数组循环,获取当前元素的高度,让随后元素通过绝对定位,排列到该元素末尾,依次执行。

export default {
  name: "login",
  components: {},
  data() {
    return {
      imageList: [
        "https://img1.baidu.com/it/u=2223176155,1442240853&fm=253&app=138&size=w931&n=0&f=JPEG&fmt=auto?sec=1669827600&t=d1a5ae0244318108715612ae0fa76ab5",
        "https://img2.baidu.com/it/u=2898829455,2734408317&fm=253&fmt=auto&app=120&f=JPEG?w=1280&h=800",
        "https://img1.baidu.com/it/u=2647973744,3827496954&fm=253&app=138&size=w931&n=0&f=JPEG&fmt=auto?sec=1669827600&t=d6bdfbb2184baf871271ef9cec6d35e9",
        "https://img0.baidu.com/it/u=1036819683,3609732603&fm=253&app=138&size=w931&n=0&f=JPEG&fmt=auto?sec=1669827600&t=49d0853367d8c6b9c1b47ad8c06949c1",
        "https://img0.baidu.com/it/u=3806884198,2790177765&fm=253&app=138&size=w931&n=0&f=JPG&fmt=auto?sec=1669827600&t=ed8d35f93e7c2797d77924f20a36caae",
        "https://img0.baidu.com/it/u=1317822440,3255572922&fm=253&app=138&size=w931&n=0&f=JPEG&fmt=auto?sec=1669827600&t=95befb9a8743210989302e6b684a034c",
        "https://img0.baidu.com/it/u=3594725999,1437276298&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=281",
        "https://img1.baidu.com/it/u=936165722,1965201282&fm=253&app=138&size=w931&n=0&f=JPEG&fmt=auto?sec=1669827600&t=46e6a3ee8e54ff4b4fc6e4f993c9a037",
        "https://img2.baidu.com/it/u=1565119354,3393975436&fm=253&app=120&size=w931&n=0&f=JPEG&fmt=auto?sec=1669827600&t=8f6165a9eb6f25c1b53cb8d5d81761f7",
        "https://img2.baidu.com/it/u=3374881627,2656788225&fm=253&app=138&size=w931&n=0&f=JPEG&fmt=auto?sec=1669827600&t=004a961123299c0466153d32fa55deba",
        "https://img1.baidu.com/it/u=1101454660,2268298569&fm=253&app=138&size=w931&n=0&f=JPEG&fmt=auto?sec=1669827600&t=41aae4f041b0f902b919993349c14ee9",
        "https://img2.baidu.com/it/u=3124488439,1080308879&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=1082",
        "https://img2.baidu.com/it/u=1661065193,1426179229&fm=253&app=138&size=w931&n=0&f=JPEG&fmt=auto?sec=1669827600&t=65967dd2a1804d94de2477eab0ddbb7d",
        "https://img1.baidu.com/it/u=219752959,2207818343&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=725",
        "https://img1.baidu.com/it/u=2629687430,3233648827&fm=253&fmt=auto&app=138&f=JPEG?w=313&h=500",
        "https://img1.baidu.com/it/u=574769240,3416094749&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=281",
        "https://img2.baidu.com/it/u=497086471,3307466230&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=281",

      ],
    };
  },
  methods: {
    getHeight() {
      // 获取页面宽度
      let pageWidth =
        document.getElementById("pubuliu").clientWidth;
      // 获取图片固定的宽度
      let itemWidth = document.getElementsByClassName("item")[0].offsetWidth;
      // 设置图片之间间距
      let gap = 10;
      // 获取一行最多可以展示几张图片
      let nums = Math.floor(pageWidth / (itemWidth + gap));
      // 瀑布流实现原则:
      // 所有图片元素绝对定位,从第二行开始,依次从第一行图片元素高度最小的下方填充,这里注意,不是从左至右填充,即优先填补空位,填补一个后,再填补下一个较大的空位
      // 定义第一行图片的所有高度的数组,之后每张图片下方填充图片后,会更新数组对应位置下的最小高度
      let heightList = [];
      let itemArr = document.getElementsByClassName("item");
      let imgLen = itemArr.length;
      for (let i = 0; i < imgLen; i++) {
        // 如果 当前图片元素索引小于一行最多可以展示的图片个数,说明是第一行,top 已在css中默认设置为0,需要统一设置 left 值,top值如果加gap,则还需设置gap值
        if (i < nums) {
          // 将第一行的图片元素的高度放入 heightList 数组
          heightList.push(itemArr[i].offsetHeight + gap);
          itemArr[i].style.top = gap + "px";
          itemArr[i].style.left = (itemWidth + gap) * i + "px";
        } else {
          // 否则从第二行开始,要根据第一行图片元素的高度,设置top和left
          // 先假设 heightList[0] 为最小高度
          let minItem = {
            minHeight: heightList[0],
            minIndex: 0,
          };
          for (let j = 0; j < heightList.length; j++) {
            if (heightList[j] < minItem["minHeight"]) {
              minItem["minHeight"] = heightList[j];
              minItem["minIndex"] = j;
            }
          }
          itemArr[i].style.top = minItem["minHeight"] + gap + "px";
          itemArr[i].style.left =
            (itemWidth + gap) * minItem["minIndex"] + "px";
          // 关键步骤,更新 heightList 中对应位置下整列图片的高度,以便在下次循环时根据heightList 重新寻找最小高度
          heightList[minItem["minIndex"]] =
            parseFloat(itemArr[i].style.top) +
            parseFloat(itemArr[i].offsetHeight);
        }
      }
    }
  },
  mounted() {
    let _this = this;
    window.onload = function () {
      _this.getHeight()
    };
  }
};

css

* {
  margin: 0;
  padding: 0;
}

body {
  width: 100vw;
  height: 100vh;
}

#pubuliu {
  width: 100%;
  height: 100%;
  overflow: scroll;
  position: relative;
  background-color: lightgray;

  .item {
    width: 200px;
    height: auto;
    box-sizing: border-box;
    background: #fff;
    border: 1px solid #000;
    border-radius: 15px;
    text-align: center;
    font-size: 40px;
    font-weight: bold;
    position: absolute;
    top: 0;
    left: 0;
  }
}

结尾

大家完全可以创建vue项目,复制源码,操作一下,实现瀑布流很简单,后续会继续更新瀑布流的懒加载实现原理,希望这篇文章对大家有所帮助。