Displayer
是一个抽象接口,是 Room
和 Player
的父接口。其定义如下。
interface Displayer {
readonly callbacks: Callbacks<DisplayerCallbacks>;
readonly observerId: number;
readonly slice?: string;
readonly deviceType: DeviceType;
readonly screenType: ScreenType;
readonly state: DisplayerState;
readonly enableWriteNow: boolean;
readonly handToolKey: string | undefined;
handToolActive: boolean;
disableCameraTransform: boolean;
refreshViewSize(): void;
setCameraBound(cameraBound: CameraBound): void;
memberState(memberId: number): MemberState;
moveCamera(camera: Partial<Camera> & Readonly<{animationMode?: AnimationMode}>): void;
moveCameraToContain(rectangle: Rectangle & Readonly<{animationMode?: AnimationMode}>): void;
bindHtmlElement(element: HTMLDivElement | null): void;
convertToPointInWorld(point: {x: number, y: number}): {x: number, y: number};
scenePreview(scenePath: string, div: HTMLElement, width: number | undefined, height: number | undefined): void;
generateScreenshot(scenePath?: string, width?: number, height?: number): Promise<string>;
fillSceneSnapshot(scenePath: string, div: HTMLElement, width: number, height: number): void;
addMagixEventListener(event: string, listener: EventListener): void;
addMagixEventListener(event: string, listener: EventsListener, fireInterval: number): void;
removeMagixEventListener(event: string, listener?: EventListener): void;
waitMagixEvent(filter: EventFilter): Promise<Event>;
scalePptToFit(animationMode?: AnimationMode): void;
scenePathType(path: string): ScenePathType;
entireScenes(): SceneMap;
}
回调方法管理器。通过如下方法可以注册对特定事件的回调方法。
displayer.callbacks.on("onSliceChanged", function(slice) {
console.log("slice uuid change to: " + slice);
});
也可以注销之前注册的回调方法。
function onSliceChanged(slice) {
console.log("slice uuid change to: " + slice);
}
// 注册回调方法
displayer.callbacks.on("onSliceChanged", onSliceChanged);
// 注销回调方法
displayer.callbacks.off("onSliceChanged", onSliceChanged);
也可以不指定回调方法,注销之前注册过的所有回调方法。
room.callbacks.off("onSliceChanged");
也可以注册一个一次性回调,该回调会在首次调用后,自动注销自己。
displayer.callbacks.once("onSliceChanged", function(slice) {
console.log("slice uuid change to: " + slice);
});
表示当前用户自己的 ID。对于 room.observerId
而言,每次加入房间时,会分配一个 observerId
,直到离开时释放。如果房间发生断线重连,则可能发生变化。
对于 player.observerId
而言,则满足如下公式。
import {AdminObserverId} from "white-web-sdk";
// 永远打印 true
console.log(player.observerId === AdminObserverId);
对于 room.slice
而言,表示此时此刻的实时房间房间内容正被录到的片段的 uuid
。若当前房间没有开启自动录制,则该值是一个无意义的字符串。
对于 player.slice
而言,表示此时此刻播放的录制片段的 uuid
。若 player
没有切换到任何一个录制片段,则返回 undefined
。
客户端的设备类型,其类型为 DeviceType,定义如下。
enum DeviceType {
// 桌面端设备,如 PC、笔记本电脑
Desktop = "desktop",
// 触摸设备,如智能手机、平板电脑
Touch = "touch",
// 同时支持键盘鼠标和触摸屏的设备
Surface = "surface",
}
客户端的屏幕类型,其类型 ScreenType 的定义如下。
enum ScreenType {
// 桌面端屏幕,如 PC、笔记本电脑
Desktop = "desktop",
// 智能手机
Phone = "phone",
// 平板电脑
Pad = "pad",
// 电视
TV = "tv",
}
业务状态类型,含义由其实例的继承并覆写。
当前是否允许进行写操作。对于 room
而言,仅在获取「可写」权限,且房间状态 room.phase
为 RoomPhase.Connected
的情况下,该值取值为 true
。对于 player
而言,永远为 false
。
手工具热键。按下该键时,会自动切换成抓手工具(currentApplianceName="hand"
),松开后,切回原来的工具。如果不传,则关闭该功能。
是否进入了抓手状态,修改它可以调整当前工具状态。
是否禁止设备主动操作视角,修改它可以禁止 / 开放设备操作视角。
refreshViewSize(): void;
在开启「自动适配尺寸」模式时,该方法不会有任何效果。关闭后,每当白板的 view 的尺寸改变时,必须主动调用 displayer.refreshViewSize()
以适配。
你可以在调用 whiteWebSdk.joinRoom
或 whiteWebSdk.replayRoom
时,在第一参数中加入 disableAutoResize: true
来关闭「自动适配尺寸」模式。
在实际操作中,我们往往发现,浏览器尺寸发生变化时,白板的尺寸也会跟着变化。如果此时我们关闭了「自动适配尺寸」功能,我们需要添加如下代码来手动适配尺寸。
window.addEventListener("resize", function() {
displayer.refreshViewSize();
});
该方法仅用于手动适配尺寸模式。如果你使用的 SDK 不低于
2.9.11
,则可以无视这个方法,因为你的 SDK 可以自动适配尺寸。
setCameraBound(cameraBound: CameraBound): void
修改视角边界。用户的视角会被限制于此范围,超出该范围后,视角会被拉回。其类型 CameraBound
定义如下。
type CameraBound = {
// 当画面突破边界时的阻尼大小,取值范围为 0.0 ~ 1.0
// 越大,阻尼越大,取 1.0 时,无论怎么拉,视角都无法突破边界
// 越小,阻尼越小,取 0.0 时,视角可以被毫无阻力地拉出边界,只有松手的时候才会弹回
// 默认值是 0.75
readonly damping?: number;
// 边界的中心点在世界坐标系中的 x 坐标
// 默认值是 0.0
readonly centerX?: number;
// 边界的中心点在世界坐标系中的 y 坐标
// 默认值是 0.0
readonly centerY?: number;
// 边界在世界坐标系中的宽,如果取 Infinity,则表示不对横向设限制
// 默认值是 Infinity
readonly width?: number;
// 边界在世界坐标系中的高,如果取 Infinity,则表示不对纵向设限制
// 默认值是 Infinity
readonly height?: number;
// 对视角放大的限制模式
// 不填是没有限制
readonly maxContentMode: ContentMode;
// 对视角缩小的限制模式
// 不填是没有限制
readonly minContentMode: ContentMode;
}
其中 ContentMode
用于设置视角对放缩的限制,我们可以通过如下方式设置。
import sdk from "white-web-sdk";
// scale 取值为 2.5
sdk.contentModeScale(2.5);
// 放缩到边界矩形的短边刚好顶住屏幕的程度
sdk.contentModeAspectFill();
// 边界矩形的短边刚好顶住屏幕的程度,在此基础上再放缩 2.5 倍
sdk.contentModeAspectFillScale(2.5);
// 放缩到刚好能在屏幕上看到完整的边界矩形的程度
sdk.contentModeAspectFit();
// 刚好能在屏幕上看到完整的边界矩形的程度,在此基础上再放缩 0.75 倍
sdk.contentModeAspectFitScale(0.75);
// 放缩到刚好能在屏幕上看到完整的边界矩形,并在周围预留 120 px 的空白空间的时候
sdk.contentModeAspectFitSpace(120);
memberState(memberId: number): MemberState;
读取特定用户的 MemberState
。
moveCamera(camera: Partial<Camera> & Readonly<{animationMode?: AnimationMode}>): void;
移动视角到指定位置。若此时白板在适配某个视觉矩形,该操作会清除这个视觉矩形。
其中参数 camera
的类型定义为。
{
// 视角中心对准的点在世界坐标系中的 x 轴坐标
readonly centerX: number;
// 视角中心对准的点在世界坐标系中的 y 轴坐标
readonly centerY: number;
// 视角放大比例
readonly scale: number;
// 视角以何种方式过度(默认值为 AnimationMode.Immediately)
readonly animationMode?: AnimationMode;
}
enum AnimationMode {
// 以平滑移动的方式过度
Continuous = "continuous",
// 一瞬间跳转到目标
Immediately = "immediately"
}
moveCameraToContain(rectangle: Rectangle & Readonly<{animationMode?: AnimationMode}>): void;
调整当前视角以适配指定的「视觉矩形」。在调完该方法后,若白板的尺寸改变,白板会一直适配该视觉矩形。但是,需注意,下列操作会清除并终止白板适配该视觉矩形。
displayer.moveCamera({...})
方法其中参数 rectangle
的类型定义为。
{
// 视觉矩形的左上角在世界坐标系中的 x 轴坐标
readonly originX: number;
// 视觉矩形的左上角在世界坐标系中的 y 轴坐标
readonly originY: number;
// 视觉矩形在世界坐标系中宽
readonly width: number;
// 视觉矩形在世界坐标系中高
readonly height: number;
// 视角以何种方式过度(默认值为 AnimationMode.Immediately)
readonly animationMode?: AnimationMode;
}
enum AnimationMode {
// 以平滑移动的方式过度
Continuous = "continuous",
// 一瞬间跳转到目标
Immediately = "immediately"
}
bindHtmlElement(element: HTMLDivElement | null): void
该方法会将白板绑定到特定的 Dom 节点,将其展示出来。
如下代码可以将白板展示在 ID 为 my-whiteboard
的 <div>
节点上。
displayer.bindHtmlElement(document.getElementById("my-whiteboard"));
如下代码可以将白板取消绑定。
displayer.bindHtmlElement(null);
绑定的 <div>
节点不应该包含子元素,也不要将多个 displayer
绑定到同一个 <div>
节点上。否则可能造成意想不到的后果。
convertToPointInWorld(point: {x: number, y: number}): {x: number, y: number};
将白板上的坐标转化成世界坐标。白板上的坐标系是:以白板左上角为原点,横向向右为 x 轴,纵向向下为 y 轴建立的坐标系。
fillSceneSnapshot(scenePath: string, div: HTMLElement, width: number, height: number): void;
将指定场景 scenePath
拍一张快照(可视为截图),并填充到 div
对应的 DOM 节点中。该快照的宽为 width
,高为 height
。
addMagixEventListener(event: string, listener: EventListener): void;
添加监听器,以监听名为 event
的自定义事件。该方法的监听器类型 EventListener
定义如下。
type EventListener = (event: Event) => void;
type Event = {
// 事件名
readonly event: string;
// 事件载荷
readonly payload: any;
// 抛出事件的用户 ID
readonly authorId: number;
}
addMagixEventListener(event: string, listener: EventsListener, fireInterval: number): void;
添加监听器,以监听名为 event
的自定义事件。并将间隔不超过 fireInterval
毫秒的事件组合成一个数组,打包回调。该方法的监听器类型 EventsListener
定义如下。
type EventsListener = (events: Event[]) => void;
removeMagixEventListener(event: string, listener?: EventListener): void;
删除监听器。若 listener
为 undefined
,则删除所有名为 event
的监听器。
waitMagixEvent(filter: EventFilter): Promise<Event>;
调用后,立即开始过滤每一个接收到的自定义事件,并将其传入 filter
进行测试。一旦 filter
返回 true
,则表示找到符合条件的事件。该方法返回一个 Promise<Event>
,等到找到符合条件的事件后就进行下一步。找到符合条件的事件后,停止过滤接收到的事件,整个流程结束。
其中 EventFilter
的定义如下。
type EventFilter = (event: Event) => boolean;
我们可以通过如下代码监听某个事件。
var filter = function(event) {
return event.event === "foobar" && event.payload.count > 10;
};
displayer.waitMagixEvent(filter).then(function(event) {
// 得到满足条件的自定义事件,流程结束
});
scalePptToFit(animationMode?: AnimationMode): void;
如果当前场景有 PPT,则放缩视角以刚好匹配 PPT(令 PPT 的长边刚好顶住屏幕的短边)。如果当前场景没有 PPT,则什么都不做。
该操作如果成功,则会让屏幕锁定以 PPT 所在的矩形作为的「视觉矩形」。该方法可以传类型为 AnimationMode
的参数,若不传,则默认值为 AnimationMode.Immediately
。类型定义如下。
enum AnimationMode {
// 以平滑移动的方式过度
Continuous = "continuous",
// 一瞬间跳转到目标
Immediately = "immediately"
}
scenePathType(path: string): ScenePathType;
获取地址为 path
的场景类型。返回值类型为 ScenePathType
,定义如下。
enum ScenePathType {
// 该场景不存在
None = "none",
// 这是一个场景组
Dir = "dir",
// 这是一个场景
Page = "page",
}
entireScenes(): SceneMap;
列出所有场景。返回值类型为 SceneMap
,定义如下。
type SceneMap = {
readonly [path: string]: Scene[];
}
type Scene = {
// 场景名
readonly name: string;
// 当前场景中有多少组建
readonly componentsCount: number;
// 当前场景中包含的 PPT 描述
readonly ppt?: PptDescription;
}