Anti-Gold/Bubble Mart box drawer sliding pop-up layer uniapp slide-popup

insert image description here
insert image description here
insert image description here
insert image description here

components

<template>
	<view class="panel"  v-touch:swipeup="swipeup" v-touch:swipedown="swipedown" @touchmove.prevent @mousewheel.prevent :style="{ height: `${height}px` }" :class="{ search_radius: !isScroll }">
		<view class="tapBoxTouchLine" v-if="showLine" @click.stop="clickSwipe">
			<slot name="header"></slot>
		</view>
		<view class="panel_content" style="overflow: hidden;">
			<scroll-view  scroll-y="true" :style="{ height: `${height-80}px` }">
				<slot></slot>
			</scroll-view>
		</view>
	</view>
</template>

<script>
/**
 * slidePopup 防高德滑动弹出层
 * @minHeight 最小高度
 * @middleHeight 二级高度
 * @maxHeight 最大高度
 * @clickSwipe (header插槽/点击开启/关闭事件)
 */
export default {
      
      
	props: {
      
      
		minHeight: {
      
       
			type: Number,
			default: 70
		},
		middleHeight: {
      
      
			type: Number,
			default: 600
		},
		maxHeight:{
      
      
			type: Number,
			default: 800
		},
		showLine: {
      
      
			type: Boolean,
			default: true
		}
	},
	data() {
      
      
		return {
      
      
			maxHeight: 400,
			height: 70, //默认高度
			lastY: 0,
			isScroll: false,
			swipeShow: false
		};
	},
	created() {
      
      
		const info = uni.getSystemInfoSync();
		// console.log(info)
		this.maxHeight = info.windowHeight;
		console.log(this.maxHeight);
	},
	directives: {
      
      
		//滑动指令
		touch: {
      
      
			bind: function(el, binding, vnode) {
      
      
				var touchType = binding.arg; //传入的模式 press swipeRight swipeLeft swipeTop swipeDowm Tap
				var timeOutEvent = 0;
				var direction = '';
				//滑动处理
				var startX, startY;

				//返回角度
				function GetSlideAngle(dx, dy) {
      
      
					return (Math.atan2(dy, dx) * 180) / Math.PI;
				}

				//根据起点和终点返回方向 1:向上,2:向下,3:向左,4:向右,0:未滑动
				function GetSlideDirection(startX, startY, endX, endY) {
      
      
					var dy = startY - endY;
					var dx = endX - startX;
					var result = 0;

					//如果滑动距离太短
					if (Math.abs(dx) < 2 && Math.abs(dy) < 2) {
      
      
						return result;
					}

					var angle = GetSlideAngle(dx, dy);
					if (angle >= -45 && angle < 45) {
      
      
						result = 'swiperight';
					} else if (angle >= 45 && angle < 135) {
      
      
						result = 'swipeup';
					} else if (angle >= -135 && angle < -45) {
      
      
						result = 'swipedown';
					} else if ((angle >= 135 && angle <= 180) || (angle >= -180 && angle < -135)) {
      
      
						result = 'swipeleft';
					}
					return result;
				}

				el.addEventListener(
					'touchstart',
					function(ev) {
      
      
						startX = ev.touches[0].pageX;
						startY = ev.touches[0].pageY;

						//判断长按
						timeOutEvent = setTimeout(() => {
      
      
							timeOutEvent = 0;
							if (touchType === 'press') {
      
      
								binding.value();
							}
						}, 500);
					},
					false
				);

				el.addEventListener('touchmove', function(ev) {
      
      
					clearTimeout(timeOutEvent);
					timeOutEvent = 0;
				});

				el.addEventListener(
					'touchend',
					function(ev) {
      
      
						var endX, endY;
						endX = ev.changedTouches[0].pageX;
						endY = ev.changedTouches[0].pageY;
						direction = GetSlideDirection(startX, startY, endX, endY);

						clearTimeout(timeOutEvent);

						switch (direction) {
      
      
							case 0:
								break;
							case 'swipeup':
								if (touchType === 'swipeup') {
      
      
									binding.value();
								}
								break;
							case 'swipedown':
								if (touchType === 'swipedown') {
      
      
									binding.value();
								}
								break;
							case 'swipeleft':
								if (touchType === 'swipeleft') {
      
      
									binding.value();
								}
								break;
							case 'swiperight':
								if (touchType === 'swiperight') {
      
      
									binding.value();
								}
								break;
							default:
						}
					},
					false
				);
			}
		}
	},
	
	methods: {
      
      
		swipeup() {
      
      
			this.swipeShow = true
			 this.$emit('swipeClick',this.swipeShow)
			if (this.height < this.middleHeight) {
      
      
				this.height = this.middleHeight;
				this.isScroll = false;
			} else {
      
      
				this.height = this.maxHeight;
				this.isScroll = true;
			}
		},
		swipedown() {
      
      
			this.swipeShow = false
			 this.$emit('swipeClick',this.swipeShow)
			if (this.height < this.middleHeight) {
      
      
				this.height = this.middleHeight;
				this.isScroll = false;
			} else {
      
      
				this.height = this.minHeight;
				this.isScroll = false;
			}
		},
		clickSwipe(){
      
      
			if(this.height > this.minHeight){
      
      
				this.swipedown()
			}else{
      
      
				this.swipeup()
			}
			
		}
	}
};
</script>

