vue3 实现简单瀑布流

news2025/1/21 7:22:08

一、整理思路

  • 实际场景中,瀑布流一般由 父组件 提供 数据列表,子组件渲染
  • 每个图片都是根据容器进行 绝对定位 ,从而定好自己的位置
  • 取出 屏幕的宽度,设定 图片的宽度 固定 为一个值,计算可以铺 多少列
  • 按列数 先铺上第一行lefttop 值)
  • 第一行铺满以后,后面的每一张都要 铺在高度最低的列,这是瀑布流的核心!所以要维护一个 长度为 列数 的 列高度数组 用于比较
  • 总结:每次放置一张图,都要计算它的 lefttop 值丢进瀑布流数组中,并且更新 列高度数据 便于下次对比

二、代码

父组件

<WaterFall :list="list" />
// 模拟列表数据
const list = [
  {
    height: 300,
    background: "red",
  },
  {
    height: 400,
    background: "pink",
  },
  {
    height: 500,
    background: "blue",
  },
  {
    height: 200,
    background: "green",
  },
  {
    height: 300,
    background: "gray",
  },
  {
    height: 400,
    background: "#CC00FF",
  },
  {
    height: 200,
    background: "gray",
  },
  {
    height: 100,
    background: "#996666",
  },
  {
    height: 500,
    background: "skyblue",
  },
  {
    height: 300,
    background: "#993366",
  },
  {
    height: 100,
    background: "#33FF33",
  },
  {
    height: 400,
    background: "skyblue",
  },
  {
    height: 200,
    background: "#6633CC",
  },
  {
    height: 300,
    background: "#666699",
  },
  {
    height: 300,
    background: "#66CCFF",
  },
  {
    height: 300,
    background: "skyblue",
  },
  {
    height: 200,
    background: "#CC3366",
  },
  {
    height: 200,
    background: "#CC9966",
  },
  {
    height: 200,
    background: "#FF00FF",
  },
  {
    height: 500,
    background: "#990000",
  },
  {
    height: 400,
    background: "red",
  },
  {
    height: 100,
    background: "#999966",
  },
  {
    height: 200,
    background: "#CCCC66",
  },
  {
    height: 300,
    background: "#FF33FF",
  },
  {
    height: 400,
    background: "#FFFF66",
  },
  {
    height: 200,
    background: "red",
  },
  {
    height: 100,
    background: "skyblue",
  },
  {
    height: 200,
    background: "#33CC00",
  },
  {
    height: 300,
    background: "#330033",
  },
  {
    height: 100,
    background: "#0066CC",
  },
  {
    height: 200,
    background: "skyblue",
  },
  {
    height: 100,
    background: "#006666",
  },
  {
    height: 200,
    background: "yellow",
  },
  {
    height: 300,
    background: "skyblue",
  },
  {
    height: 120,
    background: "#33CCFF",
  },
  {
    height: 400,
    background: "#999966",
  },
  {
    height: 630,
    background: "#CC9966",
  },
  {
    height: 250,
    background: "#33FF00",
  },
  {
    height: 300,
    background: "yellow",
  },
  {
    height: 500,
    background: "green",
  },
];

子组件

<template>
  <div class="list">
    <div
      class="item"
      v-for="(item, index) in waterList"
      :style="{
        width: width + 'px',
        height: item.height + 'px',
        left: item.left + 'px',
        top: item.top + 'px',
        background: item.background,
      }"
    >
      {{ index }}
    </div>
  </div>
</template>


<script setup lang="ts">
import { ref, reactive, onMounted } from "vue";

const props = defineProps<{
  list: any[];
}>();

// 图片宽度
const width = 120;
// 图片上下间距
const gap = 20;
// 瀑布流数组
const waterList = ref<any[]>([]);
// 列高度数组
const heightList = reactive<number[]>([]);

// 屏幕宽度需要在 mounted 之后拿到
onMounted(() => {
  // 计算列数
  const column = Math.floor(document.body.clientWidth / width);

  // 核心内容就是维护每个图片的 left、top
  for (let i = 0; i < props.list.length; i++) {
    // 先铺上第一行(i < column 则表示是第一行)
    if (i < column) {
      props.list[i].top = 0;
      props.list[i].left = width * i;
      // 塞进瀑布流
      waterList.value?.push(props.list[i]);
      // 高度数据更新
      heightList[i] = props.list[i].height;
    }

    // 后面的就要一张张塞进去,每次找出最低的列往里塞
    else {
      // 最低的高度,先默认为第一列高度
      let current = heightList[0];
      // 最低的列,先默认为第一个
      let col = 0;

      // 循环每一列进行比较
      heightList.forEach((h, i) => {
        if (h < current) {
          current = h;
          col = i;
        }
      });
      console.log("最低的列", col, "高度为", current);

      // 由此计算出该图片的 left、top
      props.list[i].left = col * width;
      props.list[i].top = current + gap;
      // 塞进瀑布流
      waterList.value.push(props.list[i]);

      // 更新列高度数组
      heightList[col] = current + gap + props.list[i].height;
    }
  }
  console.log("waterList", waterList.value);
  console.log("heightList", heightList);
});
</script>
<style lang="scss" scoped>
.list {
  position: relative;
  height: 100%;
  overflow: auto;
  
  .item {
    position: absolute;
    font-size: 30px;
  }
}
</style>

