Files
CompanyProject/金壶/appV1/components/uni-ui/uni-swipe-action/uni-swipe-action.vue
2024-09-27 01:32:49 +08:00

247 lines
5.6 KiB
Vue

<template>
<view class="uni-swipe-action">
<view :class="{ 'uni-swipe-action--show': isShowBtn }" :style="{ transform: transformX, '-webkit-transform': transformX }" class="uni-swipe-action__container" @touchstart="touchStart" @touchmove="touchMove" @touchend="touchEnd" @touchcancel="touchEnd" @click="bindClickCont">
<view class="uni-swipe-action__content">
<slot />
</view>
<view :id="elId" class="uni-swipe-action__btn-group">
<div v-for="(item, index) in options" :key="index" :style="{
backgroundColor: item.style && item.style.backgroundColor ? item.style.backgroundColor : '#C7C6CD',
color: item.style && item.style.color ? item.style.color : '#FFFFFF',
fontSize: item.style && item.style.fontSize ? item.style.fontSize : '28upx'
}" class="uni-swipe-action--btn" @click="bindClickBtn(item, index)">
{{ item.text }}
</div>
</view>
</view>
<view v-if="isShowBtn" class="uni-swipe-action__mask" @click="close" @touchmove.stop.prevent="close" />
</view>
</template>
<script>
export default {
name: 'UniSwipeAction',
props: {
isDrag: {
type: Boolean,
default: false
},
isOpened: {
type: Boolean,
default: false
},
disabled: {
type: Boolean,
default: false
},
autoClose: {
type: Boolean,
default: true
},
options: {
type: Array,
default () {
return []
}
}
},
data() {
const elId = `Uni_${Math.ceil(Math.random() * 10e5).toString(36)}`
return {
elId: elId,
isShowBtn: false,
transformX: 'translateX(0px)'
}
},
watch: {
isOpened(newValue, oldValue) {
this.isShowBtn = !!newValue
this.endMove()
}
},
created() {
this.direction = ''
this.startX = 0
this.startY = 0
this.btnGroupWidth = 0
this.isMoving = false
this.startTime = 0
},
// #ifdef H5
mounted() {
this.getSize()
},
// #endif
// #ifndef H5
onReady() {
this.getSize()
},
// #endif
methods: {
getSize() {
uni.createSelectorQuery()
.in(this)
.select(`#${this.elId}`)
.boundingClientRect()
.exec(ret => {
this.btnGroupWidth = ret[0].width
})
if (this.isOpened === true) {
this.isShowBtn = true
this.endMove()
}
},
bindClickBtn(item, index) {
this.$emit('click', {
text: item.text,
style: item.style,
index: index
})
},
bindClickCont(e) {
if (this.isShowBtn && this.autoClose === true) {
this.isShowBtn = false
this.endMove()
}
},
touchStart(event) {
this.startTime = event.timeStamp
this.startX = event.touches[0].pageX
this.startY = event.touches[0].pageY
},
touchMove(event) {
if (this.direction === 'Y' || this.disabled === true) {
return
}
var moveY = event.touches[0].pageY - this.startY
var moveX = event.touches[0].pageX - this.startX
if (!this.isMoving && Math.abs(moveY) > Math.abs(moveX)) {
// 纵向滑动
this.direction = 'Y'
return
}
this.direction = moveX > 0 ? 'right' : 'left'
this.isMoving = true
if (this.isDrag) {
let movedLength = this.isShowBtn ? -this.btnGroupWidth : 0
if (movedLength + moveX >= 0) {
this.transformX = `translateX(0px)`
return
}
if (-movedLength - moveX >= this.btnGroupWidth) {
this.transformX = `translateX(${-this.btnGroupWidth}px)`
return
}
if (movedLength - moveX > 0) {
this.transformX = `translateX(${moveX}px)`
} else {
if (moveX >= -this.btnGroupWidth) {
this.transformX = `translateX(${moveX - this.btnGroupWidth}px)`
}
}
}
},
touchEnd(event) {
this.isMoving = false
if (this.direction !== 'right' && this.direction !== 'left') {
this.direction = ''
return
}
if (this.isDrag) {
let movedLength = Math.abs(Number(this.transformX.slice(11, -3)))
let movedTime = event.timeStamp - this.startTime
this.isShowBtn = movedLength >= this.btnGroupWidth / 2
if (movedTime > 50 && movedTime < 300 && movedLength > 20) {
// 在这个时间里面,且滑动了一定的距离
if (this.direction === 'right') {
this.isShowBtn = false
} else {
this.isShowBtn = true
}
}
} else {
if (this.direction === 'right') {
this.isShowBtn = false
} else {
this.isShowBtn = true
}
}
this.endMove()
},
endMove() {
if (this.direction === 'Y' || this.disabled === true) {
this.direction = ''
return
}
if (this.isShowBtn) {
this.transformX = `translateX(${-this.btnGroupWidth}px)`
this.$emit('opened')
} else {
this.transformX = 'translateX(0px)'
this.$emit('closed')
}
this.direction = ''
},
close() {
this.isShowBtn = false
this.endMove()
}
}
}
</script>
<style>
@charset "UTF-8";
.uni-swipe-action {
width: 100%;
overflow: hidden
}
.uni-swipe-action__container {
position: relative;
background-color: #fff;
width: 200%;
display: flex;
flex-direction: row;
flex-wrap: wrap;
transition: transform 350ms cubic-bezier(.165, .84, .44, 1)
}
.uni-swipe-action__content {
width: 50%
}
.uni-swipe-action__btn-group {
display: flex;
flex-direction: row
}
.uni-swipe-action--show {
position: relative;
z-index: 1000
}
.uni-swipe-action--btn {
padding: 0 32upx;
color: #fff;
background-color: #c7c6cd;
font-size: 28upx;
display: inline-flex;
text-align: center;
flex-direction: row;
align-items: center
}
.uni-swipe-action__mask {
display: block;
opacity: 0;
position: fixed;
z-index: 999;
top: 0;
left: 0;
width: 100%;
height: 100%
}
</style>