Files
jobslink-user-clent/components/mark-slide-list/mark-slide-list.vue

187 lines
4.2 KiB
Vue
Raw Normal View History

2024-02-02 14:44:30 +08:00
<template>
<view class="slide-list">
<view class="slide-list-item" @touchstart="touchStart" @touchend="touchEnd" @touchmove="touchMove" :style="{transform}">
<slot></slot>
</view>
<view class="group-btn">
<view class="btn-div" v-for="(btn, key) in button" :key="key" @click.stop="btnClick(btn,key)" :style="{background: btn.background}">
<text class="btn-title">{{btn.title}}</text>
</view>
</view>
</view>
</template>
<script>
import handler from './slideHandler.js'
/**
* m-slide-list 滑动操作列表
* @description 滑动操作列表组件
* @tutorial https://ext.dcloud.net.cn/plugin?id=209
* @property {Array} list 数据源格式为[{title: 'xxx', image:'xxx', surname: 'xxx',detail:'xxx', rightDetail: 'xxx', slide_x: 0},{title: 'xxx', image:'xxx', surname: 'xxx',detail:'xxx', rightDetail: 'xxx', slide_x: 0}]
* @property {Array} button 按钮数据源格式为[{title: 'xxx', background:'xxx'},{title: 'xxx', background:'xxx'}]
* @property {Boolean} border 边框
*/
export default {
name: 'mark-slide-list',
props: {
button: { //按钮数据list
type: Array,
default () {
return [];
}
}
},
computed: {
windowWidth() {
return uni.getSystemInfoSync().windowWidth;
},
transform() {
return `translate3d(${ this.slide_x }px, 0, 0)`
}
},
data() {
return {
key: null,
moving: false,
btnState: 'hide',
hideLimit: 0,
showLimit: 0,
btnWidth: 0,
slide_x: 0,
handler: null
};
},
mounted() {
this.$emit('controller-reg', {
instance:{
show: this.show,
hide: this.hide
},
cb: (key) => {
this.key = key
}
})
const cb = res => {
this.btnWidth = res[0].width * -1;
this.showLimit = res[0].width / 3;
this.hideLimit = res[0].width / 3;
}
// 按钮宽度
uni.createSelectorQuery().in(this).select('.group-btn').boundingClientRect().exec(cb);
},
methods: {
btnClick(btn, key) {
this.$emit(btn.clickName, {
btn,
key
})
},
setSlideX(offset) {
const val = offset + this.slide_x
if (val < 0 && val >= this.btnWidth) {
this.slide_x = val
} else if (val > 0) {
this.slide_x = 0
}
},
// 滑动开始
touchStart(e) {
this.$emit('controller-moving', this.key)
this.moving = true
this.handler = new handler(e.timeStamp, e.touches[0].pageX, e.touches[0].pageY)
},
// 滑动中
touchMove(e) {
const slide_x = this.handler.move(e.touches[0])
this.setSlideX(slide_x)
},
// 滑动结束
touchEnd(e) {
this.moving = false
const endTime = e.timeStamp,
endY = e.changedTouches[0].pageY,
endX = e.changedTouches[0].pageX;
const x_end_distance = this.startX - this.lastX;
const end = this.handler.endMove(endTime, endX, endY)
if (end.invalid) {} else if ((end.quick && end.dir === 'l') || (end.dir === 'l' && end.move > this.showLimit)) {
this.show()
} else if ((end.quick && end.dir === 'r') || (end.dir === 'r' && end.move > this.hideLimit)) {
this.hide()
} else {
this.recover()
}
this.handler = null
},
// 点击回复原状
recover() {
if (this.btnState === 'show') {
this.show()
} else if (this.btnState === 'hide') {
this.hide()
}
},
show() {
this.btnState = 'show'
this.slide_x = this.btnWidth;
this.$emit('controller-opened', this.key)
},
hide() {
this.btnState = 'hide'
this.slide_x = 0;
this.$emit('controller-closed', this.key)
},
}
};
</script>
<style lang="scss" scoped>
.slide-list {
position: relative;
width: 100%;
.slide-list-item {
width: 100%;
overflow: hidden;
position: relative;
z-index: 2;
transition: all 100ms;
transition-timing-function: ease-out;
}
.group-btn {
position: absolute;
top: 0;
right: 0;
height: 100%;
min-width: 100rpx;
align-items: center;
z-index: 1;
display: flex;
flex-direction: row;
.btn-div {
height: 100%;
color: #fff;
text-align: center;
padding: 0 50rpx;
font-size: 34rpx;
display: table;
.btn-title {
display: table-cell;
vertical-align: middle;
}
}
.top {
background-color: #c4c7cd;
}
.removeM {
background-color: #ff3b32;
}
}
}
</style>