2 changed files with 338 additions and 13 deletions
			
			
		@ -0,0 +1,290 @@ | 
				
			|||
<template> | 
				
			|||
	<view class="swipe_action_box" @touchstart="onTouchstart" @touchmove="onTouchmove" @touchcancel="onTouchcancel" @touchend="onTouchend"> | 
				
			|||
		<view class="swipe_action_item" :style="{ width: (screenWidth + maxWidth) + 'px', transform: 'translateX(' + translateX + 'px)', transition: 'transform ' + animationTime + 'ms cubic-bezier(.165, .84, .44, 1)'  }"> | 
				
			|||
			<view class="swipe_action_content"><slot></slot></view> | 
				
			|||
			<view class="swipe_action_btn_box" ref="swipeActionBtnBox" :class="{'mune-show': mune_show}"> | 
				
			|||
				<view v-for="(item,index) of options" :key="index" class="swipe_action_btn" :style="{ | 
				
			|||
				  backgroundColor: item.style && item.style.backgroundColor ? item.style.backgroundColor : '#C7C6CD' | 
				
			|||
				}" @click.stop="onBtn(index,item)"> | 
				
			|||
					<text :style="{ | 
				
			|||
					  fontSize: item.style && item.style.fontSize ? item.style.fontSize : '14px', | 
				
			|||
					  color: item.style && item.style.color ? item.style.color : '#FFFFFF' | 
				
			|||
					}">{{ item.text }}</text> | 
				
			|||
				</view> | 
				
			|||
			</view> | 
				
			|||
		</view> | 
				
			|||
	</view> | 
				
			|||
</template> | 
				
			|||
 | 
				
			|||
<script> | 
				
			|||
// #ifdef APP-NVUE | 
				
			|||
const dom = weex.requireModule('dom'); | 
				
			|||
// #endif | 
				
			|||
