uniapp小程序—实现下滑关闭抽屉(包含上下左右滑动)

效果

在这里插入图片描述
操作:点击相应文字时从底部出现弹框,下滑超过一定速率,弹框回到下方隐藏;

核心点:

// 当按下去的时候
			fingerstart(e) {
    
    
				// 记录 距离可视区域左上角 左边距 和 上边距
				this.startData.clientX = e.changedTouches[0].clientX;
				this.startData.clientY = e.changedTouches[0].clientY;
				
			},
			// 当抬起来的时候
			fingerend(e) {
    
     
				// 当前位置 减去 按下位置 计算 距离
				const subX = e.changedTouches[0].clientX - this.startData.clientX;
				const subY = e.changedTouches[0].clientY - this.startData.clientY;
				if (subY > this.updDistance || subY < -this.updDistance) {
    
    
					if (subY > this.updDistance) {
    
    
						this.showMax = false;
						this.getDomTop()
					} else if (subY < -this.updDistance) {
    
    
						this.showMax = true;
						this.getDomTop()
					}
				} 
			},

使用组件

<btmPop :startShow="showPop" @closePop="closeWord">
	<template #detail>
	</template>
</btmPop>

全部代码

<template>
	<view 
		class="detailBox" 
		:style="[
			{
    
    
			'height':minHeight+'px',
			'transform':`translateY(${
      
      isHide?99:0}rem)`,
			'backgroundColor':bgColor
			}, 
		]"  
		@touchstart="fingerstart"
		@touchend="fingerend"
	>
	
		<view v-if="showLine" class="popLine"></view>
		<view v-if="!showLine" class="popClose" @click="closePopBox">
			<u-icon name="close" :size="20"></u-icon>
		</view>
		<!-- 自定义内容插槽 -->
		<slot name="detail"></slot>
	</view>
</template>

<script>
	export default{
    
    
		props:{
    
    
			// 高度
			boxHeihgt:{
    
    
				type:Number,
				default:0
			},
			// 背景色
			bgColor:{
    
    
				type:String,
				default:"#FDFAF5"
			},
			// 控制初始是否显示
			startShow:{
    
    
				type:Boolean,
				default:false
			},
			// 是否显示线
			showLine:{
    
    
				type:Boolean,
				default:true
			},
			// 上下滑动 超过多少距离触发 updownDistance
			updDistance: {
    
     
				type: Number,
				default: 160
			},
		},
		watch:{
    
    
			'startShow':{
    
    
				handler(n,o){
    
    
					this.isHide =!n;
				},
				deep:true,
				immediate:true
			}
		},
		data(){
    
    
			return{
    
    
				minHeight:0,
				isHide:true,
				boxPadBottom:0,
				// 根据滑动设置位置
				changeTop:0,
				// 是否固定高度
				showMax:false,
				// 记录起始位置
				startData: {
    
    
					clientX: '',
					clientY: ''
				}
			}
		},
		methods:{
    
    
			
			// 当按下去的时候
			fingerstart(e) {
    
    
				// 记录 距离可视区域左上角 左边距 和 上边距
				this.startData.clientX = e.changedTouches[0].clientX;
				this.startData.clientY = e.changedTouches[0].clientY;
				
			},
			// 当抬起来的时候
			fingerend(e) {
    
     
				// 当前位置 减去 按下位置 计算 距离
				const subX = e.changedTouches[0].clientX - this.startData.clientX;
				const subY = e.changedTouches[0].clientY - this.startData.clientY;
				if (subY > this.updDistance || subY < -this.updDistance) {
    
    
					if (subY > this.updDistance) {
    
    
						// this.bottomscroll(subY);
						this.showMax = false;
						this.getDomTop()
					} else if (subY < -this.updDistance) {
    
    
						// this.topscroll(subY);
						this.showMax = true;
						this.getDomTop()
					}
				} 
			},
			// 获取元素的top值
			getDomTop(){
    
    
				const query = uni.createSelectorQuery().in(this);
				query.select('.detailBox').boundingClientRect(data => {
    
    
				  if(data){
    
    
					// 上滑
					if(this.showMax){
    
    
					}else{
    
    
					// 下滑
						this.closePopBox()
					}
				  }
				}).exec();
			},
			// 关闭弹框
			closePopBox(){
    
    
				this.isHide = true;
				this.$emit("closePop",true)
			}
		},
		onReady() {
    
    
			let windowHeight = uni.getSystemInfoSync().windowHeight;
			let NavbarHeight = this.$store.state.Layout.NavbarHeight;
			this.minHeight = windowHeight-NavbarHeight-20-this.boxHeihgt;
			
		},
	}
</script>

<style lang="scss" scoped>
	.detailBox {
    
    
		position: fixed;
		width: 100%;
		height: auto;
		bottom: 0;
		left: 0;
		border-top-left-radius: 40rpx;
		border-top-right-radius: 40rpx;
		overflow-y: auto;
		transition: all .5s;
		z-index: 99999;
	}
	.popLine{
    
    
		width: 115rpx;
		height: 10rpx;
		border-radius: 28rpx;
		background-color: #EEE2D6;
		margin: 20rpx auto 35rpx;
	}
	.popClose{
    
    
		width: calc(100% - 80rpx);
		display: flex;
		justify-content: flex-end;
		margin: 30rpx 40rpx 10rpx 40rpx;
	}
</style>

总结:

这个组件有些多余的地方我没删,可以自行扩展。以下附带移动端的上下左右滑动,可以借鉴实现小程序的左右滑动

移动端上下左右滑动

// 元素左右滑动
  const NavonTouchStart = (e) => {
    
    
    e.persist();
    state.firstX = e.targetTouches[0].clientX;
    state.firstY = e.targetTouches[0].clientY + 60;
  };
  const NavonTouchEnd = (e) => {
    
    
    e.persist();
    state.endX = e.targetTouches[0].clientX;
    state.endY = e.targetTouches[0].clientY + 60;
    let moveX = state.endX - state.firstX;
    let moveY = state.endY - state.firstY;
    if (Math.abs(moveX) > 130 || Math.abs(moveY) > 130) {
    
        // 130理解为滑动距离
      if (Math.abs(moveX) > Math.abs(moveY)) {
    
    
        let ele = moveX > 0 ? '向右' : '向左';

      } else {
    
    
        let ele = moveY > 0 ? '向下' : '向上';
       
      }
    }
  };

猜你喜欢

转载自blog.csdn.net/hzqzzz/article/details/128485009