uniapp瀑布流组件
·
组件components>waterfallFlow>waterfallFlow
<template>
<view>
<view class="flow-box" :style="'height: ' + loadingTop + 'rpx'" ref="flow_box">
<!-- <empty v-if="newList.length === 0"></empty> -->
<empty v-show="isShowEmpty"></empty>
<view v-for="(item, index) in newList" :key="item.ProductId" class="item good_item"
v-show="positionList[item.ProductId].imageLoad"
:class="positionList[item.ProductId].right ? 'right' : 'left'"
:style="{top: positionList[item.ProductId].top + 'rpx'}" @click="onPageJump(item.ProductId)">
<view class="goods_img">
<image :data-id="item.ProductId" @load="onImageLoad" :src="item.MainImageUrl_Real" mode="widthFix" @error="imgerror($event, index)">
</image>
</view>
<view class="title">{{ item.ProductName }}</view>
<!-- <view class="goods_cont">{{item.Desc}}</view> -->
<!-- <view class="club" v-if="item.type">
<text class="goods_money_old">原价 ¥{{item.MinPrice}} </text>
<view class="goods_money members">
<text class="members_bg">VIP</text> ¥ {{item.MemberPrice}}
</view>
</view>
<view v-else class="goods_money">原价¥ {{item.MinPrice}}</view> -->
<view class="club">
<text class="goods_money_old">原价¥{{item.MinPrice}} </text>
<view class="goods_money members">
<text class="members_bg">高级会员</text> ¥{{item.MemberPrice}}
</view>
</view>
</view>
</view>
</view>
</template>
<script>
const defaultData = {
// 起始距离(rpx)
startTop: 0,
// 除了图片和标题以外的高度(rpx)
// contentHeight: 20 + 22 + 20 + 20 + 20 + 10,
contentHeight: 112,
// 瀑布流容器宽度(rpx)
viewWidth: 350,
// 标题可显示宽度(rpx)
titleWidth: 300,
// 标题文字大小(rpx)
titleSize: 28,
// 容器之间的间隔Y轴(rpx)
viewSpace: 16,
// 列表ID参数名称
idName: "ProductId",
// 列表标题参数名称
titleName: "ProductName",
};
// 文字换行计算行数
function drawtext(text, maxWidth) {
// console.log(text)
let textArr = text.split("");
let len = textArr.length;
// 上个节点
let previousNode = 0;
// 记录节点宽度
let nodeWidth = 0;
// 文本换行数组
let rowText = [];
// 如果是字母,侧保存长度
let letterWidth = 0;
// 汉字宽度
let chineseWidth = defaultData.titleSize;
// otherFont宽度
let otherWidth = defaultData.titleSize / 2;
for (let i = 0; i < len; i++) {
if (/[\u4e00-\u9fa5]|[\uFE30-\uFFA0]/g.test(textArr[i])) {
if (letterWidth > 0) {
if (nodeWidth + chineseWidth + letterWidth * otherWidth > maxWidth) {
rowText.push({
type: "text",
content: text.substring(previousNode, i)
});
previousNode = i;
nodeWidth = chineseWidth;
letterWidth = 0;
} else {
nodeWidth += chineseWidth + letterWidth * otherWidth;
letterWidth = 0;
}
} else {
if (nodeWidth + chineseWidth > maxWidth) {
rowText.push({
type: "text",
content: text.substring(previousNode, i)
});
previousNode = i;
nodeWidth = chineseWidth;
} else {
nodeWidth += chineseWidth;
}
}
} else {
if (/\n/g.test(textArr[i])) {
rowText.push({
type: "break",
content: text.substring(previousNode, i)
});
previousNode = i + 1;
nodeWidth = 0;
letterWidth = 0;
} else if (textArr[i] == "\\" && textArr[i + 1] == "n") {
rowText.push({
type: "break",
content: text.substring(previousNode, i)
});
previousNode = i + 2;
nodeWidth = 0;
letterWidth = 0;
} else if (/[a-zA-Z0-9]/g.test(textArr[i])) {
letterWidth += 1;
if (nodeWidth + letterWidth * otherWidth > maxWidth) {
rowText.push({
type: "text",
content: text.substring(previousNode, i + 1 - letterWidth)
});
previousNode = i + 1 - letterWidth;
nodeWidth = letterWidth * otherWidth;
letterWidth = 0;
}
} else {
if (nodeWidth + otherWidth > maxWidth) {
rowText.push({
type: "text",
content: text.substring(previousNode, i)
});
previousNode = i;
nodeWidth = otherWidth;
} else {
nodeWidth += otherWidth;
}
}
}
}
if (previousNode < len) {
rowText.push({
type: "text",
content: text.substring(previousNode, len)
});
}
return rowText.length;
}
let allow = true;
export default {
props: {
// 数据列表
list: {
type: Array,
default () {
return [];
}
}
},
data() {
return {
isShowEmpty: false,
newList: [],
positionList: {},
loadingTop: 0,
leftHistoryTop: 0,
rightHistoryTop: 0,
imgUrl: this.$imgUrl,
};
},
watch: {
// 数据
list: function(newVal, oldVal) {
// console.log(newVal)
if (newVal.length === 0) {
this.newList = [];
this.isShowEmpty = true;
} else {
this.isShowEmpty = false;
this.newList = newVal;
this.getCalculationPosition();
}
},
},
methods: {
imgerror(e, index) {
// console.log('this.newList++++++++',this.newList)
this.newList[index].MainImageUrl_Real="https://image.zhihewei.club/FileServer/File/static/logo/zhiwei.png";
console.log('this.newList[index]----------------',this.newList[index])
// this.newList.splice(index, 1)
// this.newList.splice(index, 0, '@/static/logo.png')
},
onPageJump(id) {
console.log(id)
this.$emit('onPageJump', id);
uni.navigateTo({
url: '../details/details2?id=' + id
})
},
refreshData() {},
// 节流
throttle(callback, time = 400) {
if (!allow) return false;
allow = false;
setTimeout(function() {
allow = true;
callback();
}, time);
},
// 获取数据位置信息 top,right
getCalculationPosition() {
let leftHistoryTop = defaultData.startTop;
let rightHistoryTop = defaultData.startTop;
let positionList = this.positionList;
// console.log(positionList)
this.newList.forEach((item, index) => {
// console.log(item)
let currentHeight = '';
if (item.type) {
currentHeight = defaultData.contentHeight + 60;
} else {
currentHeight = defaultData.contentHeight + 60;
}
// console.log(currentHeight)
// console.log(currentHeight)
let positionItem = {};
// 查看是否有位置数据
// console.log(positionList[item[defaultData.idName]])
if (positionList[item[defaultData.idName]]) {
positionItem = positionList[item[defaultData.idName]];
} else {
positionList[item[defaultData.idName]] = {};
}
// console.log(positionItem)
// 查看是否有图片高度数据,没有默认等宽
// console.log(positionItem.imageHeight)
if (positionItem.imageHeight) {
currentHeight += positionItem.imageHeight;
positionList[item[defaultData.idName]].imageLoad = true;
} else {
currentHeight += defaultData.viewWidth;
}
// 查看是否有标题高度数据,没有获取高度
if (positionItem.titleHeight) {
currentHeight += positionItem.titleHeight;
} else {
let titleListLen = drawtext(item[defaultData.titleName], defaultData.titleWidth);
titleListLen = titleListLen > 2 ? 2 : titleListLen;
positionList[item[defaultData.idName]].titleHeight = titleListLen * (defaultData
.titleSize + 6);
currentHeight += titleListLen * (defaultData.titleSize + 6);
}
if (leftHistoryTop > rightHistoryTop) {
positionList[item[defaultData.idName]].top = rightHistoryTop;
positionList[item[defaultData.idName]].right = true;
positionList[item[defaultData.idName]].height = currentHeight;
rightHistoryTop += currentHeight + defaultData.viewSpace;
} else {
positionList[item[defaultData.idName]].top = leftHistoryTop;
positionList[item[defaultData.idName]].right = false;
positionList[item[defaultData.idName]].height = currentHeight;
leftHistoryTop += currentHeight + defaultData.viewSpace;
}
});
if (leftHistoryTop > rightHistoryTop) {
this.loadingTop = leftHistoryTop;
} else {
this.loadingTop = rightHistoryTop;
}
this.positionList = positionList;
this.$forceUpdate();
},
// 图片加载完成
onImageLoad(e) {
// console.log(e)
let id = e.currentTarget.dataset.id;
let scale = defaultData.viewWidth / e.detail.width;
let height = scale * e.detail.height;
// console.log(scale)
// console.log(height)
// console.log(this.positionList[id])
if (this.positionList[id]) {
this.positionList[id].imageHeight = height;
} else {
this.positionList[id] = {
imageHeight: height
}
}
// 图片加载完刷新位置节流一下,提升性能
this.throttle(() => {
this.getCalculationPosition();
}, 100);
}
}
};
</script>
<style lang="scss">
@import '@/style/mixin.scss';
.flow-box {
position: relative;
color: #1a1a1a;
box-sizing: content-box;
top: -10rpx;
}
.flow-box .left {
left: 12rpx;
}
.flow-box .right {
right: 12rpx;
}
.flow-box .good_item {
box-sizing: border-box;
position: absolute;
width: 358rpx;
border: 2rpx solid #f9f9f9;
background: #fff;
border-radius: 8rpx;
overflow: hidden;
&.noMargin {
margin-right: 0;
}
.goods_img {
padding-bottom: 20rpx;
image {
width: 100%;
display: block;
}
}
.goods_cont {
padding: 0 20rpx;
font-size: 24rpx;
color: #666;
line-height: 36rpx;
text-overflow: -o-ellipsis-lastline;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
line-clamp: 2;
-webkit-box-orient: vertical;
}
.title {
font-size: 26rpx;
padding: 0 20rpx;
color: #333333;
font-size: 28rpx;
@include bov(2);
}
.goods_money {
padding: 20rpx 20rpx;
font-size: 28rpx;
color: $my-font-color;
font-weight: 800;
}
.goods_money_old {
color: #717171;
text-decoration: line-through;
padding-left: 30rpx;
padding-top: 20rpx;
font-size: 20rpx;
}
.club {
padding-top: 20rpx;
.members {
display: flex;
align-items: center;
padding-left: 30rpx;
font-weight: 500;
.members_bg {
width: 84rpx;
height: 26rpx;
line-height: 24rpx;
text-align: center;
background: linear-gradient(to right, $my-left-btn-color, $my-right-btn-color);
color: #fff;
font-size: 16rpx;
padding: 0;
border-top-left-radius: 14rpx;
border-bottom-right-radius: 14rpx;
text {
font-weight: normal;
}
}
}
}
}
</style>
style>mixin.scss
@charset "utf-8";
//主题色
$themeColor: #ea552d;
@mixin theme($type,$path:''){
@if $type == "btn_bg" {
background-image: linear-gradient(90deg, #ea552d 0%, #f19837 100%);
} @else if $type == "unselected_img" {
background-image: url($path + "static/icon/ic_gender_unselected.png");
} @else if $type == "check_img" {
background-image: url($path + "static/icon/ic_agreed.png");
} @else if $type == "radio_img" {
background-image: url($path + "static/icon/ic_gender_selected.png");
}
}
// 背景图片地址和大小
@mixin bis($url, $size: cover) {
background-image: url($url);
background-repeat: no-repeat;
background-position: center center;
background-size: $size;
}
// 头像
@mixin ic($width, $height) {
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
flex-shrink: 0;
width: $width;
height: $height;
}
// 单行省略号
@mixin toe() {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap
}
// 多行省略号
@mixin bov($num:2) {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: $num;
-webkit-box-orient: vertical;
}
更多推荐



所有评论(0)