You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

124 lines
4.6 KiB

<template>
<view class="waterfalls-box" :style="{ height: height + 'px' }">
<view
v-for="(item, index) of list"
class="waterfalls-list"
:key="item[idKey]"
:id="'waterfalls-list-id-' + item[idKey]"
:ref="'waterfalls-list-id-' + item[idKey]"
:style="{
'--offset': offset + 'px',
'--cols': cols,
top: allPositionArr[index] ? allPositionArr[index].top : 0,
left: allPositionArr[index] ? allPositionArr[index].left : 0,
}"
@click="goto" :data-url="'/pagesA/article/detail?id='+item[idKey]"
>
<image
class="waterfalls-list-image"
mode="widthFix"
:style="imageStyle"
:src="item[imageSrcKey] || ' '"
@load="imageLoadHandle(index)"
@error="imageLoadHandle(index)"
/>
<view class="article-waterfall-info">
<view class="p1">{{item.name}}</view>
<view class="p2">
<text style="overflow:hidden" class="flex1" v-if="showtime=='1'">{{item.createtime}}</text>
<text style="overflow:hidden" v-if="showreadcount=='1'">阅读 {{item.readcount}}</text>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
props: {
list: { type: Array, required: true },
// offset 间距,单位为 px
offset: { type: Number, default: 8 },
// 列表渲染的 key 的键名,值必须唯一,默认为 id
idKey: { type: String, default: "id" },
// 图片 src 的键名
imageSrcKey: { type: String, default: "pic" },
// 列数
cols: { type: Number, default: 2, validator: (num) => num >= 2 },
imageStyle: { type: Object },
showtime: {type: String, default: "1" },
showreadcount: {type: String, default: "1" }
},
data() {
return {
topArr: [], // left, right 多个时依次表示第几列的数据
allPositionArr: [], // 保存所有的位置信息
allHeightArr: [], // 保存所有的 height 信息
height: 0, // 外层包裹高度
oldNum: 0,
num: 0,
};
},
created() {
this.refresh();
},
methods: {
imageLoadHandle(index) {
const id = "waterfalls-list-id-" + this.list[index][this.idKey],
query = uni.createSelectorQuery().in(this);
query
.select("#" + id)
.fields({ size: true }, (data) => {
this.num++;
//console.log(data.height);
this.$set(this.allHeightArr, index, data.height);
if (this.num === this.list.length) {
for (let i = this.oldNum; i < this.num; i++) {
const getTopArrMsg = () => {
let arrtmp = [...this.topArr].sort((a, b) => a - b);
return {
shorterIndex: this.topArr.indexOf(arrtmp[0]),
shorterValue: arrtmp[0],
longerIndex: this.topArr.indexOf(arrtmp[this.cols - 1]),
longerValue: arrtmp[this.cols - 1],
};
};
const { shorterIndex, shorterValue } = getTopArrMsg();
const position = {
top: shorterValue + "px",
left: (data.width + this.offset) * shorterIndex + "px",
};
this.$set(this.allPositionArr, i, position);
this.topArr[shorterIndex] =
shorterValue + this.allHeightArr[i] + this.offset;
this.height = getTopArrMsg().longerValue - this.offset;
}
this.oldNum = this.num;
// 完成渲染 emit `image-load` 事件
this.$emit("image-load");
}
})
.exec();
},
refresh() {
let arr = [];
for (let i = 0; i < this.cols; i++) {
arr.push(0);
}
this.topArr = arr;
this.num = 0;
this.oldNum = 0;
this.height = 0;
},
},
};
</script>
<style scoped>
.waterfalls-box {position: relative;width: 100%;overflow: hidden;}
.waterfalls-box .waterfalls-list {width: calc((100% - var(--offset) * (var(--cols) - 1)) / var(--cols));position: absolute;background-color: #fff;border-radius: 8rpx;left: calc(-50% - var(--offset));}
.waterfalls-box .waterfalls-list .waterfalls-list-image {width: 100%;will-change: transform;border-radius:8rpx 8rpx 0 0;display: block;}
.article-waterfall-info{padding:10rpx 20rpx 20rpx 20rpx;display:flex;flex-direction:column;}
.article-waterfall-info .p1{color:#222222;font-weight:bold;font-size:28rpx;line-height:46rpx;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden;}
.article-waterfall-info .p2{flex-grow:0;flex-shrink:0;display:flex;align-items:center;padding-top:10rpx;font-size:24rpx;color:#a88;overflow:hidden}
</style>