原理很简单,计算图片的宽高,再计算每列的使用高度,然后再将当前图片放置在列高最小的一列。其实这种方式使用什么方式布局都无所谓,我使用的是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