export default { | 
				
			|||
	props: { | 
				
			|||
		/** | 
				
			|||
		 * 按钮内容 | 
				
			|||
		 */ | 
				
			|||
		options: { | 
				
			|||
			type: Array, | 
				
			|||
			default () { | 
				
			|||
				return [] | 
				
			|||
			} | 
				
			|||
		}, | 
				
			|||
		/** | 
				
			|||
		 * 禁用 | 
				
			|||
		 */ | 
				
			|||
		disabled: { | 
				
			|||
			type: Boolean, | 
				
			|||
			default: false | 
				
			|||
		}, | 
				
			|||
		/** | 
				
			|||
		 * 变量控制开关 | 
				
			|||
		 */ | 
				
			|||
		show: { | 
				
			|||
			type: Boolean, | 
				
			|||
			default: false | 
				
			|||
		}, | 
				
			|||
		/** | 
				
			|||
		 * 是否自动关闭 | 
				
			|||
		 */ | 
				
			|||
		autoClose: { | 
				
			|||
			type: Boolean, | 
				
			|||
			default: true | 
				
			|||
		}, | 
				
			|||
		/** | 
				
			|||
		 * swipe-action 的索引值 | 
				
			|||
		 */ | 
				
			|||
		index: { | 
				
			|||
			type: Number, | 
				
			|||
			default: 0 | 
				
			|||
		} | 
				
			|||
	}, | 
				
			|||
	data() { | 
				
			|||
		return { | 
				
			|||
			//开始触摸时间 | 
				
			|||
			startTime: 0, | 
				
			|||
			//开始触摸距离 | 
				
			|||
			touchStartX: 0, | 
				
			|||
			//最大距离 | 
				
			|||
			maxWidth: 58, | 
				
			|||
			//滑动距离 | 
				
			|||
			translateX: 0, | 
				
			|||
			animationTime: 0, | 
				
			|||
			//上次的位置 | 
				
			|||
			currentX: 0, | 
				
			|||
			screenWidth: 0, | 
				
			|||
			mune_show: false | 
				
			|||
		}; | 
				
			|||
	}, | 
				
			|||
	watch:{ | 
				
			|||
		show(val){ | 
				
			|||
			if(val){ | 
				
			|||
				this.animationTime = 350; | 
				
			|||
				this.translateX = -this.maxWidth; | 
				
			|||
			}else { | 
				
			|||
				this.animationTime = 350; | 
				
			|||
				this.translateX = 0; | 
				
			|||
			} | 
				
			|||
		}, | 
				
			|||
		translateX(val){ | 
				
			|||
			if(val == 0){ | 
				
			|||
				this.mune_show = false; | 
				
			|||
			}else{ | 
				
			|||
				this.mune_show = true; | 
				
			|||
			} | 
				
			|||
		} | 
				
			|||
	}, | 
				
			|||
	created() { | 
				
			|||
		let systemInfo = uni.getSystemInfoSync(); | 
				
			|||
		this.screenWidth = systemInfo.screenWidth; | 
				
			|||
	}, | 
				
			|||
	mounted() { | 
				
			|||
		const _this = this; | 
				
			|||
		setTimeout(() => { | 
				
			|||
			// #ifdef APP-NVUE | 
				
			|||
			dom.getComponentRect(this.$refs['swipeActionBtnBox'], (data) => { | 
				
			|||
				_this.maxWidth = data.size.width; | 
				
			|||
				if(_this.show){ | 
				
			|||
					_this.animationTime = 350; | 
				
			|||
					_this.translateX = -data.size.width; | 
				
			|||
				} | 
				
			|||
			}); | 
				
			|||
			// #endif | 
				
			|||
			// #ifndef APP-NVUE | 
				
			|||
			uni.createSelectorQuery().in(this).selectAll('.swipe_action_btn_box') | 
				
			|||
				.boundingClientRect(data => { | 
				
			|||
					_this.maxWidth = data[0].width; | 
				
			|||
					if(_this.show){ | 
				
			|||
						_this.animationTime = 350; | 
				
			|||
						_this.translateX = -data[0].width; | 
				
			|||
					} | 
				
			|||
				}).exec() | 
				
			|||
			// #endif | 
				
			|||
		},500); | 
				
			|||
	}, | 
				
			|||
	//方法 | 
				
			|||
	methods: { | 
				
			|||
		onBtn(index, item) { | 
				
			|||
			this.$emit('button', { | 
				
			|||
				content: item, | 
				
			|||
				index: this.index, | 
				
			|||
				buttonIndex: index | 
				
			|||
			}); | 
				
			|||
			if(this.autoClose){ | 
				
			|||
				this.animationTime = 350; | 
				
			|||
				this.translateX = 0; | 
				
			|||
			} | 
				
			|||
		}, | 
				
			|||
		// 手指触摸动作开始 | 
				
			|||
		onTouchstart(e) { | 
				
			|||
			if(this.disabled){ | 
				
			|||
				return; | 
				
			|||
			} | 
				
			|||
			//储存手指触摸坐标,当前时间戳,当前坐标 | 
				
			|||
			// #ifdef APP-NVUE | 
				
			|||
			this.touchStartX = e.changedTouches[0].screenX; | 
				
			|||
			// #endif | 
				
			|||
			// #ifndef APP-NVUE | 
				
			|||
			this.touchStartX = e.changedTouches[0].clientX; | 
				
			|||
			// #endif | 
				
			|||
			this.startTime = new Date().getTime(); | 
				
			|||
			this.currentX = this.translateX; | 
				
			|||
		}, | 
				
			|||
		// 手指触摸后移动 | 
				
			|||
		onTouchmove(e) { | 
				
			|||
			if(this.disabled){ | 
				
			|||
				return; | 
				
			|||
			} | 
				
			|||
			//手指当前坐标 | 
				
			|||
			// #ifdef APP-NVUE | 
				
			|||
			const clientX = e.changedTouches[0].screenX; | 
				
			|||
			// #endif | 
				
			|||
			// #ifndef APP-NVUE | 
				
			|||
			const clientX = e.changedTouches[0].clientX; | 
				
			|||
			// #endif | 
				
			|||
			//计算滑动距离 | 
				
			|||
			const difference = this.touchStartX - clientX; | 
				
			|||
			//判断左滑还是右滑 | 
				
			|||
			if (difference > 0) { | 
				
			|||
				//计算当前已滑动距离 | 
				
			|||
				const leftDifference = this.currentX - Math.abs(difference); | 
				
			|||
				//判断是否大于滑动的最大宽度 | 
				
			|||
				if (this.maxWidth < Math.abs(leftDifference)) { | 
				
			|||
					this.animationTime = 0; | 
				
			|||
					this.translateX = -this.maxWidth; | 
				
			|||
				} else { | 
				
			|||
					this.animationTime = 0; | 
				
			|||
					this.translateX = leftDifference; | 
				
			|||
				} | 
				
			|||
			} else { | 
				
			|||
				const rightDifference = this.currentX + Math.abs(difference); | 
				
			|||
				if (0 < rightDifference) { | 
				
			|||
					this.animationTime = 0; | 
				
			|||
					this.translateX = 0; | 
				
			|||
				} else { | 
				
			|||
					this.animationTime = 0; | 
				
			|||
					this.translateX = rightDifference; | 
				
			|||
				} | 
				
			|||
			} | 
				
			|||
		}, | 
				
			|||
		// 手指触摸动作被打断,如来电提醒,弹窗 | 
				
			|||
		onTouchcancel(e) { | 
				
			|||
			if(this.disabled){ | 
				
			|||
				return; | 
				
			|||
			} | 
				
			|||
			// #ifdef APP-NVUE | 
				
			|||
			this.finallySlide(e.changedTouches[0].screenX); | 
				
			|||
			// #endif | 
				
			|||
			// #ifndef APP-NVUE | 
				
			|||
			this.finallySlide(e.changedTouches[0].clientX); | 
				
			|||
			// #endif | 
				
			|||
			 | 
				
			|||
		}, | 
				
			|||
		// 手指触摸动作结束 | 
				
			|||
		onTouchend(e) { | 
				
			|||
			if(this.disabled){ | 
				
			|||
				return; | 
				
			|||
			} | 
				
			|||
			// #ifdef APP-NVUE | 
				
			|||
			this.finallySlide(e.changedTouches[0].screenX); | 
				
			|||
			// #endif | 
				
			|||
			// #ifndef APP-NVUE | 
				
			|||
			this.finallySlide(e.changedTouches[0].clientX); | 
				
			|||
			// #endif | 
				
			|||
		}, | 
				
			|||
		//最终判断滑动 | 
				
			|||
		finallySlide(finallyX) { | 
				
			|||
			//手指离开的时间 | 
				
			|||
			const endTime = new Date().getTime(); | 
				
			|||
			//手机滑动屏幕的总花费时间 | 
				
			|||
			const timeDifference = endTime - this.startTime; | 
				
			|||
			//手指触摸总滑动距离 | 
				
			|||
			const distanceDifference = this.touchStartX - finallyX; | 
				
			|||
			//判断最终滑动方向 | 
				
			|||
			if (distanceDifference > 0) { | 
				
			|||
				//判断是否滑动到左边  滑动距离超过3分之一 或者 滑动时间在300毫秒并且距离在4分之一 | 
				
			|||
				if (Math.abs(this.translateX) > this.maxWidth / 2 || (timeDifference < 300 && distanceDifference > this.maxWidth / 4)) { | 
				
			|||
					this.animationTime = 350; | 
				
			|||
					this.translateX = -this.maxWidth; | 
				
			|||
				} else { | 
				
			|||
					this.animationTime = 350; | 
				
			|||
					this.translateX = 0; | 
				
			|||
				} | 
				
			|||
				 | 
				
			|||
			} else if (distanceDifference < 0) { | 
				
			|||
				//判断是否滑动到右边  滑动距离超过3分之一 或者 滑动时间在300毫秒并且距离在4分之一 | 
				
			|||
				if (Math.abs(this.translateX) < this.maxWidth / 2 || (timeDifference < 300 && Math.abs(distanceDifference) > this.maxWidth / 4)) { | 
				
			|||
					this.animationTime = 350; | 
				
			|||
					this.translateX = 0; | 
				
			|||
				} else { | 
				
			|||
					this.animationTime = 350; | 
				
			|||
					this.translateX = -this.maxWidth; | 
				
			|||
				} | 
				
			|||
			} | 
				
			|||
		} | 
				
			|||
	} | 
				
			|||
}; | 
				
			|||
