Bootstrap

uni-app技术分享| 用uni-app实现拖动的诀窍

还在为实现类似于 那样的视频窗口随意拖动而苦恼吗?福音来了,今天就为大家解决这样的烦恼。

前提:

使用 anyrtc 基本实现音视频(nvue页面)

需求:

两人通话时可随意拖动小视频

实现原理:

uniapp的nvue内置原生插件 BindingX。具体可查看

效果展示:

项目地址:

具体实现:

1. 在实现音视频功能插件提供的视频容器外边包裹一层。

如:(使用 )

  
    
  

2. 使用nvue内置插件 BindingX(uniapp已默认集成) 。

nvue内置插件,具体可查看 BindingX 效果以及相关方法可参考

const BindingX = uni.requireNativePlugin('bindingx');

3. 实现拖拽具体方法:

1. 相关数据(nvue)
      data() {
        return {
            // 页面高宽
            windowWidth: 200,
          windowHeight: 400,
          // 记录当前位置
          position: { 
                x: 0,
                y: 0
              },
            // 判断是点击事件还是拖动事件      
            timer: false,
        }
      }

2. 封装 BindingX 获取拖动的元素(添加到nvue的methods)
      // 获取元素
      getEl(el) {
        if (typeof el === 'string' || typeof el === 'number') return el;
          if (WXEnvironment) {
            return el.ref;
          } else {
            return el instanceof HTMLElement ? el : el.$el;
           }
      },
3. 为可拖动元素绑定手指触发事件(添加到nvue的methods)
      drag_start(e) {
          const move = this.getEl(this.$refs.move);
          let oBindingX = BindingX.bind({
                anchor: move,
                eventType: 'pan',
                props: [{
                    element: move,
                    property: 'transform.translateX',
                    expression: `x+${this.position.x}`,
                  },
                  {
                    element: move,
                    property: 'transform.translateY',
                    expression: `y+${this.position.y}`,  
                  }
                ]
              }, (e) => {
                if (e.state === 'end') {
                  if (this.timer) { 
                                  //移动时间特别短暂 视为点击事件
                    clearTimeout(this.timer);
                                  // 点击事件处理
                  }
                  BindingX.unbind({
                    token: oBindingX.token,
                    eventType: 'pan'
                  })
                  //记录位置 
                  this.position.x += e.deltaX;
                  this.position.y += e.deltaY;
                  // x轴边界
                  if (-this.position.x >= (this.windowWidth - 193)) {
                    this.position.x = 193 - this.windowWidth;
                  }
                  if (this.position.x > 0) {
                    this.position.x = 0;
                  }
                  // y 轴边界 
                  if (this.position.y < 0) {
                    this.position.y = 0;
                  }
                  if (this.position.y >= (this.windowHeight - 244)) {
                    this.position.y = this.windowHeight - 244;
                  }
                              // 结束拖动
                  this.endAmaier();
                } else {
                              // 判断点击事件还是拖动事件
                  this.timer = setTimeout(() => {
                    this.timer = null;
                  }, 50)
                }
              });
            
      }
      
      // 结束拖动
      endAmaier(e) {
          const my = this.getEl(this.$refs.move);
        let result = BindingX.bind({
                eventType: 'timing',
                exitExpression: 't>200',
                props: [{
                    element: my,
                    property: 'transform.translateX',
                    expression: "easeOutElastic(t," + this.position.x + "," + 0 +
                      ",200)",
                  },
                  {
                    element: my,
                    property: 'transform.translateY',
                    expression: "easeOutElastic(t," + this.position.y + "," + 0 +
                      ",200)",
                  }
                ]
              }, (e) => {
                if (e.state === 'end' || e.state === 'exit') {
                  BindingX.unbind({
                    token: result.token,
                    eventType: 'timing'
                  })
                }
              });
      }

4. 运行项目,即可流畅拖动