fix: water-fall image list

This commit is contained in:
ShawnPhang 2023-10-03 23:02:26 +08:00
parent 91213c4f97
commit 4467227b47

View File

@ -2,15 +2,15 @@
* @Author: ShawnPhang
* @Date: 2021-12-16 16:20:16
* @Description: 瀑布流组件
* @LastEditors: ShawnPhang <site: book.palxp.com>
* @LastEditTime: 2023-07-06 17:58:49
* @LastEditors: ShawnPhang <https://m.palxp.cn>
* @LastEditTime: 2023-10-03 22:58:32
-->
<template>
<div ref="imgWaterFall" :style="{ height: countHeight + 'px' }" class="img-water-fall">
<!-- backgroundImage: `url(${item.cover})` -->
<div v-for="(item, index) in list" :key="index + 'iwf'" :style="{ top: item.top + 'px', left: item.left + 'px', width: width + 'px', height: item.height + 'px' }" class="img-box" @click.stop="selectItem(item, index)">
<v-lazy-image v-if="!item.fail" class="img" @error="loadError(item)" :src="item.cover" />
<div class="fail_img" v-else>{{ item.title }}</div>
<v-lazy-image v-if="!item.fail" class="img" :src="item.cover" @error="loadError(item)" />
<div v-else class="fail_img">{{ item.title }}</div>
</div>
</div>
</template>
@ -18,12 +18,9 @@
<script>
import vLazyImage from 'v-lazy-image'
const NAME = 'img-water-fall'
// import api from '@/api/album'
const columnHeights = [] //
const columnNums = 2 //
const gap = 7 //
import { defineComponent, toRefs, reactive, watch } from 'vue'
export default {
export default defineComponent({
name: NAME,
components: { vLazyImage },
props: {
@ -31,63 +28,65 @@ export default {
type: Array,
required: true,
},
// scroll: {
// default: true,
// },
},
emits: ['select', 'load'],
data() {
return {
setup(props, { emit }) {
const state = reactive({
width: 146, //
list: [],
countHeight: 0,
})
const columnHeights = [] //
const columnNums = 2 //
const gap = 7 //
watch(
() => props.listData,
() => {
columnHeights.length = 0
const widthLimit = state.width * columnNums // + gap * (columnNums - 1) // 每行宽度
const cloneList = JSON.parse(JSON.stringify(props.listData))
for (let i = 0; i < cloneList.length; i++) {
let index = i % columnNums
const item = cloneList[i]
item.height = (item.height / item.width) * state.width //
item.left = index * (widthLimit / columnNums + gap) //
item.top = columnHeights[index] + gap || 0 //
// columnHeights[index] = isNaN(columnHeights[index]) ? item.height : item.height + columnHeights[index] + gap //
//
if (isNaN(columnHeights[index])) {
columnHeights[index] = item.height
} else {
index = columnHeights.indexOf(Math.min(...columnHeights))
item.left = index * (widthLimit / columnNums + gap)
item.top = columnHeights[index] + gap || 0
columnHeights[index] = item.height + columnHeights[index] + gap
}
}
state.countHeight = Math.max(...columnHeights)
state.list = cloneList
},
)
const load = () => {
emit('load')
}
const selectItem = (value, index) => {
emit('select', value)
}
const loadError = (item) => {
item.fail = true
}
return {
...toRefs(state),
load,
selectItem,
loadError,
}
},
// async mounted() {
// },
watch: {
listData() {
columnHeights.length = 0
const widthLimit = this.width * columnNums // + gap * (columnNums - 1) // 每行宽度
const cloneList = JSON.parse(JSON.stringify(this.listData))
let lineWidth = 0
let index = 0
for (let i = 0; i < cloneList.length; i++) {
const item = cloneList[i]
const r = item.width / this.width
item.height = item.height / r
lineWidth += this.width
if (lineWidth >= widthLimit) {
index++
item.left = this.width + gap
item.top = columnHeights[index] + gap || 0
columnHeights[index] = typeof columnHeights[index] === 'number' ? item.height + columnHeights[index] + gap : item.height
// init
lineWidth = 0
index = 0
} else {
item.top = columnHeights[index] + gap || 0
item.left = 0
columnHeights[index] = typeof columnHeights[index] === 'number' ? item.height + columnHeights[index] + gap : item.height
}
}
this.countHeight = Math.max(...columnHeights)
this.list = cloneList
},
},
methods: {
load() {
this.$emit('load')
},
selectItem(value, index) {
this.$emit('select', value)
},
loadError(item) {
item.fail = true
},
},
}
})
</script>
<style lang="less" scoped>