Flex布局,几行代码就可以实现瀑布流布局,代码简单,定制化强。

原理很简单,计算图片的宽高,再计算每列的使用高度,然后再将当前图片放置在列高最小的一列。其实这种方式使用什么方式布局都无所谓,我使用的是flexd布局。Flex的使用在这里就不讲解了,网上的教程一大堆。这里讲解使用VUE3实现,并封装成可以使用的组件。

话不多说,上效果
h5-editor

以下是核心代码。

template

<template>
    <div :id="fluidId" v-infinite-scroll="loadMore" :infinite-scroll-distance="20" :infinite-scroll-immediate="false" class="uabs uof-x uof-y-s">
        <div v-if="imgList.length > 0" class="ub ub-f1 upad-rl06">
            <div v-for="i in col" :key="i" class="ub ub-f1 ub-ver" :style="'margin-left:' + (i != 1 ? gutter : 0) + 'px'">
                <el-image v-for="img, idx in imgList[i - 1]" @click="emit('getData', img)" @dragstart="emit('dragstart', img)" @dragend="emit('dragend', img)" :key="idx" :src="img.url || img.thumbnailUrl" loading="lazy" fit="scale-down" class="img-hover uba ushadow" :style="'margin-top:' + gutter + 'px'">
                    <template #error>
                        <el-icon class="ub ub-ac ub-pc ub-fv ub-fh uc-font-gray2 uf-s2" style="height: 50px;">
                            <Picture />
                        </el-icon>
                    </template>
                </el-image>
            </div>
            <div class="uhide">
                <el-image v-for="img, idx in data" :key="idx" :src="img.url || img.thumbnailUrl" @load="load(img)" @error="error(img)" fit="scale-down"></el-image>
            </div>
        </div>
        <el-empty v-if="data.length==0 && isReturn" :image-size="100"></el-empty>
        <div v-else class="ub ub-ac ub-pc upad-t1">
            <el-button v-if="hasMore" type="info" link :loading="!loadOver" @click="loadMore">
                {{ loadOver ? 'more' : 'loading' }}
                <el-icon v-show="loadOver">
                    <ArrowDownBold />
                </el-icon>
            </el-button>
            <el-divider v-else><span class="uf-s06 uc-font-gray1">No more</span></el-divider>
        </div>
    </div>
</template>

以上代码的主要部分是隐藏图片加载,计算当前图片的宽高。

javascript

<script setup>
import {
    ref,
    onMounted
} from 'vue';
import { ArrowDownBold } from '@element-plus/icons-vue';
const emit = defineEmits(['loadMore', 'getData', 'dragstart']);

const props = defineProps({
    col: {
        type: Number,
        default: 2
    },
    gutter: {
        type: Number,
        default: 10
    },
    data: {
        type: Array,
        default: []
    },
    hasMore: {
        type: Boolean,
        default: false
    },
    isReturn: {
        type: Boolean,
        default: false
    }
});
const fluidId = ref(new Date().getTime());
let colWidth = 0;
let imgTotalHeight = [];
const imgList = ref([]);
let loadCount = 0;
const loadOver = ref(false);
const load = (img) => {
    if (colWidth == 0) {
        const dom = document.getElementById(fluidId.value);
        colWidth = (dom.clientWidth / props.col) - (props.col - 1) * props.gutter;
    }
    const temImg = new Image();
    temImg.src = img.url || img.thumbnailUrl;
    
    temImg.onload = function () {
        const width = temImg.width;
        const height = temImg.height;
        const minTotalHeight = Math.min(...imgTotalHeight);
        const colIdx = imgTotalHeight.indexOf(minTotalHeight);
        img.width = width;
        img.height = height;
        imgTotalHeight[colIdx] += (height * colWidth) / width;
        imgList.value[colIdx].push(img);
        loadCount++
        if (loadCount == props.data.length) {
            loadOver.value = true;
        }
    }
}
const error = (img) => {
    const height = 50;
    const minTotalHeight = Math.min(...imgTotalHeight);
    const colIdx = imgTotalHeight.indexOf(minTotalHeight);
    imgTotalHeight[colIdx] += height;
    imgList.value[colIdx].push(img);
    loadCount++;
    if (loadCount == props.data.length) {
        loadOver.value = true;
    }
}

const loadMore = () => {
    if (props.hasMore) {
        loadOver.value = false;
        emit('loadMore', true);
    }
}

const init = () => {
    loadCount = 0;
    loadOver.value = false;
    imgTotalHeight = [];
    imgList.value = [];
    for (let i = 0; i < props.col; i++) {
        imgTotalHeight.push(0);
        imgList.value.push([]);
    }
}
defineExpose({ init });

onMounted(() => {
    init();
})
</script>

以上代码核心代码为load,计算图片的宽高,再计算每列的高度,将图片放置在较矮的那一列。