</script> | 
				
			|||
<style scoped> | 
				
			|||
.swipe_action_box { | 
				
			|||
	overflow: hidden; | 
				
			|||
	width: 750rpx; | 
				
			|||
} | 
				
			|||
.swipe_action_item { | 
				
			|||
	/* #ifndef APP-NVUE */ | 
				
			|||
	display: flex; | 
				
			|||
	/* #endif */ | 
				
			|||
	flex-direction: row; | 
				
			|||
} | 
				
			|||
.swipe_action_content { | 
				
			|||
	/* width: 750rpx; */ | 
				
			|||
	width: max-content; | 
				
			|||
	/* #ifndef APP-NVUE */ | 
				
			|||
	flex-shrink: 0; | 
				
			|||
	/* #endif */ | 
				
			|||
} | 
				
			|||
.swipe_action_btn_box { | 
				
			|||
	/* #ifndef APP-NVUE */ | 
				
			|||
	display: flex; | 
				
			|||
	flex-shrink: 0; | 
				
			|||
	/* #endif */ | 
				
			|||
	flex-direction: row; | 
				
			|||
	visibility: hidden; | 
				
			|||
} | 
				
			|||
.mune-show{ | 
				
			|||
	visibility: initial; | 
				
			|||
} | 
				
			|||
.swipe_action_btn { | 
				
			|||
	/* #ifndef APP-NVUE */ | 
				
			|||
	display: flex; | 
				
			|||
	/* #endif */ | 
				
			|||
	flex-direction: row; | 
				
			|||
	align-items: center; | 
				
			|||
	justify-content: center; | 
				
			|||
	padding: 0 30rpx; | 
				
			|||
} | 
				
			|||
.swipe_action_btn:nth-child(1){ | 
				
			|||
	margin-left: 20rpx; | 
				
			|||
} | 
				
			|||
</style> | 
				
			|||
						Write
						Preview
					
					
					Loading…
					
					Cancel
						Save
					
		Reference in new issue