uniapp 实现轮播图(手写Swiper)

108 阅读1分钟

首页禁止左滑 尾页禁止右滑

代码路径

image.png

FSwiper.vue

<template>
	<view class="swiper-wrap">
		<view class="swiper-main" :style="style" @touchstart="startEvent" @touchend="endEvent" @touchmove="moveEvent"
			:class="{ auto: auto }">
			<slot />
		</view>
	</view>
</template>

<script>
	export default {
		name: 'FSwiper',
		props: {
			amount: {
				type: Number,
				default: 1,
			},
		},
		data() {
			return {
				activeIndex: 0,
				windowWidth: 0,
				startX: 0,
				currentX: 0,
			};
		},
		computed: {
			style() {
				let distance =
					this.activeIndex * this.windowWidth - (this.currentX - this.startX);
				if (distance < 0) {
					distance = 0;
				} else if (distance > (this.amount - 1) * this.windowWidth) {
					distance = (this.amount - 1) * this.windowWidth;
				}
				return {
					transform: `translateX(${-distance + 'px'})`,
				};
			},
		},
		methods: {
			startMove() {
				if (this.activeIndex === this.amount - 1) {
					this.activeIndex = 0;
				} else {
					this.activeIndex++;
				}
			},
			startEvent(e) {
				this.startX = e.changedTouches[0].pageX;
				this.currentX = e.changedTouches[0].pageX;
				this.auto = false;
			},
			endEvent(e) {
				if (this.currentX - this.startX < -20) {
					if (this.activeIndex == (this.amount - 1)) {
						return;
					}
					this.activeIndex++;
					this.$emit('IndexChange', this.activeIndex);
				}
				if (this.currentX - this.startX > 20) {
					if (this.activeIndex == 0) {
						return;
					}
					this.activeIndex--;
					this.$emit('IndexChange', this.activeIndex);
				}
				this.startX = 0;
				this.currentX = 0;
				this.auto = true;
			},
			moveEvent(e) {
				this.currentX = e.changedTouches[0].pageX;
			},
		},
		mounted() {
			uni.getSystemInfo({
				success: (res) => {
					this.windowWidth = res.windowWidth;
				},
			});
		},
	};
</script>

<style scoped>
	.swiper-wrap {
		width: 100vw;
		overflow: hidden;
		position: relative;
	}

	.swiper-wrap .swiper-dots {
		position: absolute;
		bottom: 20rpx;
		left: 50%;
		transform: translateX(-50%);
		display: flex;
		align-items: center;
	}

	.swiper-wrap .swiper-dots .dot-item {
		width: 10rpx;
		height: 10rpx;
		background-color: #fff;
		border-radius: 50%;
		margin: 0 5rpx;
		color: transparent;
		overflow: hidden;
	}

	.swiper-wrap .swiper-dots .dot-item.active {
		background-color: #c63427;
	}

	.swiper-wrap .swiper-main {
		display: flex;
		flex-wrap: nowrap;
		align-items: center;
	}

	.swiper-wrap .swiper-main.auto {
		transition: all 0.5s linear;
	}

	.swiper-wrap .swiper-main /deep/>* {
		flex-shrink: 0;
		width: 100vw;
	}
</style>

index.vue

<template>
	<FSwiper ref="BirdSwiperRef" :amount="3" @IndexChange='IndexChange'>
		<view class="" style="background-color: red;height: 300rpx;">
			page1
		</view>
		<view class="" style="background-color: blue;height: 300rpx;">
			page2
		</view>
		<view class="" style="background-color: aqua;height: 300rpx;">
			page3
		</view>
	</FSwiper>
	{{cIndex}}
</template>

<script>
	import FSwiper from "../../components/FSwiper/FSwiper.vue"
	export default {
		components: {
			FSwiper
		},
		data() {
			return {
				cIndex: 0
			}
		},
		mounted() {
			
		},
		methods: {
			IndexChange(index) {
				this.cIndex = index;
			}
		}
	}
</script>

<style>
</style>

截图

image.png

ext.dcloud.net.cn/plugin?id=1…