当前位置:首页 > IT技术 > 移动平台 > 正文

uni-app技术分享| 用uni-app实现拖动的诀窍
2021-10-12 14:16:45

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

前提:

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

需求:

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

实现原理:

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

效果展示:

在这里插入图片描述
在这里插入图片描述

项目地址:

Call_uniapp

具体实现:

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

如:(使用 anyRTC 音视频插件)

    <view ref="move" @touchstart="drag_start">
        <AR-CanvasView ref="location" style="flex: 1;" />
    </view>

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

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

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

3. 实现拖拽具体方法:

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

2. 封装 BindingX 获取拖动的元素(添加到nvue的methods)
  ```javascript
  // 获取元素
  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. 为可拖动元素绑定手指触发touchstart事件(添加到nvue的methods)
  ```javascript
  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. 运行项目,即可流畅拖动

本文摘自 :https://blog.51cto.com/u