接收的Props
col:展示的列数
gutter: 每列之前的距离,单位px
data: 图片列表,如:[{url:url1},{url:url2}]
hasMore: 是否有更多,为true向下滚动可自动加载
isReturn:展示loading用

暴露的方法
loadMore:加载更多
getData:点击当前图片
dragstart:拖拽当前图片

style

.ub {
  position: relative;
  display: -webkit-flex;
  display: flex;
  flex-direction: row;
}
.ub-ac {
  justify-content: center;
} 

.ub-pc {
  align-items: center;
}
.ub-fh {
  width: 100%;
}

.ub-fv {
  height: 100%;
}
.fluid-img {
    border-radius: 5px;
    overflow: hidden;
    min-height: 30px;
}

如何使用

<template>
  <template v-else>
    <Fluid ref="fluidCom" :col="3" :gutter="10" :data="dataList" :is-return="isReturn" :has-more="hasMore" @load-more="getMoreMaterial"></Fluid>
  </template>
<script setup>
  import Fluid from '@/components/Fluid.vue';
</script>

代码已开源,可参考源码加载资源部分。代码简单,定制化强,不防试试。
见github

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数据治理到底是什么?为什么要做数据治理?

数据治理的两个目标&#xff1a;一个是提质量&#xff0c;一个是控安全。通过业务流程优化&#xff0c;规范数据从产生、处理、使用到销毁的整个生命周期&#xff0c;使得数据在各阶段、各流程环节安全可控&#xff0c;合规使用。 数据治理治的是“数据”吗&#xff1f; 数据是…

springboot与springcloud之间的版本对应关系

https://start.spring.io/actuator/info 当然&#xff0c;你可以直接在&#xff1a; https://spring.io/projects/spring-cloud 上看文档查询&#xff0c; 不过&#xff0c;最后应该是调到这里的&#xff1a; https://github.com/spring-cloud/spring-cloud-release/wiki/Suppo…

2024年【中级消防设施操作员(考前冲刺)】找解析及中级消防设施操作员(考前冲刺)考试总结

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2024年中级消防设施操作员&#xff08;考前冲刺&#xff09;找解析为正在备考中级消防设施操作员&#xff08;考前冲刺&#xff09;操作证的学员准备的理论考试专题&#xff0c;每个月更新的中级消防设施操作员&#…

git clone常见问题一览及解决方法

在使用Ubuntu下&#xff0c;终端运行git clone命令时会遇见许多问题&#xff0c;本文主要针对一些常见的问题进行整理。关于换源问题&#xff0c;推荐使用小鱼的一键换源。 1.git clone 速度过慢 1.1 魔法 这个方法不做过多赘述&#xff0c;ubuntu下个人使用发现体验良好&am…

国外知名的农业机器人公司

从高科技温室到云播种&#xff0c;农业机器人如何帮助农民填补劳动力短缺以及超市货架的短缺。 概要 “高科技农业”并不矛盾。当代农业经营更像是硅谷&#xff0c;而不是美国哥特式&#xff0c;拥有控制灌溉的应用程序、驾驶拖拉机的 GPS 系统和监控牲畜的带有 RFID 芯片的耳…

Kotlin 协程1:深入理解withContext

Kotlin 协程1&#xff1a;深入理解withContext 引言 在现代编程中&#xff0c;异步编程已经变得非常重要。在 Kotlin 中&#xff0c;协程提供了一种优雅和高效的方式来处理异步编程和并发。在这篇文章中&#xff0c;我们将深入探讨 Kotlin 协程中的一个重要函数&#xff1a;wi…

中科院国际预警期刊名单发布一周年,共8本期刊被剔除!

据官方消息称&#xff1a;2024年中科院《国际期刊预警名单》将于2024年1月更新&#xff0c;今天已经是2月1号了&#xff0c;距离去年的2023年版《国际期刊预警名单&#xff08;试行&#xff09;》发布已经一周年&#xff0c;在去年被列入预警名单的28本期刊中&#xff0c;截止目…

FPGA高端项目:Xilinx Artix7系列FPGA 多路视频缩放拼接 工程解决方案 提供4套工程源码+技术支持

目录 1、前言版本更新说明给读者的一封信FPGA就业高端项目培训计划免责声明 2、相关方案推荐我这里已有的FPGA图像缩放方案我已有的FPGA视频拼接叠加融合方案本方案的Xilinx Kintex7系列FPGA上的ov5640版本本方案的Xilinx Kintex7系列FPGA上的HDMI版本 3、设计思路框架设计框图…

黑马程序员前端web入门:新浪新闻

