zhangzengfei
2021-09-16 38430ddb8612fce15a2f1c940f9bd57d4da3e70b
components/uni-swipe-action-item/bindingx.js
@@ -1,245 +1,245 @@
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()
               }
            })
         }
      }
   }
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()
               }
            })
         }
      }
   }
}