293 lines
6.1 KiB
JavaScript
293 lines
6.1 KiB
JavaScript
|
const BindingX = uni.requireNativePlugin('bindingx');
|
||
|
const dom = uni.requireNativePlugin('dom');
|
||
|
const animation = uni.requireNativePlugin('animation');
|
||
|
|
||
|
export default {
|
||
|
data() {
|
||
|
return {}
|
||
|
},
|
||
|
|
||
|
watch: {
|
||
|
show(newVal) {
|
||
|
if (this.autoClose) return
|
||
|
if (this.stop) return
|
||
|
this.stop = true
|
||
|
if (newVal) {
|
||
|
this.open(newVal)
|
||
|
} else {
|
||
|
this.close()
|
||
|
}
|
||
|
},
|
||
|
leftOptions() {
|
||
|
this.getSelectorQuery()
|
||
|
this.init()
|
||
|
},
|
||
|
rightOptions(newVal) {
|
||
|
this.init()
|
||
|
}
|
||
|
},
|
||
|
created() {
|
||
|
if (this.swipeaction.children !== undefined) {
|
||
|
this.swipeaction.children.push(this)
|
||
|
}
|
||
|
},
|
||
|
mounted() {
|
||
|
this.box = this.getEl(this.$refs['selector-box--hock'])
|
||
|
this.selector = this.getEl(this.$refs['selector-content--hock']);
|
||
|
this.leftButton = this.getEl(this.$refs['selector-left-button--hock']);
|
||
|
this.rightButton = this.getEl(this.$refs['selector-right-button--hock']);
|
||
|
this.init()
|
||
|
},
|
||
|
beforeDestroy() {
|
||
|
this.swipeaction.children.forEach((item, index) => {
|
||
|
if (item === this) {
|
||
|
this.swipeaction.children.splice(index, 1)
|
||
|
}
|
||
|
})
|
||
|
},
|
||
|
methods: {
|
||
|
init() {
|
||
|
this.$nextTick(() => {
|
||
|
this.x = 0
|
||
|
this.button = {
|
||
|
show: false
|
||
|
}
|
||
|
setTimeout(() => {
|
||
|
this.getSelectorQuery()
|
||
|
}, 200)
|
||
|
})
|
||
|
},
|
||
|
onClick(index, item, position) {
|
||
|
this.$emit('click', {
|
||
|
content: item,
|
||
|
index,
|
||
|
position
|
||
|
})
|
||
|
},
|
||
|
touchstart(e) {
|
||
|
// 每次只触发一次,避免多次监听造成闪烁
|
||
|
if (this.stop) return
|
||
|
this.stop = true
|
||
|
if (this.autoClose) {
|
||
|
this.swipeaction.closeOther(this)
|
||
|
}
|
||
|
|
||
|
const leftWidth = this.button.left.width
|
||
|
const rightWidth = this.button.right.width
|
||
|
let expression = this.range(this.x, -rightWidth, leftWidth)
|
||
|
let leftExpression = this.range(this.x - leftWidth, -leftWidth, 0)
|
||
|
let rightExpression = this.range(this.x + rightWidth, 0, rightWidth)
|
||
|
|
||
|
this.eventpan = BindingX.bind({
|
||
|
anchor: this.box,
|
||
|
eventType: 'pan',
|
||
|
props: [{
|
||
|
element: this.selector,
|
||
|
property: 'transform.translateX',
|
||
|
expression
|
||
|
}, {
|
||
|
element: this.leftButton,
|
||
|
property: 'transform.translateX',
|
||
|
expression: leftExpression
|
||
|
}, {
|
||
|
element: this.rightButton,
|
||
|
property: 'transform.translateX',
|
||
|
expression: rightExpression
|
||
|
}, ]
|
||
|
}, (e) => {
|
||
|
// nope
|
||
|
if (e.state === 'end') {
|
||
|
this.x = e.deltaX + this.x;
|
||
|
this.isclick = true
|
||
|
this.bindTiming(e.deltaX)
|
||
|
}
|
||
|
});
|
||
|
},
|
||
|
touchend(e) {
|
||
|
if (this.isopen !== 'none' && !this.isclick) {
|
||
|
this.open('none')
|
||
|
}
|
||
|
},
|
||
|
bindTiming(x) {
|
||
|
const left = this.x
|
||
|
const leftWidth = this.button.left.width
|
||
|
const rightWidth = this.button.right.width
|
||
|
const threshold = this.threshold
|
||
|
if (!this.isopen || this.isopen === 'none') {
|
||
|
if (left > threshold) {
|
||
|
this.open('left')
|
||
|
} else if (left < -threshold) {
|
||
|
this.open('right')
|
||
|
} else {
|
||
|
this.open('none')
|
||
|
}
|
||
|
} else {
|
||
|
if ((x > -leftWidth && x < 0) || x > rightWidth) {
|
||
|
if ((x > -threshold && x < 0) || (x - rightWidth > threshold)) {
|
||
|
this.open('left')
|
||
|
} else {
|
||
|
this.open('none')
|
||
|
}
|
||
|
} else {
|
||
|
if ((x < threshold && x > 0) || (x + leftWidth < -threshold)) {
|
||
|
this.open('right')
|
||
|
} else {
|
||
|
this.open('none')
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* 移动范围
|
||
|
* @param {Object} num
|
||
|
* @param {Object} mix
|
||
|
* @param {Object} max
|
||
|
*/
|
||
|
range(num, mix, max) {
|
||
|
return `min(max(x+${num}, ${mix}), ${max})`
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* 开启swipe
|
||
|
*/
|
||
|
open(type) {
|
||
|
this.animation(type)
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* 关闭swipe
|
||
|
*/
|
||
|
close() {
|
||
|
this.animation('none')
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* 开启关闭动画
|
||
|
* @param {Object} type
|
||
|
*/
|
||
|
animation(type) {
|
||
|
const time = 300
|
||
|
const leftWidth = this.button.left.width
|
||
|
const rightWidth = this.button.right.width
|
||
|
if (this.eventpan && this.eventpan.token) {
|
||
|
BindingX.unbind({
|
||
|
token: this.eventpan.token,
|
||
|
eventType: 'pan'
|
||
|
})
|
||
|
}
|
||
|
|
||
|
switch (type) {
|
||
|
case 'left':
|
||
|
Promise.all([
|
||
|
this.move(this.selector, leftWidth),
|
||
|
this.move(this.leftButton, 0),
|
||
|
this.move(this.rightButton, rightWidth * 2)
|
||
|
]).then(() => {
|
||
|
this.setEmit(leftWidth, type)
|
||
|
})
|
||
|
break
|
||
|
case 'right':
|
||
|
Promise.all([
|
||
|
this.move(this.selector, -rightWidth),
|
||
|
this.move(this.leftButton, -leftWidth * 2),
|
||
|
this.move(this.rightButton, 0)
|
||
|
]).then(() => {
|
||
|
this.setEmit(-rightWidth, type)
|
||
|
})
|
||
|
break
|
||
|
default:
|
||
|
Promise.all([
|
||
|
this.move(this.selector, 0),
|
||
|
this.move(this.leftButton, -leftWidth),
|
||
|
this.move(this.rightButton, rightWidth)
|
||
|
]).then(() => {
|
||
|
this.setEmit(0, type)
|
||
|
})
|
||
|
|
||
|
}
|
||
|
},
|
||
|
setEmit(x, type) {
|
||
|
const leftWidth = this.button.left.width
|
||
|
const rightWidth = this.button.right.width
|
||
|
this.isopen = this.isopen || 'none'
|
||
|
this.stop = false
|
||
|
this.isclick = false
|
||
|
// 只有状态不一致才会返回结果
|
||
|
if (this.isopen !== type && this.x !== x) {
|
||
|
if (type === 'left' && leftWidth > 0) {
|
||
|
this.$emit('change', 'left')
|
||
|
}
|
||
|
if (type === 'right' && rightWidth > 0) {
|
||
|
this.$emit('change', 'right')
|
||
|
}
|
||
|
if (type === 'none') {
|
||
|
this.$emit('change', 'none')
|
||
|
}
|
||
|
}
|
||
|
this.x = x
|
||
|
this.isopen = type
|
||
|
},
|
||
|
move(ref, value) {
|
||
|
return new Promise((resolve, reject) => {
|
||
|
animation.transition(ref, {
|
||
|
styles: {
|
||
|
transform: `translateX(${value})`,
|
||
|
},
|
||
|
duration: 150, //ms
|
||
|
timingFunction: 'linear',
|
||
|
needLayout: false,
|
||
|
delay: 0 //ms
|
||
|
}, function(res) {
|
||
|
resolve(res)
|
||
|
})
|
||
|
})
|
||
|
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* 获取ref
|
||
|
* @param {Object} el
|
||
|
*/
|
||
|
getEl(el) {
|
||
|
return el.ref
|
||
|
},
|
||
|
/**
|
||
|
* 获取节点信息
|
||
|
*/
|
||
|
getSelectorQuery() {
|
||
|
Promise.all([
|
||
|
this.getDom('left'),
|
||
|
this.getDom('right'),
|
||
|
]).then((data) => {
|
||
|
let show = 'none'
|
||
|
if (this.autoClose) {
|
||
|
show = 'none'
|
||
|
} else {
|
||
|
show = this.show
|
||
|
}
|
||
|
|
||
|
if (show === 'none') {
|
||
|
// this.close()
|
||
|
} else {
|
||
|
this.open(show)
|
||
|
}
|
||
|
|
||
|
})
|
||
|
|
||
|
},
|
||
|
getDom(str) {
|
||
|
return new Promise((resolve, reject) => {
|
||
|
dom.getComponentRect(this.$refs[`selector-${str}-button--hock`], (data) => {
|
||
|
if (data) {
|
||
|
this.button[str] = data.size
|
||
|
resolve(data)
|
||
|
} else {
|
||
|
reject()
|
||
|
}
|
||
|
})
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
}
|