更新记录

2.6.0(2024-09-20) 下载此版本

  1. 超级白板原生插件JS封装层

平台兼容性

Vue2 Vue3
×
App 快应用 微信小程序 支付宝小程序 百度小程序 字节小程序 QQ小程序
HBuilderX 3.7.9 × × × × × ×
钉钉小程序 快手小程序 飞书小程序 京东小程序
× × × ×
H5-Safari Android Browser 微信浏览器(Android) QQ浏览器(Android) Chrome IE Edge Firefox PC-Safari
× × × × × × × × ×

快速开始

这份文档将指导您如何在 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
    1. 使用 HBuilderX 打开 manifest.json,重新生成一个 uni-app 应用标识。
    2. 创建自定义基座,填入 AppID。

[图片]

[图片] 注意:IOS 需要苹果开发者证书。为方便测试,可以暂时只勾选安卓端。

  1. 将插件市场的 ZEGO 即构实时音视频 SDK SDK 引入到项目中,并找到 manifest.json 中的 App 原生插件配置。

[图片]

[图片]

勾选上面购买的 ZEGO 即构实时音视频 SDK 并确认。 [图片]

  1. 将插件市场的 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);

完整代码

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>
  1. 配置入口与页面路由

根据业务场景为通话页配置入口。

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 中点击 运行到手机或模拟器 ,选择需要运行的端侧与基座,即可在设备上运行和测试您的应用程序。

隐私、权限声明

1. 本插件需要申请的系统权限列表:

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

许可协议

MIT协议

暂无用户评论。

使用中有什么不明白的地方,就向插件作者提问吧~ 我要提问