还在为实现类似于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)

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. 为可拖动元素绑定手指触发touchstart事件(添加到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. 运行项目,即可流畅拖动


anyRTC
343 声望5 粉丝

实时交互,万物互联,全球实时互动云服务商领跑者!