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

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

话不多说,上效果

代码已开源,可参考源码图片资源加载部分。

github地址:https://github.com/jiwaiwai-loading/h5-editor

开源项目说明查看上一篇文章:耗时半年,开源了我精心开发的html5编辑器,可通过拖拉拽生成漂亮的HTML页面。

以下是这部分的核心代码。

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;}

代码简单,定制化强,不妨试试。

原创文章,作者:网络技术联盟站,如若转载,请注明出处:https://www.sudun.com/ask/49756.html

(0)
网络技术联盟站's avatar网络技术联盟站
上一篇 2024年5月16日 下午12:52
下一篇 2024年5月16日 下午12:54

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注