效果如图

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/895518.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【嵌入式】MKV31F512VLL12 微控制器 (MCU) 、Cyclone® IV E EP4CE10E22I8LN,FPGA-现场可编程门阵列芯片

1、MKV31F512VLL12 微控制器 (MCU) 是适用于BLDC、PMSM和ACIM电机控制应用的高性能解决方案。这些MCU采用运行频率为100MHz/120MHz、带数字信号处理 (DSP) 和浮点单元 (FPU) 的ARM Cortex-M4内核。KV3x MCU配备两个采样率高达1.2MS/s的16位ADC、多个控制定时器以及512KB闪存。 …

【SpringCloud】Stream消息通知使用

文章目录 概述标准MQ 配置POMYML 示例消息发送配置RabbitMQ可视化插件消息消费者 遇到的问题复现解决&#xff1a;修改YML注意 概述 屏蔽底层消息中间件的差异,降低切换成本&#xff0c;统一消息的编程模型 官网&#xff1a; https://spring.io/projects/spring-cloud-stream#…

Docker Dockerfile Docker-compose学习笔记

文章目录 Centos环境下安装Docker配置镜像源 Windows环境下安装Docker配置镜像源 使用Dokcer镜像1.获取镜像2.查看镜像信息(1)列出镜像(2)镜像标签(3)镜像详细信息(4)镜像历史 3.搜索镜像4.删除和清理镜像(1)使用标签删除镜像(2)使用ID删除镜像(3)清理镜像 5.创建镜像(1)基于已…

Git分享-规范/建议/技巧

1. Git多人协作开发流程图 1.1 processOn默认的模板 1.2 改造之后 https://www.processon.com/view/link/64ccaf56a433c931b2f9428a 访问密码&#xff1a;512I ① 总流程图 ② feat分支&#xff08;功能/需求 分支&#xff09;流程 ③ bugfix分支&#xff08;紧急补丁分支&…

微信设置快捷回复话术,快速回复!

微信上如何快速回复&#xff1f;其实是有个小技巧的 微信作为目前最流行的社交媒体平台之一&#xff0c;已经成为许多企业与用户之间沟通的重要渠道。当用户数量的增加和信息交流的频繁&#xff0c;如何提高回复效率就成了某部分人的问题。 微信上是没有快速回复的功能的&#…

315官方点赞!多燕瘦或将成酵素选购唯一标准

食用酵素及其衍生产品&#xff0c;是近年来国内主流电商平台的主要增长类目之一。在全球范围内&#xff0c;酵素的流行由来已久&#xff0c;其中在日本、北美、欧洲等发达国家和地区尤为风靡。据不完全统计&#xff1a;欧洲酵素市场规模约占全球酵素市场份额的40%以上&#xff…

Grafana监控大盘配置教程

1、新建大盘 2、输入指标和大盘名 若是Time series类型&#xff0c;则到此就可以看到数据&#xff1b;若是Table类型则进行下一步 3、修改大盘类型为Table 4、修改指标输出 Transformation functions&#xff1a;Transform data | Grafana documentation Filter by name——…

re学习(35)攻防世界-no-strings-attached(动调)

参考文章&#xff1a;re学习笔记&#xff08;28&#xff09;攻防世界-re-no-strings-attached_Forgo7ten的博客-CSDN博客 攻防世界逆向入门题之no-strings-attached_攻防世界 no-strings-attached_沐一 林的博客-CSDN博客 本人题解&#xff1a; 扔入Exepeinfo中查壳和其他信息…

预测性维护能为工厂带来什么改变?

数字化时代的到来&#xff0c;为制造业带来了前所未有的机遇和挑战。在数字化转型的浪潮中&#xff0c;预测性维护&#xff08;PredictiveMaintenance&#xff0c;简称PdM&#xff09;凭借其卓越的潜力&#xff0c;在提升设备效率、降低成本、优化生产等方面成为工厂的强有力助…