<style lang="scss">
.panel {
      
      
	z-index: 999;
	position: fixed;
	bottom: 0;
	width: 100vw;
	background-color: #ffffff;
	padding: 0 20rpx 30rpx;
	box-sizing: border-box;
	display: flex;
	flex-direction: column;
	justify-content: flex-start;
	align-items: center;
	transition-duration: 0.5s;
	.search_wrapper {
      
      
		display: flex;
		justify-content: center;
		align-items: center;
		width: 100%;
		margin-bottom: 20rpx;

		.search_content {
      
      
			height: 74rpx;
			width: 100%;
			display: flex;
			justify-content: space-between;
			align-items: center;
			background-color: #ebf0f3;
			border-radius: 16rpx;
			border: 1rpx solid #dfe4e7;
			padding: 0 20rpx;

			.search_content_input {
      
      
				flex: 1;
				display: flex;
				justify-content: flex-start;
				align-items: center;

				.search_icon {
      
      
					margin-right: 10rpx;
				}

				.search_text {
      
      
					color: #595e5f;
					font-size: 32rpx;
					letter-spacing: 1.8rpx;
				}
			}

			.search_suffix {
      
      
				width: 48rpx;
				height: 48rpx;

				image {
      
      
					width: 100%;
					height: 100%;
				}
			}
		}
	}

	.panel_content {
      
      
		width: 100%;
		height: 100%;
	}
}

.search_radius {
      
      
	border-radius: 50rpx 50rpx 0 0;
	box-shadow: 0 -8rpx 30rpx rgba(109, 109, 109, 0.1);
}
</style>

use

<template>
	<view class="">
		<slide-popup :minHeight="70" :middleHeight="600" :showLine="true" @swipeClick="swipeClick">
			<view class="tapBoxTouchLine" slot="header">
				<view class="line"></view>
				<view class="title">{
   
   { markShow ? '返回趣味抽盒' : '获取更多游戏机会' }}</view>
				<view class="text-tw">任务中心</view>
			</view>
			<view class="mission-center">
				<image src="../../static/carton-drawer/banner.png" mode=""></image>
				<view class="">
					<view class="mission-board-li" v-for="item in missionList">
						<view class="h3">{
   
   { item.texth }}</view>
						<view class="task-list" v-for="i in item.taskList">
							<image :src="i.url" mode=""></image>
							<view class="task-warp">
								<view class="title">{
   
   { i.title }}</view>
								<view class="ip-beans">
									可获得
									<text>{
   
   { i.ipbeans }}</text>
								</view>
								<view class="text">{
   
   { i.text }}</view>
							</view>
							<button class="give-away-btn" @click="leftClick">去完成</button>
						</view>
					</view>
				</view>
			</view>
		</slide-popup>
		<!-- 遮盖层 -->
		<view class="mark" v-show="markShow"></view>
	</view>