黑马程序员前端web入门&#xff1a;新浪新闻 几点学习到的&#xff1a; 设置li无圆点: list-style: none;设置a无下划线&#xff1a;text-decoration: none;a属于行内元素&#xff0c;高度hegiht不起作用&#xff0c;可以设置 display: block; 把它变成块元素。此时&#xff0c…

创新型海外网红合作模式:打破传统,解锁品牌推广新机会

随着社交媒体的普及和全球化的发展&#xff0c;海外网红营销已经成为品牌推广的重要渠道。然而&#xff0c;传统的合作模式往往局限于简单的赞助或广告投放&#xff0c;缺乏深度和创新。为了打破这一局限&#xff0c;品牌需要探索一些创新型的海外网红合作模式&#xff0c;以带…

【简便方法和积累】pytest 单元测试框架中便捷安装插件和执行问题

又来进步一点点~~~ 背景&#xff1a;之前写了两篇关于pytest单元测试框架的文章&#xff0c;本篇内容对之前的做一个补充 一、pytest插件&#xff1a; pytest 有非常多的插件&#xff0c;很方便&#xff0c;以下为插件举例&#xff1a; pytest&#xff0c;pytest-html&#x…

【算法】拦截导弹(线性DP)

题目 某国为了防御敌国的导弹袭击&#xff0c;发展出一种导弹拦截系统。 但是这种导弹拦截系统有一个缺陷&#xff1a;虽然它的第一发炮弹能够到达任意的高度&#xff0c;但是以后每一发炮弹都不能高于前一发的高度。 某天&#xff0c;雷达捕捉到敌国的导弹来袭。 由于该系…

机器学习4-多元线性回归

多元线性回归(Multiple Linear Regression)是线性回归的一种扩展形式&#xff0c;用于建立因变量与多个自变量之间的关系。在简单线性回归中&#xff0c;我们考虑一个因变量和一个自变量之间的线性关系&#xff0c;而多元线性回归允许我们考虑多个自变量对因变量的影响。 一般…

openssl3.2 - .pod文件的查看方法

文章目录 .pod文件的查看方法概述笔记初步的解决方法备注 - pod2html.bat的详细用法好像Perl就自带这个BATEND .pod文件的查看方法 概述 看到openssl源码目录下有很多.pod文件, 软件发布的帮助内容都在里面. 当make install后, 大部分的.pod都会转成html文件, 但是有一部分…

FreeBSD Virtual Box 突然发现只能创建32位系统问题解决

要用 Virtual Box 起kali系统的映像&#xff0c;发现只能创建32位系统&#xff0c;于是百度&#xff0c;得出的结论是BIOS里没有开CPU 虚拟化&#xff0c;进入BIOS将其打开&#xff0c;问题解决。 以前怎么没有注意到这个问题呢&#xff1f; 而且里面有个Ubunut的虚拟&#xff…

Qt扩展-muParser数学公式解析

muParser数学公式解析 一、概述1. 针对速度进行了优化2. 支持的运算符3. 支持的函数4. 用户定义的常量5. 用户定义的变量6. 自定义值识别回调7. 其他功能 二、内置函数三、内置二元运算符四、三元运算符五、内置常量六、源码引入1. 源码文件2. 编译器开关1. MUP_BASETYPE2.MUP_…

机器学习-3降低损失(Reducing Loss)

机器学习-3降低损失(Reducing Loss) 学习内容来自&#xff1a;谷歌ai学习 https://developers.google.cn/machine-learning/crash-course/framing/check-your-understanding?hlzh-cn 本文作为学习记录1.降低损失&#xff1a;迭代方法 迭代学习 下图展示了机器学习算法用于训…

[嵌入式系统-7]:龙芯1B 开发学习套件 -4- LoongIDE 集成开发工具的使用-创建应用程序工程、编译、下载、调试

目录 前言&#xff1a; 步骤1&#xff1a;设置工作工作空间 步骤2&#xff1a;设置工具链 步骤3&#xff1a;创建裸机应用程序 步骤4&#xff1a;创建带实时操作系统的应用程序 步骤5&#xff1a;编译 步骤6&#xff1a;下载调试 前言&#xff1a; LoongIDE集成开发环境…

075:vue+mapbox 利用高德地址逆转换,点击地图,弹出地址信息

第075个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+mapbox中利用高德逆地理编码,点击地图,弹出某点坐标和地址信息。这里要仔细阅读高德地图的逆编码API,同时要注意的是,这种转换在中国很好用,到了欧美国家就不好使了。同时这个底图是天地图的图像和标记。 直接…

第三篇:跨平台QT开发-打包

&#xff08;1&#xff09;设置应用程序图标 https://www.bitbug.net/---->可以做图标 准备好 login.ico 文件&#xff0c;ExamSys.pro 文件中添加如下一行的代码 RC_ICONS login.ico-->图标的名字 找到项目运行的目录把图标拷贝进去(并将项目设置为release模式) 一定要…