【0基础入门Python笔记】二、python 之逻辑运算和制流程语句

二、python 之逻辑运算和制流程语句 逻辑运算控制流程语句条件语句&#xff08;if语句&#xff09;循环结构&#xff08;for循环、while循环&#xff09;continue、break和pass关键字控制流程语句的嵌套以及elif 逻辑运算 Python提供基本的逻辑运算&#xff1a;不仅包括布尔运…

龙测面对面,一张图让你明白软件测试saas企业的功能布局

大家好&#xff0c;和大家认识也挺久了&#xff0c;好像也没有做过自我介绍。择日不如撞日&#xff0c;今天我们就好好聊聊吧。自我介绍分为了两个部分&#xff0c;上半部分是龙测科技的由来、梦想以及目前的成就&#xff1b;下半部分是龙测目前的产品功能框架。对产品功能感兴…

windows下redis服务启动及.bat文件中中redis服务的启动

windows windows下redis服务的启动 1、不配置环境变量 找到redis服务的安装目录进入命令行窗口并输入命令redis-server.exe redis.windows.conf2、配置环境变量 将redis安装目录配置在path环境变量中之后就可以在cmd窗口的任意位置输入redis-server命令就可以启动redis服务…

[测试报告] 爱搜Blog 自动化测试报告

目录 项目背景 项目功能 测试详情 一、设计测试用例 二、功能测试步骤结果 1. 登录页面 2. 个人博客页面 3. 博客详情页 4. 博客编辑页 三、自动化测试及测试结果 1. 测试环境 2. 登录测试用例&#xff1a; 3. 个人详情页测试用例&#xff1a; 4. 写博客并发布测试…

1849. 将字符串拆分为递减的连续值;1024. 视频拼接;1530. 好叶子节点对的数量

1849. 将字符串拆分为递减的连续值 核心思想:递归回溯题。和842. 将数组拆分成斐波那契序列的代码是差不多的&#xff0c;遇到拆分题首先想的就是dfs(index)表示从index开始拆分是否可以&#xff0c;然后去枚举拆分的end即可&#xff0c;我把这种题目归纳为拆分题&#xff0c;…

Kubernetes 对外服务 Ingress

Ingress 简介 service的作用体现在两个方面&#xff0c;对集群内部&#xff0c;它不断跟踪pod的变化&#xff0c;更新endpoint中对应pod的对象&#xff0c;提供了ip不断变化的pod的服务发现机制&#xff1b;对集群外部&#xff0c;他类似负载均衡器&#xff0c;可以在集群内外部…

解决访问Github出现的Couldn‘t connect to server错误

文章目录 前言原因分析以及解决办法原因分析解决办法 参考 前言 在Github上面克隆代码仓库出现Failed to connect to 127.0.0.1 port 1080 after 2063 ms: Couldnt connect to server、Failed to connect to github.com port 443 after 21083 ms: Couldnt connect to server等…

Docker中为RabbitMQ安装rabbitmq_delayed_message_exchange延迟队列插件

1、前言 rabbitmq_delayed_message_exchange是一款向RabbitMQ添加延迟消息传递&#xff08;或计划消息传递&#xff09;的插件。 插件下载地址&#xff1a;https://www.rabbitmq.com/community-plugins.html 1、下载插件 首先需要确定我们当前使用的RabbitMQ的版本&#xff0c…

Win11任务栏左下角如何显示天气

最近有小伙伴找到我想要知道win11左下角怎么显示天气&#xff0c;小编为小伙伴带来了win11左下角显示天气方法介绍&#xff0c;首先打开任务栏设置&#xff0c;然后找到小组件&#xff0c;点开小组件之后可以看到关于天气的选项&#xff0c;点击右上角的就可以成功的添加&#…

Ozon限制售卖品类 速速收藏

每个电商平台都会有自己的规则和政策&#xff0c;都会有一些限制销售的品类&#xff0c;根据不同地域和文化会有不同&#xff0c;本文来介绍一下老牌俄罗斯购物平台Ozon有哪些限制售卖的品类。选品的商家需要明确自己的品类有没有违规&#xff0c;违规商品平台会进行下架和限制…

【C++类和对象】类有哪些默认成员函数呢?(下)

文章目录 一、类的6个默认成员函数二、日期类的实现2.1 运算符重载部分2.2 日期之间的运算2.3 整体代码1.Date.h部分2. Date.cpp部分 三. const成员函数四. 取地址及const取地址操作符重载扩展内容 总结 ヾ(๑╹◡╹)&#xff89;" 人总要为过去的懒惰而付出代价ヾ(๑╹◡…