更新记录
2.6.0(2024-09-30)
下载此版本
更新iOS插件
0.0.2(2024-09-20)
下载此版本
更新文件和白板,接入更简单
0.1.0(2021-01-21)
下载此版本
支持涂鸦、文本、直线、矩形、椭圆、橡皮、激光笔等功能
音画同步
实时协作
查看更多
平台兼容性
Android
Android CPU类型
iOS
适用版本区间:5.0 - 14.0
armeabi-v7a:支持,arm64-v8a:支持,x86:未测试
适用版本区间:9 - 17
原生插件通用使用流程:
购买插件,选择该插件绑定的项目。
在HBuilderX里找到项目,在manifest的app原生插件配置中勾选模块,如需要填写参数则参考插件作者的文档添加。
根据插件作者的提供的文档开发代码,在代码中引用插件,调用插件功能。
打包自定义基座,选择插件,得到自定义基座,然后运行时选择自定义基座,进行log输出测试。
开发完毕后正式云打包
付费原生插件目前不支持离线打包。
Android 离线打包原生插件另见文档 https://nativesupport.dcloud.net.cn/NativePlugin/offline_package/android
iOS 离线打包原生插件另见文档 https://nativesupport.dcloud.net.cn/NativePlugin/offline_package/ios
注意事项:使用HBuilderX2.7.14以下版本,如果同一插件且同一appid下购买并绑定了多个包名,提交云打包界面提示包名绑定不一致时,需要在HBuilderX项目中manifest.json->“App原生插件配置”->”云端插件“列表中删除该插件重新选择
快速开始
这份文档将指导您如何在 uni-app 项目集成 超级白板 uniapp SDK 并快速开始创建一个纯白板。
准备环境
在开始集成超级白板 SDK 前,请确保开发环境满足以下要求:
参考 uni-app 文档创建项目。
HBuilderX 3.0.0 或以上版本。
IOS
Xcode 15.0 或以上版本。
iOS 12.0 或以上版本且支持音视频的 iOS 设备。
Android
Android Studio 2020.3.1 或以上版本。
Android SDK 25、Android SDK Build-Tools 25.0.2、Android SDK Platform-Tools 25.x.x 或以上版本。
Android 4.4 或以上版本,且支持音视频的 Android 设备。
设备已经连接到 Internet。
前提条件
已在 ZEGO 控制台 创建项目,并申请有效的 AppID 和 AppSign,详情请参考 控制台 - 项目信息。
联系 ZEGO 技术支持,开通文件相关服务。
填写配置文件
在 “common/KeyCenter.js.example” 文件中,填入本文 前提条件 已获取的 AppID 和 appSign。
实现流程
引入SDK
使用 HBuilderX 打开 manifest.json,重新生成一个 uni-app 应用标识。
创建自定义基座,填入 AppID。
[图片]
[图片]
注意:IOS 需要苹果开发者证书。为方便测试,可以暂时只勾选安卓端。
将插件市场的 ZEGO 即构实时音视频 SDK SDK 引入到项目中,并找到 manifest.json 中的 App 原生插件配置。
[图片]
[图片]
勾选上面购买的 ZEGO 即构实时音视频 SDK 并确认。
[图片]
将插件市场的 ZEGO superboard sdk 下载并导入 HBuilderX。
插件未发布,todo @马军福 @章聪
按照 rtc 流程截图补充
基本实现
引入白板 view 组件
在 vue 的 template 中使用 ZegoSuperboardContainerView 组件
引入 SDK 并初始化
引入 sdk 路径待更新,todo @马军福 @章聪
// 引入 sdk 路径待更新
import ZegoSuperBoardApp from "@/components/zego-ZegoSuperBoardUniApp-JS/lib/ZegoSuperBoardApp";
import ZegoExpressEngine from '@/uni_modules/zego-ZegoExpressUniApp-JS/components/zego-ZegoExpressUniApp-JS/lib/ZegoExpressEngine';
const appID = keyCenter.getAppID();
const appSign = keyCenter.getAppSign();
const userID = keyCenter.getUserID();
const userName = keyCenter.getUserName();
const roomID = keyCenter.getRoomID();
// 初始化 Express RTC SDK
// 使用从 ZEGO 控制台申请到的 appID 用于初始化
const profile = {
appID : xxx,
// AppSign 仅满足简单的鉴权需求,如果需要升级为更加安全的鉴权方式,请参考如何从 AppSign 鉴权升级为 Token 鉴权 // AppSign 可通过控制台 获取,格式为 @"39011cbxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
appSign: '39011cbxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
scenario : 0
};
ZegoExpressEngine.createEngineWithProfile(profile)
let roomConfig = {};
// 只有传入 “isUserStatusNotify” 参数取值为 “true” 的 ZegoRoomConfig,才能收到 onRoomUserUpdate 回调。
roomConfig.isUserStatusNotify = true;
// 登录房间
ZegoExpressEngine.instance().loginRoom(roomID, {'userID': userID, 'userName': userName}, roomConfig);
// 初始化超级白板 SDK
ZegoSuperBoardApp.init({
appID,
appSign,
userID,
});
// 设置白板容器
ZegoSuperBoardApp.setContainerView();
创建白板
var zegoSuperBoardSubView = ZegoSuperBoardApp.getInstance()
.getSuperBoardView()
.getCurrentSuperBoardSubView();
// 监听远端新增白板
ZegoSuperBoardApp.getInstance().on(
"remoteSuperBoardSubViewAdded",
function (name, createTime, fileID, fileType, uniqueID, whiteboardIDList) {}
);
// 创建白板
let params = {
perPageWidth: 640,
perPageHeight: 360,
pageCount: 10,
name: "白板名" + new Date().getTime(),
};
ZegoSuperBoardApp.getInstance().createWhiteboardView(params);
完整代码
RoomID:{{ roomID }}
{{ selectedOptionName !== "" ? selectedOptionName : "请选择" }}
<button type="default" @click="logout">退出</button>
<button type="default" @click="flipToPrePage">上一页</button>
{{ currentPage + "/" + pageCount }}
<button type="default" @click="flipToNextPage">下一页</button>
功能区
<button type="default" @click="createSuperBoardView">创建白板</button>
<button type="default" @click="setSuperBoardViewStyle">
设置白板样式
</button>
<button type="default" @click="getList">获取列表</button>
<button type="default" @click="undo">undo</button>
<button type="default" @click="redo">redo</button>
import { ref, onMounted, computed, onBeforeMount } from "vue";
import keyCenter from "@/common/KeyCenter.ts";
// 引入 sdk 路径待更新
import ZegoSuperBoardApp from "@/components/zego-ZegoSuperBoardUniApp-JS/lib/ZegoSuperBoardApp";
import ZegoExpressEngine from "@/components/zego-express-video-uniapp/lib/ZegoExpressEngine.js";
const appID = keyCenter.getAppID();
const appSign = keyCenter.getAppSign();
const userID = keyCenter.getUserID();
const userName = keyCenter.getUserName();
const roomID = keyCenter.getRoomID();
const containerview = ref(null);
const engine = ref(null);
const superboard = ref(null);
const curView = ref(null);
const currentPage = ref(0);
const pageCount = ref(0);
const options = ref([]);
const selectedOptionId = ref("");
const selectedOptionName = ref("");
const initRTC = async () => {
let profile = {
appID,
appSign,
scenario: 0,
};
engine.value = await ZegoExpressEngine.createEngineWithProfile(profile);
};
const loginRTCRoom = async () => {
let user = {
userID,
userName,
};
let config = {
isUserStatusNotify: true,
};
const result = await ZegoExpressEngine.instance().loginRoom(
roomID,
user,
config
);
};
const initSuperboad = async () => {
const superboard_init_res = await ZegoSuperBoardApp.init({
appID,
appSign,
userID,
});
console.log("init=", superboard_init_res);
superboard.value = ZegoSuperBoardApp.getInstance();
};
const setContainerView = async () => {
containerview.value.addSuperboardView();
// await ZegoSuperBoardApp.setContainerView();
};
// 窗口尺寸发生变化才需要调用
const updateContainerFrame = () => {
ZegoSuperBoardApp.updateContainerViewFrame();
};
const superboardEvent = () => {
// 监听白板翻页、滚动
var zegoSuperBoardSubView = superboard.value
.getSuperBoardView()
.getCurrentSuperBoardSubView();
superboard.value.on(
"scrollChange",
function (
name,
createTime,
fileID,
fileType,
uniqueID,
whiteboardIDList,
currentPage,
pageCount
) {
console.log("scrollChange", currentPage);
// SuperBoardView 每次滚动后都会回调这个方法
// 业务层可在这里更新界面的 页码/总页数 等信息
}
);
// 监听远端切换白板
superboard.value.on("remoteSuperBoardSubViewSwitched", function (uniqueID) {
// 收到远端切换白板文件。
// 可以根据当前 ZegoSuperBoardManager.getInstance().getSuperBoardView().getCurrentSuperBoardSubView() 的信息更新UI,如更新当前显示白板/文件名称。
});
// 监听远端新增白板
superboard.value.on(
"remoteSuperBoardSubViewAdded",
function (name, createTime, fileID, fileType, uniqueID, whiteboardIDList) {}
);
};
const logout = async () => {
await superboard.value.unInit()
await engine.value.logoutRoom(roomID);
uni.navigateTo({ url: "/pages/login/index" });
};
// 创建白板
const createSuperBoardView = async () => {
let params = {
perPageWidth: 640,
perPageHeight: 360,
pageCount: 10,
name: "白板名" + new Date().getTime(),
};
const res = await superboard.value.createWhiteboardView(params);
if (res.errorCode === 0) {
uni.showToast({
title: "创建白板成功",
icon: "success",
duration: 2000,
});
options.value.push({ uniqueID: res.uniqueID, name: res.name });
} else {
uni.showToast({
title: "创建白板失败:" + res.code,
icon: "none",
duration: 2000,
});
}
};
// 设置白板样式
const setSuperBoardViewStyle = async () => {
var zegoSuperBoardSubView = superboard.value
.getSuperBoardView()
.getCurrentSuperBoardSubView();
console.log("setSuperBoardViewStyle", !!zegoSuperBoardSubView);
if (zegoSuperBoardSubView) {
superboard.value.enableHandwriting(true);
// 画笔颜色,默认为红色
superboard.value.setBrushColor('#1016ff');
// 画笔粗细,默认为 6
superboard.value.setBrushSize(12);
// 设置白板背景颜色
zegoSuperBoardSubView.setWhiteboardBackgroundColor('#1016ff');
}
};
// 销毁白板
const destroySuperBoardSubView = async (uniqueID: string) => {
console.log("uniqueID", uniqueID);
try {
const res = await superboard.value.destroySuperBoardSubView(uniqueID);
if (res.errorCode === 0) {
uni.showToast({
title: "删除白板成功",
icon: "success",
duration: 2000,
});
updateList('delete', {uniqueID})
} else {
uni.showToast({
title: "删除白板失败:" + res.code,
icon: "none",
duration: 2000,
});
}
} catch (e) {
console.log("destroySuperBoardSubView:", e);
}
};
//翻上一页
const flipToPrePage = async () => {
var zegoSuperBoardSubView = superboard.value
.getSuperBoardView()
.getCurrentSuperBoardSubView();
if (zegoSuperBoardSubView) {
// 这里可以调用subView对应的接口进行翻页,以下是简单的示例
// 跳转上一页
zegoSuperBoardSubView.flipToPrePage();
}
};
// 翻下一页
const flipToNextPage = async () => {
var zegoSuperBoardSubView = superboard.value
.getSuperBoardView()
.getCurrentSuperBoardSubView();
if (zegoSuperBoardSubView) {
// 这里可以调用subView对应的接口进行翻页,以下是简单的示例
// 跳转下一页
zegoSuperBoardSubView.flipToNextPage();
}
};
// 撤销
const undo = async () => {
var zegoSuperBoardSubView = superboard.value
.getSuperBoardView()
.getCurrentSuperBoardSubView();
if (zegoSuperBoardSubView) {
zegoSuperBoardSubView.undo();
}
};
// 重做
const redo = async () => {
var zegoSuperBoardSubView = superboard.value
.getSuperBoardView()
.getCurrentSuperBoardSubView();
if (zegoSuperBoardSubView) {
zegoSuperBoardSubView.redo();
}
};
// 切换白板
const onWhitebopardChange = async (e) => {
try {
const index = e.detail.value;
// 根据索引值从选项数组中获取对应的选项
const selected = options.value[index];
selectedOptionId.value = selected.uniqueID; // 记录选中的id
selectedOptionName.value = selected.name; // 显示选中的name
var superBoardView = superboard.value.getSuperBoardView();
// 切换白板
superBoardView.switchSuperBoardSubView(selected.uniqueID)
} catch (errorData) {
console.error(errorData)
}
};
// 更新当前 view 相关数据
const updateCurView = async () => {
var zegoSuperBoardSubView = superboard.value
.getSuperBoardView()
.getCurrentSuperBoardSubView();
if (zegoSuperBoardSubView) {
curView.value = zegoSuperBoardSubView;
currentPage.value = await zegoSuperBoardSubView.getCurrentPage();
pageCount.value = await zegoSuperBoardSubView.getPageCount();
}
};
const updateList = (type: any, data?: any) => {
if (type === "add") {
options.value.push({ uniqueID: data.uniqueID, name: data.name });
} else {
options.value = options.value.filter(
(item) => item.uniqueID !== data.uniqueID
);
}
};
// 获取列表
const getList = async () => {
const list = await superboard.value.getSuperBoardSubViewModelList();
// 遍历 list 并更新 options 的数据
list.forEach((res: { uniqueID: any; name: any }) => {
updateList("add", res);
});
if (list.length !== 0) {
var zegoSuperBoardSubView = superboard.value
.getSuperBoardView()
.getCurrentSuperBoardSubView();
let view = await zegoSuperBoardSubView.getCurrentSuperBoardSubViewModel();
selectedOptionName.value = view.name;
selectedOptionId.value = view.uniqueID;
}
};
onMounted(async () => {
try {
await initRTC();
await loginRTCRoom();
await initSuperboad();
await setContainerView();
updateContainerFrame();
await getList();
await updateCurView();
superboardEvent();
} catch (e) {
console.error("demo error=", e);
}
});
<style>
.content {
}
.flex {
display: flex;
flex-wrap: wrap;
flex-direction: row;
align-items: center;
justify-content: space-between;
}
.flex-start {
justify-content: flex-start;
}
.containerview {
width: 750rpx;
height: 500rpx;
/* background-color: #ccc; */
}
.picker {
padding: 10px;
background-color: #f3f3f3;
text-align: center;
border: 1px solid #ddd;
border-radius: 5px;
}
</style>
配置入口与页面路由
根据业务场景为通话页配置入口。
AppID
<input class="zego-input" type="number" maxlength="-1" :value="appID" @input="bindAppIDChange" />
UserID
<input class="zego-input" maxlength="-1" :value="userID" @input="bindUserIDChange" />
UserName
<input class="zego-input" maxlength="-1" :value="userName" @input="bindUserNameChange" />
Appsign
<input class="zego-input" maxlength="-1" :value="appSign" @input="bindAppsignChange" />
RoomID
<input class="zego-input" maxlength="-1" :value="roomID" @input="bindRoomIDChange" />
<button type="default" @click="login">登录</button>
import { ref } from 'vue';
import keyCenter from '@/common/KeyCenter.ts';
const appID = ref(keyCenter.getAppID());
const userID = ref(keyCenter.getUserID());
const appSign = ref(keyCenter.getAppSign());
const roomID = ref(keyCenter.getRoomID());
const userName = ref(keyCenter.getUserName());
const bindAppIDChange = (e) => {
keyCenter.setAppID(e.detail.value);
};
const bindUserIDChange = (e) => {
keyCenter.setUserID(e.detail.value);
};
const bindAppsignChange = (e) => {
keyCenter.setAppSign(e.detail.value)
};
const bindRoomIDChange = (e) => {
keyCenter.setRoomID(e.detail.value);
};
const bindUserNameChange = (e)=>{
keyCenter.setUserName(e.detail.value);
}
const login = ()=>{
uni.navigateTo({ url: "/pages/index/index" })
}
<style lang="scss" scoped>
.zego-container {
background-color: #F4F4F4;
}
.zego-row-area {
flex-direction: row;
margin-left: 36.53rpx;
margin-right: 36.53rpx;
margin-top: 17.3rpx;
margin-bottom: 17.3rpx;
align-items: center;
justify-content: space-between;
}
.zego-row-area-2 {
margin-left: 36.53rpx;
margin-right: 36.53rpx;
margin-top: 17.3rpx;
margin-bottom: 17.3rpx;
}
.zego-input {
background-color: #FFFFFF;
border-radius: 9.61rpx;
border-color: #BBBBBB;
border-width: 1.92rpx;
border-style: solid;
color: #101010;
font-size: 26.92rpx;
height: 46.15rpx;
padding-left: 9.61rpx;
}
.zego-title-text {
color: #101010;
font-size: 26.92rpx;
}
</style>
打开 pages.json,添加 pages 配置
{
"pages": [
{
"path": "pages/login/index",
"style": {
"navigationBarTitleText": "login"
}
},
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "uni-app"
}
}
],
}
运行和测试
至此,您已经完成了所有步骤!
只需在 HBuilderX 中点击 运行到手机或模拟器 ,选择需要运行的端侧与基座,即可在设备上运行和测试您的应用程序。