uniapp中使用swiper实现详情页面轮播图动态高度,实现仿某红薯图片展示轮播图效果。

0、废话部分可以不看

        

在用uniapp开发小程序过程中,想写一个某红薯详情页面的轮播图,开始用来uview3的swiper组件,非常简洁。但是,存在图片显示不完全或者很小,或者又不能很美观。因为什么呢?

主要是图片原尺寸基本上都是9:16或者16:9的比例,想要按比例将图片显示完整,尽可能效果好点试了很多方式,都不能很好的按照图片高度动态一个最大值设置为swiper高度。总有显示不完整的情况。就很丑。记得当时这个height属性弄得我很麻烦。看官方图

二、最终方案:uniapp的swiper

直接上代码:

1、详情 detail.vue 页面:      

:style="{height: swiperHeight + 'px'}"  //该属性用来动态绑定计算后的swiper高度

其他属性参考官方:https://uniapp.dcloud.net.cn/component/swiper.html

mode="widthFix"是图片的裁剪方式  

定义看官方:https://uniapp.dcloud.net.cn/component/image.html

           

<template>
	<view class="container">
		<swiper class="swiper-box" :style="{height: swiperHeight + 'px'}" :indicator-dots="indicatorDots"
			:autoplay="autoplay" :interval="interval" :duration="duration">
			<swiper-item class="swiper-item" v-for="(item, index) in swiperItem" :key="index">
				<image class="image" :src="item.image" mode="widthFix" @load="onImageLoad($event, item)" />
			</swiper-item>
		</swiper>
	</view>
</template>

<script>
import { mapState } from 'vuex';

export default {
	// name: 'DetailPage',
	computed: {
		...mapState(['list', 'swiperItem']),

		indicatorDots() {
			return true;
		},
		autoplay() {
			return true;
		},
		interval() {
			return 3000;
		},
		duration() {
			return 500;
		},
	},
	data() {
		return {
			imagesInfo: [], // 存储所有图片尺寸信息的数组
			portraitImages: [], // 存储竖屏图片信息的数组
			imagesLoadedCount: 0, // 已加载图片的数量
			swiperHeight: 0, // 计算后的最高竖屏图片的高度
		};
	},
	methods: {
		onImageLoad(event, item) {
			const detail = event.detail;
			const { width, height } = detail;
			const entry = {
				url: item.image,
				width,
				height,
				aspectRatio: height / width,
			};
			this.imagesInfo.push(entry);

			// 检查是否为竖屏比例
			if (entry.aspectRatio > 1) {
				this.portraitImages.push(entry);
			}

			console.log('高宽:', entry.height, entry.width);

			this.imagesLoadedCount++;
			if (this.imagesLoadedCount === this.list.length) {
				this.calculateAveragePortraitHeight();
			}
		},
		calculateAveragePortraitHeight() {
			if (this.portraitImages.length === 0) {
				console.warn('没有竖屏图片');
				return;
			}

			const totalHeight = this.portraitImages.reduce((sum, image) => sum + image.height, 0);
			const averageHeight = totalHeight / this.portraitImages.length;

			const {
				windowWidth
			} = uni.getSystemInfoSync(); // 这里可能需要改为异步调用
			console.log("屏幕宽度:", windowWidth); // 输出屏幕宽度

			this.swiperHeight = Math.round((averageHeight * windowWidth) / this.portraitImages[0].width);
			console.log("计算后swiper高度:", this.swiperHeight); // 计算后swiper高度
		},
	},
	mounted() {
		// 在这里可以监听窗口大小变化等操作
	},
	beforeDestroy() {
		// 清除标记
	}
};
</script>

<style>
.container {
	width: 100%;
	position: relative;
}

.swiper {
	width: 100%;
	height: 500px; /* 使用计算属性 */
}

.image {
	width: 100%;
	height: auto;
}
</style>
...mapState(['list']),//这是导入store中的list数组。只有list一个数组用这句就行。

...mapState(['list','swiperItem']),//这是导入store中的list数组,和swiperItem。

大致实现逻辑思路

method里面的内容,大致逻辑是:

      加载数组图片,并将图片的宽高信息储存,判断是不是竖屏的图片类型。

                是,将其图片高度储存在一个新数组。

                找出竖屏图片数组中高度最高的图片的宽高,用于计算是swiper的最终高度,使其能够以最大高度显示完整图片,比起尺寸小的图片也能显示完整。

