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