bindingx.js 5.79 KB
const BindingX = uni.requireNativePlugin('bindingx');
const dom = uni.requireNativePlugin('dom');
const animation = uni.requireNativePlugin('animation');

export default {
	data() {
		return {
			right: 0,
			button: [],
			preventGesture: false
		}
	},

	watch: {
		show(newVal) {
			if (!this.position || JSON.stringify(this.position) === '{}') return;
			if (this.autoClose) return
			if (this.isInAnimation) return
			if (newVal) {
				this.open()
			} else {
				this.close()
			}
		},
	},
	created() {
		if (this.swipeaction.children !== undefined) {
			this.swipeaction.children.push(this)
		}
	},
	mounted() {
		this.boxSelector = this.getEl(this.$refs['selector-box-hock']);
		this.selector = this.getEl(this.$refs['selector-content-hock']);
		this.buttonSelector = this.getEl(this.$refs['selector-button-hock']);
		this.position = {}
		this.x = 0
		setTimeout(() => {
			this.getSelectorQuery()
		}, 200)
	},
	beforeDestroy() {
		if (this.timing) {
			BindingX.unbind({
				token: this.timing.token,
				eventType: 'timing'
			})
		}
		if (this.eventpan) {
			BindingX.unbind({
				token: this.eventpan.token,
				eventType: 'pan'
			})
		} 
		this.swipeaction.children.forEach((item, index) => {
			if (item === this) {
				this.swipeaction.children.splice(index, 1)
			}
		})
	},
	methods: {
		onClick(index, item) {
			this.$emit('click', {
				content: item,
				index
			})
		},
		touchstart(e) {
			if (this.isInAnimation) return
			if (this.stop) return
			this.stop = true
			if (this.autoClose) {
				this.swipeaction.closeOther(this)
			}
			let endWidth = this.right
			let boxStep = `(x+${this.x})`
			let pageX = `${boxStep}> ${-endWidth} && ${boxStep} < 0?${boxStep}:(x+${this.x} < 0? ${-endWidth}:0)`

			let props = [{
				element: this.selector,
				property: 'transform.translateX',
				expression: pageX
			}]

			let left = 0
			for (let i = 0; i < this.options.length; i++) {
				let buttonSelectors = this.getEl(this.$refs['button-hock'][i]);
				if (this.button.length === 0 || !this.button[i] || !this.button[i].width) return
				let moveMix = endWidth - left
				left += this.button[i].width
				let step = `(${this.x}+x)/${endWidth}`
				let moveX = `(${step}) * ${moveMix}`
				let pageButtonX = `${moveX}&& (x+${this.x} > ${-endWidth})?${moveX}:${-moveMix}`
				props.push({
					element: buttonSelectors,
					property: 'transform.translateX',
					expression: pageButtonX
				})
			}

			this.eventpan = this._bind(this.boxSelector, props, 'pan', (e) => {
				if (e.state === 'end') {
					this.x = e.deltaX + this.x;
					if (this.x < -endWidth) {
						this.x = -endWidth
					}
					if (this.x > 0) {
						this.x = 0
					}
					this.stop = false
					this.bindTiming();
				}
			})
		},
		touchend(e) {
			this.$nextTick(() => {
				if (this.isopen && !this.isDrag && !this.isInAnimation) {
					this.close()
				}
			})
		},
		bindTiming() {
			if (this.isopen) {
				this.move(this.x, -this.right)
			} else {
				this.move(this.x, -40)
			}
		},
		move(left, value) {
			if (left >= value) {
				this.close()
			} else {
				this.open()
			}
		},
		/**
		 * 开启swipe
		 */
		open() {
			this.animation(true)
		},
		/**
		 * 关闭swipe
		 */
		close() {
			this.animation(false)
		},
		/**
		 * 开启关闭动画
		 * @param {Object} type
		 */
		animation(type) {
			this.isDrag = true
			let endWidth = this.right
			let time = 200
			this.isInAnimation = true;

			let exit = `t>${time}`;
			let translate_x_expression = `easeOutExpo(t,${this.x},${type?(-endWidth-this.x):(-this.x)},${time})`
			let props = [{
				element: this.selector,
				property: 'transform.translateX',
				expression: translate_x_expression
			}]

			let left = 0
			for (let i = 0; i < this.options.length; i++) {
				let buttonSelectors = this.getEl(this.$refs['button-hock'][i]);
				if (this.button.length === 0 || !this.button[i] || !this.button[i].width) return
				let moveMix = endWidth - left
				left += this.button[i].width
				let step = `${this.x}/${endWidth}`
				let moveX = `(${step}) * ${moveMix}`
				let pageButtonX = `easeOutExpo(t,${moveX},${type ? -moveMix + '-' + moveX: 0 + '-' + moveX},${time})`
				props.push({
					element: buttonSelectors,
					property: 'transform.translateX',
					expression: pageButtonX
				})
			}

			this.timing = BindingX.bind({
				eventType: 'timing',
				exitExpression: exit,
				props: props
			}, (e) => {
				if (e.state === 'end' || e.state === 'exit') {
					this.x = type ? -endWidth : 0
					this.isInAnimation = false;

					this.isopen = this.isopen || false
					if (this.isopen !== type) {
						this.$emit('change', type)
					}
					this.isopen = type
					this.isDrag = false
				}
			});
		},
		/**
		 * 绑定  BindingX
		 * @param {Object} anchor
		 * @param {Object} props
		 * @param {Object} fn
		 */
		_bind(anchor, props, eventType, fn) {
			return BindingX.bind({
				anchor,
				eventType,
				props
			}, (e) => {
				typeof(fn) === 'function' && fn(e)
			});
		},
		/**
		 * 获取ref
		 * @param {Object} el
		 */
		getEl(el) {
			return el.ref
		},
		/**
		 * 获取节点信息
		 */
		getSelectorQuery() {
			dom.getComponentRect(this.$refs['selector-content-hock'], (data) => {
				if (this.position.content) return
				this.position.content = data.size
			})
			for (let i = 0; i < this.options.length; i++) {
				dom.getComponentRect(this.$refs['button-hock'][i], (data) => {
					if (!this.button) {
						this.button = []
					}
					if (this.options.length === this.button.length) return
					this.button.push(data.size)
					this.right += data.size.width
					if (this.autoClose) return
					if (this.show) {
						this.open()
					}
				})
			}
		}
	}
}