计算逻辑:

这里swiper可以理解为屏幕,即屏幕宽高。

swiper高度                    swiper宽度 

——————     =    ———————

原图高度                        原图宽度

                           

                                swiper宽度 *原图高度

swiper高度   =     ———————

                                 原图宽度

     

const {windowWidth} = uni.getSystemInfoSync();
				console.log("屏幕宽度:", windowWidth); // 输出屏幕宽度

这句用来获取屏幕宽度,也就是swiper的宽度。

2、需要的数组:list

        list数组定义在vuex也就是uniapp的store中 ,上完整代码:

import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex); // Vue 的插件机制

// Vuex.Store 构造器选项
const store = new Vuex.Store({
	state: {
		// 图片数组
            //下方的连接是cdn图片地址,cdn图片可以自行搜索。
		list: [
			{ image: 'https://xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.jpg' },
			{ image: 'https://xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.jpg'},
			{ image: 'https://xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.jpg' },
			{ image: 'https://xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.jpg' },
			{ image: 'https://xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.jpg' },
		]
	},
	mutations: {},
	actions: {},
	
});

export default store;

思路二:

取竖屏图片数组高度的平均值作为swiper的高度。(推荐)

这样对于一组图片,显示效果会

<template>
	<view class="container">
		<!-- 该页面逻辑将竖屏图片数组高度的平均值作为容器高度 -->
		<swiper class="swiper-box" :style="{height: swiperHeight + 'px'}" :indicator-dots="indicatorDots"
			:autoplay="autoplay" :interval="interval" :duration="duration">
			<swiper-item class="swiper-item" v-for="(item, index) in swiperItem" :key="index">
				<image class="image" :src="item.image" mode="widthFix" @load="onImageLoad($event, item)" />
			</swiper-item>
		</swiper>
	</view>
</template>

<script>
import { mapState } from 'vuex';

export default {
	// name: 'DetailPage',
	computed: {
		...mapState(['list', 'swiperItem']),

		indicatorDots() {
			return true;
		},
		autoplay() {
			return true;
		},
		interval() {
			return 3000;
		},
		duration() {
			return 500;
		},
	},
	data() {
		return {
			imagesInfo: [], // 存储所有图片尺寸信息的数组
			portraitImages: [], // 存储竖屏图片信息的数组
			imagesLoadedCount: 0, // 已加载图片的数量
			swiperHeight: 0, // 计算后的最高竖屏图片的高度
		};
	},
	methods: {
		onImageLoad(event, item) {
			const detail = event.detail;
			const { width, height } = detail;
			const entry = {
				url: item.image,
				width,
				height,
				aspectRatio: height / width,
			};
			this.imagesInfo.push(entry);

			// 检查是否为竖屏比例
			if (entry.aspectRatio > 1) {
				this.portraitImages.push(entry);
			}

			console.log('高宽:', entry.height, entry.width);

			this.imagesLoadedCount++;
			if (this.imagesLoadedCount === this.list.length) {
				this.calculateAveragePortraitHeight();
			}
		},
		calculateAveragePortraitHeight() {
			if (this.portraitImages.length === 0) {
				console.warn('没有竖屏图片');
				return;
			}

			const totalHeight = this.portraitImages.reduce((sum, image) => sum + image.height, 0);
			const averageHeight = totalHeight / this.portraitImages.length;

			const {
				windowWidth
			} = uni.getSystemInfoSync(); // 这里可能需要改为异步调用
			console.log("屏幕宽度:", windowWidth); // 输出屏幕宽度

			this.swiperHeight = Math.round((averageHeight * windowWidth) / this.portraitImages[0].width);
			console.log("计算后swiper高度:", this.swiperHeight); // 计算后swiper高度
		},
	},
	mounted() {
		// 在这里可以监听窗口大小变化等操作
	},
	beforeDestroy() {
		// 清除标记
	}
};
</script>

<style>
.container {
	width: 100%;
	position: relative;
}

.swiper {
	width: 100%;
	height: 500px; /* 使用计算属性 */
}

.image {
	width: 100%;
	height: auto;
}
</style>

好很多。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值