mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-06 03:57:59 +08:00
138 lines
4.3 KiB
Vue
138 lines
4.3 KiB
Vue
<template>
|
|
<div
|
|
v-clickoutside:touchstart="swipeMove"
|
|
@click="swipeMove()"
|
|
@touchstart="startDrag"
|
|
@touchmove="onDrag"
|
|
@touchend="endDrag"
|
|
class="van-cell-swipe"
|
|
ref="cell">
|
|
<div class="van-cell-wrapper">
|
|
<slot>单元格内容</slot>
|
|
</div>
|
|
<div class="van-cell-left">
|
|
<div ref="left">
|
|
<slot name="left"></slot>
|
|
</div>
|
|
</div>
|
|
<div class="van-cell-right">
|
|
<div ref="right">
|
|
<slot name="right"></slot>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import {once} from '../../utils/dom';
|
|
import Clickoutside from '../../utils/clickoutside';
|
|
|
|
export default {
|
|
name: 'van-cell-swipe',
|
|
props: {
|
|
'leftWidth': {type: Number, default: 0},
|
|
'rightWidth': {type: Number, default: 0}
|
|
},
|
|
directives: {Clickoutside},
|
|
data() {
|
|
return {
|
|
start: {x: 0, y: 0}
|
|
};
|
|
},
|
|
computed: {
|
|
leftDefaultTransform(){
|
|
return this.translate3d(-this.leftWidth - 1);
|
|
},
|
|
rightDefaultTransform(){
|
|
return this.translate3d(this.rightWidth);
|
|
}
|
|
},
|
|
mounted() {
|
|
this.wrap = this.$refs.cell.querySelector('.van-cell-wrapper');
|
|
this.leftElm = this.$refs.left;
|
|
this.leftWrapElm = this.leftElm.parentNode;
|
|
this.leftWrapElm.style.webkitTransform = this.leftDefaultTransform;
|
|
|
|
this.rightElm = this.$refs.right;
|
|
this.rightWrapElm = this.rightElm.parentNode;
|
|
this.rightWrapElm.style.webkitTransform = this.rightDefaultTransform;
|
|
},
|
|
methods: {
|
|
resetSwipeStatus() {
|
|
this.swiping = false; // 是否正在拖动
|
|
this.opened = true; // 记录是否滑动左右 或者 注册
|
|
this.offsetLeft = 0; // 记录单次拖动的拖动距离
|
|
},
|
|
translate3d(offset) {
|
|
return `translate3d(${offset}px, 0, 0)`;
|
|
},
|
|
swipeMove(offset = 0) {
|
|
this.wrap.style.webkitTransform = this.translate3d(offset);
|
|
this.rightWrapElm.style.webkitTransform = this.translate3d(this.rightWidth + offset);
|
|
this.leftWrapElm.style.webkitTransform = this.translate3d(-this.leftWidth + offset);
|
|
offset && (this.swiping = true);
|
|
},
|
|
swipeLeaveTransition(direction) {
|
|
setTimeout(() => {
|
|
this.swipeLeave = true;
|
|
// left
|
|
if (direction > 0 && -this.offsetLeft > this.rightWidth * 0.4 && this.rightWidth > 0) {
|
|
this.swipeMove(-this.rightWidth);
|
|
this.resetSwipeStatus();
|
|
return;
|
|
// right
|
|
} else if (direction < 0 && this.offsetLeft > this.leftWidth * 0.4 && this.leftWidth > 0) {
|
|
this.swipeMove(this.leftWidth);
|
|
this.resetSwipeStatus();
|
|
return;
|
|
} else {
|
|
this.swipeMove(0);
|
|
once(this.wrap, 'webkitTransitionEnd', _ => {
|
|
this.wrap.style.webkitTransform = '';
|
|
this.rightWrapElm.style.webkitTransform = this.rightDefaultTransform;
|
|
this.leftWrapElm.style.webkitTransform = this.leftDefaultTransform;
|
|
this.swipeLeave = false;
|
|
this.swiping = false;
|
|
});
|
|
}
|
|
}, 0);
|
|
},
|
|
startDrag(evt) {
|
|
evt = evt.changedTouches ? evt.changedTouches[0] : evt;
|
|
this.dragging = true;
|
|
this.start.x = evt.pageX;
|
|
this.start.y = evt.pageY;
|
|
},
|
|
onDrag(evt) {
|
|
if (this.opened) {
|
|
!this.swiping && this.swipeMove(0);
|
|
this.opened = false;
|
|
return;
|
|
}
|
|
if (!this.dragging) return;
|
|
let swiping;
|
|
const e = evt.changedTouches ? evt.changedTouches[0] : evt;
|
|
const offsetTop = e.pageY - this.start.y;
|
|
const offsetLeft = this.offsetLeft = e.pageX - this.start.x;
|
|
if ((offsetLeft < 0 && -offsetLeft > this.rightWidth) ||
|
|
(offsetLeft > 0 && offsetLeft > this.leftWidth) ||
|
|
(offsetLeft > 0 && !this.leftWidth) ||
|
|
(offsetLeft < 0 && !this.rightWidth)) {
|
|
return;
|
|
}
|
|
const y = Math.abs(offsetTop);
|
|
const x = Math.abs(offsetLeft);
|
|
swiping = !(x < 5 || (x >= 5 && y >= x * 1.73));
|
|
if (!swiping) return;
|
|
evt.preventDefault();
|
|
this.swipeMove(offsetLeft);
|
|
},
|
|
endDrag() {
|
|
if (!this.swiping) return;
|
|
this.swipeLeaveTransition(this.offsetLeft > 0 ? -1 : 1);
|
|
}
|
|
}
|
|
};
|
|
</script>
|
|
|