uniapp实现app端图片+视频轮播
Posted 阵前马弓手
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了uniapp实现app端图片+视频轮播相关的知识,希望对你有一定的参考价值。
需求:swiper轮播里面,可能有图片也可能有视频。当swiper切换到视频时,视频以动画的样式展示(无按钮、进度条等默认播放控件),自动轮播取消,手动滑动切换取消。当视频播放完毕后,可以自动轮播,可以手动滑动切换。
找了个插件市场里的改的。(感谢大佬的插件!)
第一步:使用DCloud插件swiper-video-image - DCloud 插件市场
第二步:①video标签里加属性。实现隐藏按钮、进度条等默认播放控件
controls = "false"
②原swiperChange方法中添加判断,实现切换到视频时,自动轮播取消,手动滑动切换取消。
if (obj[this.typeName] === 'video')
this.touch = true
this.autoplay = false
swiper标签中加属性
:disable-touch = "touch"(是否禁止用户 touch 操作)
:autoplay="autoplay"(是否自动切换)
③使用@ended,用来判断视频当播放到末尾时触发事件,解开自动轮播,手动滑动切换。
@ended="videoEnded"
videoEnded()
this.touch = false
this.autoplay = true
,
部分代码:
<template>
<view class="content">
<view class="screen-swiper-box">
<swiper :current="index" @change="swiperChange" class="screen-swiper" indicator-dots="true" :circular="circular"
:autoplay="autoplay" :interval="interval" duration="500" :style="[whStyle]" :disable-touch = "touch">
<swiper-item v-for="(item, i) in list" :key="i" :id="i">
<video v-if="item[typeName] == videoValue" :id="'myVideo-'+i" class="myVideo" :src="item[linkName]"
controls = "false" objectFit="cover" enable-progress-gesture="false" show-loading="true"
play-btn-position="center" show-fullscreen-btn="true" :style="[whStyle]"
@click="swiperClick(item,i)" @ended="videoEnded"></video>
<image v-if="item[typeName] == imgvalue" class="swiperImage" :src="item[linkName]" mode="scaleToFill"
:style="[whStyle]" @click="swiperClick(item,i)">
</image>
</swiper-item>
</swiper>
</view>
</view>
</template>
<script>
export default
data()
return
index: 0, // 当前页
videoCtx: '',
touch:false,
,
methods:
videoEnded()
this.touch = false
this.autoplay = true
,
swiperChange(e)
// 获取上一个
let obj = this.list[this.index]
if (obj[this.typeName] == this.videoValue)
// console.log('暂停', this.index)
this.videoCtx = uni.createVideoContext('myVideo-' + this.index, this)
this.videoCtx.pause()
// 获取当前
this.index = e.detail.current // 更新当前index
obj = this.list[this.index]
if (obj[this.typeName] == this.videoValue && this.autoPlayVideo)
// console.log('播放', this.index)
this.videoCtx = uni.createVideoContext('myVideo-' + this.index, this)
this.videoCtx.play()
this.$emit('swiperChange', this.index)
if (obj[this.typeName] === 'video')
this.touch = true
this.autoplay = false
,
,
</script>
uni-app技术分享|开源demo视频呼叫arcall uni-app端技术实现
uniapp_arcall
介绍
基本
uniapp_arcall 是通过 uniapp 实现的语音通话、视频通话以及相关配套的呼叫邀请。
解决向指定用户发起呼叫通知,对方接受后进行通话的场景需求。
呼叫邀请基本流程
graph TD
A[主叫] -->|发起呼叫|B{被叫收到呼叫}
A -->|收到被叫接听|C[主叫执行 RTC]
A -->|收到被叫拒绝|G[相关逻辑]
B -->D[被叫接听]
B -->E[被叫拒绝]
D -->|通知主叫接听|A
D -->F[被叫执行 RTC]
E -->|通知主叫拒绝|A
B -->H[60s 无操作邀请自动失败]
通话基本流程
graph LR
A[初始化 RTC 实例] -->|采集音视频|B[加入房间]
B -->|本地采集音视频| C[发布并渲染音视频]
B -->|通过回调获取远端音视频| D[渲染远端音视频]
arcall 具体实现
呼叫邀请相关逻辑
引入呼叫邀请所需插件
// rtm 实时消息引入
const rtmModule = uni.requireNativePlugin(\'AR-RtmModule\');
呼叫邀请初始化
uniapp_arcall的是项目启动就登陆 RTM,因此写在 onLaunch
中,调试时会发生以下错误
Error: [JS Framework] Failed to receiveTasks, instance (1) is not available.
原因是多次将 RTM 实例初始化,会影响到 RTM 相关的使用请将程序杀死后在进行调试
// 初始化回调
await rtmModule.setCallBack(res => {
switch (res.rtmEvent) {
// SDK 与 RTM 系统的连接状态发生改变回调。
case \'onConnectionStateChanged\':
break;
// 收到点对点消息回调
case \'onPeerMessageReceived\':
break;
// 被订阅用户在线状态改变
case \'onPeersOnlineStatusChanged\':
break;
// 返回给主叫:被叫已接受呼叫邀请
case \'onLocalInvitationAccepted\':
break;
// 返回给主叫:呼叫邀请已被取消
case \'onLocalInvitationCanceled\':
break;
// 返回给主叫:呼叫邀请进程失败
case \'onLocalInvitationFailure\':
break;
// 返回给主叫:被叫已收到呼叫邀请
case \'onLocalInvitationReceivedByPeer\':
break;
// 返回给主叫:被叫已拒绝呼叫邀请
case \'onLocalInvitationRefused\':
break;
// 返回给被叫:接受呼叫邀请成功
case \'onRemoteInvitationAccepted\':
break;
// 返回给被叫:主叫已取消呼叫邀请
case \'onRemoteInvitationCanceled\':
break;
// 返回给被叫:来自主叫的呼叫邀请进程失败
case \'onRemoteInvitationFailure\':
break;
// 返回给被叫:收到一个呼叫邀请
case \'onRemoteInvitationReceived\':
break;
// 返回给被叫:拒绝呼叫邀请成功
case \'onRemoteInvitationRefused\':
break;
default:
break;
}
})
// 初始化实例
await rtmModule.createInstance({
"appId": "你的 appid"
}, res => {
console.log(res);
})
// 登录 RTM 系统
await rtmModule.login({
"token": "",
"userId": "本地用户标识"
}, (res) => {
console.log("登录 RTM 系统", res);
})
// // 使用 RTM 呼叫邀请(设置邀请呼叫实例的监听器)
await rtmModule.setCallEventListener();
主叫
-
查询呼叫用户是否在线
rtmModule.queryPeersOnlineStatus({ "peerIds": ["呼叫用户"] }, (res) => { console.log(res); })
-
呼叫用户在线时发起呼叫并订阅
- 发起呼叫
把本地创建的频道房间发送过去
rtmModule.sendLocalInvitation({ "calleeId": calleeId, // 被呼叫者的 user ID "content": JSON.stringify(info) // 邀请内容 }, (res) => { resolve(res.code); })
- 订阅(获取对方在线状态)
当结束通话或结束邀请时记得取消订阅
rtmModule.subscribePeersOnlineStatus({ "peerIds": ["对方 uid"] }, (res) => { //smething console.log("订阅指定单个或多个用户的在线状态", res); })
- 主叫取消呼叫
rtmModule.cancelLocalInvitation({ "calleeId": calleeId, // 被呼叫者的 user ID "content": JSON.stringify(info) // 邀请内容 }, (res) => { console.log("取消给对方的呼叫邀请", res); });
- 发起呼叫
被叫
通过回调 onRemoteInvitationReceived
收到主叫
- 拒绝呼叫
rtmModule.refuseRemoteInvitation({
"calleeId": userId,
"response": JSON.stringify(info) /邀请内容
}, (res) => {
});
- 接受呼叫
rtmModule.acceptRemoteInvitation({
"calleeId": calleeId, // 供被叫获取主叫的用户 ID
"response": info ? JSON.stringify(info) : "" // 邀请响应
}, (res) => {
});
// 订阅对方在线状态
...
相关提示
相关的提示、逻辑都可通过回调来进行操作
通话相关逻辑
视频组件必须实在 nvue 页面
<AR-CanvasView ref="location" style="flex: 1;" />
不管是主叫还是被叫,收到接听的回调后就可以进入 RTC 的相关逻辑
- 引入插件
const rtcModule = uni.requireNativePlugin(\'AR-RtcModule\');
- 初始化
// 初始化回调
await rtcModule.setCallBack(res => {
switch (res.engineEvent) {
case "onConnectionLost":
console.log("onConnectionLost", res);
break;
// 网络连接状态已改变回调
case "onConnectionStateChanged":
console.log("网络连接状态已改变回调", res);
break;
// 发生警告回调
case "onWarning":
break;
// 发生错误回调
case "onError":
break;
// 加入频道成功回调
case "onJoinChannelSuccess":
// 本地渲染
break;
// 远端用户加入当前频道回调
case "onUserJoined":
break;
// 远端用户离开当前频道回调
case "onUserOffline":
console.log("远端用户离开当前频道回调", res);
break;
// 网络连接状态已改变回调
case "onConnectionStateChanged":
break;
// 已显示远端视频首帧回调
case "onFirstRemoteVideoFrame":
break;
case "onFirstRemoteVideoDecoded":
break;
// 远端用户视频状态发生已变化回调(当频道内的用户超过 17 时,该回调可能不准确)
case "onRemoteVideoStateChanged":
break;
// // 本地网络类型发生改变回调
// case "onNetworkTypeChanged":
// break;
// // 网络连接中断
// case "onConnectionLost":
// break;
// // 远端音频状态发生改变回调
// case "onRemoteAudioStateChanged":
// break;
// // 本地音频状态发生改变回调
// case "onLocalAudioStateChanged":
// break;
// // 本地视频状态发生改变回调
// case "onLocalVideoStateChanged":
// break;
// // 重新加入频道回调
// case "onRejoinChannelSuccess":
// break;
// // 离开频道回调
// case "onLeaveChannel":
// break;
// 已发送本地音频首帧回调
// case "onFirstLocalAudioFrame":
// break;
// // 已显示本地视频首帧回调
// case "onFirstLocalVideoFrame":
// break;
// // Token 服务即将过期回调
// case "onTokenPrivilegeWillExpire":
// break;
// // Token 过期回调
// case "onRequestToken":
// break;
// // 用户角色已切换回调(直播场景下)
// case "onClientRoleChanged":
// break;
// // 本地或远端视频大小或旋转信息发生改变回调
// case "onVideoSizeChanged":
// break;
// // 通话中远端音频流的统计信息回调
// case "onRemoteAudioStats":
// break;
// // 当前通话统计回调。 该回调在通话中每两秒触发一次
// case "onRtcStats":
// break;
// // 通话中每个用户的网络上下行 last mile 质量报告回调
// case "onNetworkQuality":
// break;
// // 通话中本地视频流的统计信息回调
// case "onLocalVideoStats":
// break;
// // 通话中本地音频流的统计信息回调
// case "onLocalAudioStats":
// break;
// // 通话中远端视频流的统计信息回调
// case "onRemoteVideoStats":
// break;
}
});
// 初始化实例
await rtcModule.create({
"appId": \'你的 appid\'
}, res => {
console.log(\'初始化实例 rtc\', res);
});
// 开启智能降噪
await rtcModule.setParameters({
Cmd: \'SetAudioAiNoise\',
Enable: 1
}, (res) => {
console.log(\'私人定制\', res);
});
- 采集音视频
如果是语音通话可以不执行下列代码
// 设置视频编码属性
await rtcModule.setVideoEncoderConfiguration({},res) => {
console.log(\'RTC 设置视频编码属性 setVideoEncoderConfiguration 方法调用\', res.code ===0 ? \'成功\' :\'失败:\' + res);
});
// 启用视频
await rtcModule.enableVideo((res) => {
console.log(\'RTC 启用视频 enableVideo 方法调用\', res.code === 0 ? \'成功\' : \'失败:\' +res);
});
- 加入房间
rtcModule.joinChannel({
"token": \'\',
"channelId": 本地创建的频道/通过呼叫邀请传递过来的频道,
"uid": 本地的userid,
}, (res) => {
console.log(\'RTC joinChannel 方法调用\', res.code === 0 ? \'成功\' : \'失败:\' + res);
});
-
本地视频渲染
<AR-CanvasView ref="location" style="flex: 1;" />
获取容器
// 请确保可以获取到容器 Store.location = this.$refs.location; console.log(Store.location); // 打印后 类似这种 { "ref": "68", "type": "AR-CanvasView", "attr": { "@styleScope": "data-v-39c12bd0" }, "style": { "flex": "1" } }
// 渲染视频 await Store.location.setupLocalVideo({ "renderMode": 1, "channelId": 加入的频道房间 "uid": 本地的userid "mirrorMode": 0 }, (res) => { console.log(\'渲染视频\', res); }); // 本地预览 await Store.location.startPreview((res) => { console.log(\'本地预览\', res); })
-
远端视频渲染
通过回调onFirstRemoteVideoDecoded
获取远端用户发布视频
Store.remote 与 Store.location 类似await Store.remote.setupRemoteVideo({ "renderMode": 1, "channelId": 加入的频道 "uid": res.uid "mirrorMode": 0 }, (res) => { console.log(\'渲染远端视频\', res); }) // 本地预览 await Store.remote.startPreview((res) => { console.log(\'远端本地预览\', res); })
-
挂断
// 销毁实例 rtcModule.destroyRtc((res) => { console.log("销毁实例", res); });
总结
当前逻辑基本实现呼叫邀请+通话
需要更详细,更具体,更全面的代码请前往 demo 源码 地址
- 注意事项
- RTM 初始化、RTC 初始化都只需要执行一次,多次执行请杀掉程序
- RTM 可以在 vue页面, RTC 视频容器必须在 nvue 页面
以上是关于uniapp实现app端图片+视频轮播的主要内容,如果未能解决你的问题,请参考以下文章
uniapp外包杯学习笔记day07 | 微信小程序轮播图分类导航楼层图的开发与实现