skyouc
2024-12-21 c9c263dc43ad90f95f24a036cee9e6b47afb596c
uni_modules/uni-swipe-action/components/uni-swipe-action-item/bindingx.js
@@ -1,300 +1,300 @@
let bindIngXMixins = {}
// #ifdef APP-NVUE
const BindingX = uni.requireNativePlugin('bindingx');
const dom = uni.requireNativePlugin('dom');
const animation = uni.requireNativePlugin('animation');
bindIngXMixins = {
   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() {
      this.swipeaction = this.getSwipeAction()
      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()
               }
            })
         })
      }
   }
}
// #endif
export default bindIngXMixins
let bindIngXMixins = {}
// #ifdef APP-NVUE
const BindingX = uni.requireNativePlugin('bindingx');
const dom = uni.requireNativePlugin('dom');
const animation = uni.requireNativePlugin('animation');
bindIngXMixins = {
   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() {
      this.swipeaction = this.getSwipeAction()
      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()
               }
            })
         })
      }
   }
}
// #endif
export default bindIngXMixins