创建 FastboardApp
let app = await createFastboard({
// 必填项只有下面这些
sdkConfig: {
appIdentifier: APPID,
region: "ch-hz",
},
joinRoom: {
uid: "unique_id",
uuid: ROOM_UUID,
roomToken: ROOM_TOKEN,
},
// 完整配置见下方
});
参数
name | type | desc |
---|---|---|
sdkConfig | [required] WhiteWebSdkConfiguration | SDK 配置 |
joinRoom | [required] JoinRoomParams | 加入房间配置 |
managerConfig | [optional] MountParams | WindowManager 配置 |
将 FastboardApp 挂载到 DOM
let ui = mount(app, document.getElementById("#board"));
ui.update({ theme: "dark", language: "zh-CN" });
ui.destroy();
参数
name | type | desc |
---|---|---|
app | [required] FastboardApp | 从 createFastboard 获取的 app 对象 |
dom | [required] HTMLElement | 挂载的 DOM 元素 |
opts | [optional] MountOptions | UI 配置 |
type MountOptions = {
// 默认 "light"
theme?: "light" | "dark";
// 默认 "en"
language?: "en" | "zh-CN";
// 具体配置每个组件是否显示
config?: {
toolbar?: { enable?: boolean; apps?: { enable?: boolean } };
redo_undo?: { enable?: boolean };
zoom_control?: { enable?: boolean };
page_control?: { enable?: boolean };
};
// 白板的 div 出现的时候会触发这个回调
containerRef?: (container: HTMLDivElement | null) => void;
};
返回值
type ReturnValue = {
// 更新 UI
update: (opts: MountOptions) => void;
// 卸载白板
destroy: () => void;
};
回放白板
let player = await replayFastboard({
// 必填项只有下面这些
sdkConfig: {
appIdentifier: APPID,
region: "ch-hz",
},
replayRoom: {
uid: "unique_id",
uuid: ROOM_UUID,
roomToken: ROOM_TOKEN,
},
// 完整配置见下方
});
参数
name | type | desc |
---|---|---|
sdkConfig | [required] WhiteWebSdkConfiguration | SDK 配置 |
replayRoom | [required] ReplayRoomParams | 回放配置 |
managerConfig | [optional] MountParams | WindowManager 配置 |
将 FastboardPlayer 挂载到 DOM
let ui = replay(player, document.getElementById("#board"));
ui.update({ theme: "dark", language: "zh-CN" });
ui.destroy();
参数
name | type | desc |
---|---|---|
player | [required] FastboardPlayer | 从 replayFastboard 获取的 player 对象 |
dom | [required] HTMLElement | 挂载的 DOM 元素 |
opts | [optional] ReplayProps | UI 配置 |
type ReplayProps = {
// 默认 "light"
theme?: "light" | "dark";
// 默认 "en"
language?: "en" | "zh-CN";
// 白板的 div 出现的时候会触发这个回调
containerRef?: (container: HTMLDivElement | null) => void;
};
返回值
type ReturnValue = {
// 更新 UI
update: (opts: ReplayProps) => void;
// 卸载白板
destroy: () => void;
};
控制 Apps 菜单内容的单例对象
// 例子:插入一个 YouTube 按钮,其功能是插入 Plyr 播放器播放指定地址的视频
apps.push({
icon: "https://api.iconify.design/logos:youtube-icon.svg?color=currentColor",
kind: "Plyr",
label: "YouTube",
onClick(app) {
app.manager.addApp({
kind: "Plyr",
options: { title: "YouTube" },
attributes: {
src: "https://www.youtube.com/embed/bTqVqk7FSmY",
provider: "youtube",
},
});
},
});
接口
// 在最后增加一个按钮
apps.push({
icon: "按钮图标地址",
kind: "唯一标识符",
label: "显示在按钮下面的文字",
onClick(app) {
// 点击时触发的回调
},
});
// 在指定位置插入一个按钮
apps.insert({ icon, kind, label, onClick }, 0);
// 删掉指定按钮
apps.delete(config => config.kind === "Plyr");
// 删掉所有按钮
// 注意这不会导致工具栏上的 Apps 按钮消失,请通过 config.toolbar.apps.enable 设置
apps.clear();
在 React Hooks 里辅助调用
createFastboard
的 hook
function App {
const app = useFastboard(() => ({
// 必填项只有下面这些
sdkConfig: {
appIdentifier: APPID,
region: "ch-hz",
},
joinRoom: {
uid: "unique_id",
uuid: ROOM_UUID,
roomToken: ROOM_TOKEN,
},
// 完整配置见 createFastboard
}));
const [uiConfig] = useState(() => ({
page_control: { enable: true },
redo_undo: { enable: true },
toolbar: { enable: true, apps: { enable: true } },
zoom_control: { enable: true }
}));
return <Fastboard app={app} language="en" theme="dark" config={uiConfig} />;
}
参数
name | type | desc |
---|---|---|
config | [required] () => FastboardOptions | 见 createFastboard 的参数 |
在 React Hooks 里辅助调用
replayFastboard
的 hook
function App {
const player = useReplayFastboard(() => ({
// 必填项只有下面这些
sdkConfig: {
appIdentifier: APPID,
region: "ch-hz",
},
replayRoom: {
uid: "unique_id",
uuid: ROOM_UUID,
roomToken: ROOM_TOKEN,
},
// 完整配置见 replayFastboard
}));
return <ReplayFastboard player={player} language="en" theme="dark" />;
}
参数
name | type | desc |
---|---|---|
config | [required] () => FastboardReplayOptions | 见 replayFastboard 的参数 |
绑定白板到 DOM(注意,这里只有白板本身,不包含任何外部组件)
app.bindContainer(document.getElementById("whiteboard"));
参数
name | type | desc |
---|---|---|
dom | [required] HTMLElement | 挂载白板的 DOM 元素 |
修改 WindowManager 的
抽屉的位置
app.bindCollector(document.getElementById("#collector"));
参数
name | type | desc |
---|---|---|
dom | [required] HTMLElement | 挂载 collector 的 DOM 元素 |
撤销
app.undo();
重做
app.redo();
移动视角
app.moveCamera({ centerX: 0, centerY: 0, scale: 1 });
参数
name | type | default | desc |
---|---|---|---|
centerX | [optional] number | 0 | 视角的中心对准的点的 x 坐标(世界坐标系) |
centerY | [optional] number | 0 | 视角的中心对准的点的 y 坐标(世界坐标系) |
scale | [optional] number | 1 | 缩放 |
移动视角到包含一个区域
app.moveCameraToContain({ originX: -100, originY: -100, width: 200, height: 200 });
参数
name | type | desc |
---|---|---|
originX | [required] number | 左上角 X |
originY | [required] number | 左上角 Y |
width | [required] number | 宽 |
height | [required] number | 高 |
清空当前选中场景
app.cleanCurrentScene();
设置教具
app.setAppliance("pencil");
app.setAppliance("shape", "triangle");
参数
name | type | desc |
---|---|---|
appliance | [required] ApplianceNames | 教具 |
shape | [optional] ShapeType | 当 appliance 是 shape 时,用的形状 |
类型
enum ApplianceNames {
selector = "selector",
clicker = "clicker",
laserPointer = "laserPointer",
pencil = "pencil",
rectangle = "rectangle",
ellipse = "ellipse",
shape = "shape",
eraser = "eraser",
text = "text",
straight = "straight",
arrow = "arrow",
hand = "hand",
}
enum ShapeType {
Triangle = "triangle",
Rhombus = "rhombus",
Pentagram = "pentagram",
SpeechBalloon = "speechBalloon",
}
设置笔触宽度
app.setStrokeWidth(1);
设置笔触颜色
app.setStrokeColor([255, 0, 0]); // 红色
设置文字颜色
app.setTextColor([255, 0, 0]); // 红色
设置文字大小
app.setTextSize(16);
插入图片
await app.insertImage("cdn/path/to/image");
参数
name | type | desc |
---|---|---|
url | string | 图片地址 |
插入 PDF / PPT
const appId = await app.insertDocs("文件名.pptx", conversionResponse);
参数
name | type | desc |
---|---|---|
title | string | 窗口标题 |
response | ConversionResponse | 转码结果 |
返回的 appId 见 WindowManager 文档。
插入音视频
const appId = await app.insertMedia("文件名.mp3", url);
参数
name | type | desc |
---|---|---|
title | string | 窗口标题 |
url | string | 音视频地址 |
类型
export type FastboardDisposer = () => void;
export interface FastboardReadable<T> {
readonly value: T;
subscribe(callback: (value: T) => void): FastboardDisposer;
reaction(callback: (value: T) => void): FastboardDisposer;
}
export interface FastboardWritable<T, SetFn = (value: T) => void> extends FastboardReadable<T> {
setValue: SetFn;
}
当前房间是否可写,理论上,不可写时要将所有 UI 组件禁用
app.writable.value; // true | false
app.writable.set(false); // 切换到不可写状态
app.writable.subscribe(value => {
// value 变化时触发
});
类型
type writable = FastboardWritable<boolean>;
App 窗口状态
类型
type boxState = FastboardReadable<"normal" | "minimized" | "maximized" | undefined>;
当前选中的 App
类型
type focusedApp = FastboardReadable<string | undefined>;
能重做的步数
类型
type canRedoSteps = FastboardReadable<number>;
能撤销的步数
类型
type canUndoSteps = FastboardReadable<number>;
视角
类型
type camera = FastboardReadable<Camera>;
type Camera = {
centerX: number;
centerY: number;
scale: number;
};
用户状态(正在用的教具之类)
类型
type memberState = FastboardReadable<MemberState>;
type MemberState = {
currentApplianceName: ApplianceNames;
strokeColor: Color;
textColor?: Color;
strokeWidth: number;
textSize: number;
bold?: boolean;
italic?: boolean;
underline?: boolean;
lineThrough?: boolean;
shapeType?: ShapeType;
};
场景下标
类型
type sceneIndex = FastboardReadable<number>;
场景数量
类型
type sceneLength = FastboardReadable<number>;
app 加载状态
类型
type appsStatus = FastboardReadable<AppsStatus>;
type AppsStatus = {
[kind: string]: {
status: "idle" | "loading" | "failed";
reason?: string;
};
};