</template>

<script>
export default {
      
      
	props: {
      
      
	},
	data() {
      
      
		return {
      
      
			markShow:false,
			missionList: [
				{
      
      
					texth: '新手任务',
					taskList: [
						{
      
      
							url: '../../static/carton-drawer/fx-icon.png',
							text: '每日限制一次',
							ipbeans: '300Ip',
							title: '分享好友'
						},
						{
      
      
							url: '../../static/carton-drawer/yq-icon.png',
							text: '邀请开卡有礼',
							ipbeans: '100Ip',
							title: '不限次数'
						}
					]
				},
				{
      
      
					texth: '进阶任务',
					taskList: [
						{
      
      
							url: '../../static/carton-drawer/gw-icon.png',
							text: '不限次数',
							ipbeans: '100 Ip',
							title: '购买商品'
						}
					]
				}
			]
		};
	},
	watch:{
      
      
		markShow(n){
      
      
			this.markShow = n
		}
	},
	methods: {
      
      
		swipeClick(show) {
      
      
			this.markShow = show;
		},
		toAchieve() {
      
      }
	}
};
</script>

<style lang="scss" scoped>
.tapBoxTouchLine {
      
      
	display: flex;
	align-items: center;
	flex-direction: column;
	justify-content: center;

	.line {
      
      
		margin: 10rpx 0;
		vertical-align: middle;
		border-bottom: 16rpx solid #9f9f9f;
		border-radius: 10rpx 10rpx 0 0;
		width: 76rpx;
		transform: scaleY(0.5);
	}

	.title {
      
      
		color: #666666;
		margin: 0;
		font-size: 24rpx;
	}
	.text-tw {
      
      
		width: 96vw;
		margin-left: 2vw;
		height: 60rpx;
		line-height: 60rpx;
		font-size: 28rpx;
		color: #999999;
		text-align: start;
	}
}

.mission-center {
      
      
	margin-top: 12rpx;
	image {
      
      
		width: 98%;
		margin-left: 1%;
		height: 212rpx;
		border-radius: 40rpx;
	}

	.mission-board-li {
      
      
		.h3 {
      
      
			border-left: solid #f75348 8rpx;
			padding-left: 30rpx;
			border-radius: 8rpx;
			font-size: 36rpx;
			font-weight: 700;
			margin: 40rpx 0;
		}

		.task-list {
      
      
			display: flex;
			justify-content: space-between;
			align-items: center;
			height: 160rpx;
			image {
      
      
				width: 76rpx;
				height: 76rpx;
			}

			.task-warp {
      
      
				width: 57%;
				.title {
      
      
					font-size: 32rpx;
					font-weight: 700;
					margin-bottom: 12rpx;
				}
				.ip-beans {
      
      
					font-size: 30rpx;
					text {
      
      
						color: #f1c40f;
					}
				}
				.text {
      
      
					margin-top: 4rpx;
					font-size: 24rpx;
					color: #bdbdbd;
				}
			}
			.give-away-btn {
      
      
				width: 176rpx;
				height: 60rpx;
				background: #f75348;
				border-radius: 30rpx;
				color: #ffffff;
				padding: 0 !important;
				margin: 0 !important;
				font-size: 28rpx;
				line-height: 60rpx;
			}
		}
	}
}


.mark {
      
      
	position: fixed;
	height: 100vh;
	background: rgba(0, 0, 0, 0.1);
	left: 0%;
	right: 0%;
	top: 0;
	z-index: 100;
}
</style>

Guess you like

Origin blog.csdn.net/qq_43869822/article/details/127051009