卡片覆盖轮播图纯手写

31 篇文章 0 订阅
31 篇文章 0 订阅
  • 非常好用 特性牛逼
<template>
	<view>
		<view :style="{height: height+'rpx'}" class="swiper-container" @touchstart="touchStart" @touchend="touchEnd">
			<view class="swiper-item" v-for="(item, index) in list" :key="index"
				:style="{transform: styleList[index].transform, zIndex: styleList[index].zIndex, opacity: styleList[index].opacity,display:styleList[index].display}">
				<view class="wrap" @click="itemClick(index)">
					<image class="image" :src="item"></image>
				</view>
			</view>
		</view>
		<view class="indication">
			<block v-for="(item,index) in list" :key="index">
				<view class="spot" :class="index == 1? 'active': '' "></view>
			</block>
		</view>
	</view>
</template>

<script>
	export default {
		props: {
			/**
			 * 图片url列表
			 */
			// list: {
			// 	type: Array,
			// 	default: []
			// },
			/**
			 * swiper高度
			 */
			height: {
				type: Number,
				default: 690
			}
		},
		data() {
			return {
				/**
				 * 开始触摸点坐标
				 */
				start: {
					x: 0,
					y: 0
				},
				/**
				 * 每个item样式列表
				 */
				list: [],
				styleList: [],
				timer: null
			};
		},
		async created() {
			await this.getIMG()
			await this.aotoChange()
		},
		methods: {
			async getIMG() {
				const requestPayload2 = {
					name: 'swiper',
					current: 1,
					size: 10
				}
				const retult = await this.$request('/benefit/wx/my/page', this.$PostHeader,
					requestPayload2, 'post')
				if (retult.code !== 200) return
				if (retult.data.records) {
					let arr = retult.data.records[0].photoUrl.split(',')
					this.list = arr.map(v => `${this.$imageUrl}${v}`);
					this.list.forEach((item, index) => {
						this.styleList.push(this.addStyle(index))
					})
				}
			},
			aotoChange() {
				this.timer = setInterval(() => {
					var newStyleList = JSON.parse(JSON.stringify(this.styleList))
					var last = [newStyleList.pop()]
					newStyleList = last.concat(newStyleList)
					this.styleList = newStyleList
				}, 3000)
			},
			/**
			 * 计算每个item样式
			 * @param {Object} idx
			 */
			addStyle(idx) {
				const len = this.list.length;
				if (idx > len / 2) {
					//这里是数组后一半的item放在左边,平移位置由远到近,例如共6个,后2个处理在这里
					var left = len - idx
					return {
						transform: 'scale(' + (1 - left / 5) + ') translate(-' + (left * 18) + '%,0px)',
						zIndex: 99 - left,
						opacity: 0.8 / left,
						display: idx == len - 1 ? "block" : "none"
					}
				} else {
					//这里是数组前一半item放在右边,平移位置由近到远,例如共6个,前4个处理在这里,这里第一个元素始终放在中间位置
					return {
						transform: 'scale(' + (1 - idx / 5) + ') translate(' + (idx * 18) + '%,0px)',
						zIndex: 99 - idx,
						opacity: 0.8 / (idx === 0 ? 0.8 : idx),
						display: idx > 1 ? "none" : "block"
					}
				}
			},
			/**
			 * 触摸开始
			 * @param {Object} e
			 */
			touchStart(e) {
				this.start.x = e.changedTouches[0] ? e.changedTouches[0].pageX : 0;
				this.start.y = e.changedTouches[0] ? e.changedTouches[0].pageY : 0;
				clearInterval(this.timer)
			},
			/**
			 * 触摸结束
			 * @param {Object} e
			 */
			touchEnd(e) {
				var newStyleList = JSON.parse(JSON.stringify(this.styleList))
				let tx = e.changedTouches[0].pageX - this.start.x
				let ty = e.changedTouches[0].pageY - this.start.y
				if (Math.abs(tx) > Math.abs(ty)) {
					//左右方向滑动
					if (tx < 0) {
						// 向左滑动
						var last = [newStyleList.pop()]
						newStyleList = last.concat(newStyleList)
					} else if (tx > 0) {
						// 向右滑动
						newStyleList.push(newStyleList[0])
						newStyleList.splice(0, 1)
					}
				} else {
					//这里就不处理上下方向的事件了,有此需求的同仁可以在这里写逻辑
					//上下方向滑动
					if (ty < 0) {
						// 向上滑动
					} else if (ty > 0) {
						// 向下滑动
					}
				}
				this.styleList = newStyleList
				this.aotoChange()
			},
			/**
			 * 当前item点击返回索引下标
			 * @param {Object} idx
			 */
			itemClick(idx) {
				this.$emit('click', idx);
			}
		}
	}
</script>

<style lang="scss">
	.swiper-container {
		box-sizing: border-box;
		height: 690rpx;
		width: 100%;
		overflow: hidden;
		position: relative;

		.swiper-item {
			height: 100%;
			width: 100%;
			position: absolute;
			top: 0;
			left: 0;
			transition: all .5s;
			padding: 2rpx 0;

			.wrap {
				height: 100%;
				width: 610rpx;
				margin: 0 auto;

				.image {
					height: 100%;
					width: 100%;
					border-radius: 16rpx;
					box-shadow: 0 0 10rpx #333; //加阴影的话去掉注释即可
				}
			}
		}
	}
	
	/* 轮播指示点 start*/
	.indication {
		z-index: 9999;
		width: 100%;
		height: 36rpx;
		position: absolute;
		padding-right: 48rpx;
		display: flex;
		flex-direction: row;
		align-items: center;
		justify-content: center;
	}
	
	.spot {
		background-color: #FF483C;
		opacity: 0.4;
		width: 10rpx;
		height: 10rpx;
		border-radius: 20rpx;
		top: -53rpx;
		margin: 0 8rpx !important;
		position: relative;
	}
	
	.spot.active {
		opacity: 1;
		width: 24rpx;
		background: url('../../static/Stroke.png') no-repeat;
		background-size: contain;
		margin-top: 2rpx !important;
	}
</style>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值