A starter library for making whiteboard web app, based on white-web-sdk, @netless/window-manager and netless-app.
npm add @netless/fastboard @netless/window-manager white-web-sdk
Note:
@netless/window-manager
andwhite-web-sdk
are peerDependencies.
import { createFastboard, createUI } from "@netless/fastboard";
async function main() {
const fastboard = await createFastboard({
// [1]
sdkConfig: {
appIdentifier: "whiteboard-appid",
region: "us-sv", // "cn-hz" | "us-sv" | "sg" | "in-mum" | "gb-lon"
},
// [2]
joinRoom: {
uid: "unique_id_for_each_client",
uuid: "room-uuid",
roomToken: "NETLESSROOM_...",
// (optional)
userPayload: {
nickName: "foo",
},
},
// [3] (optional)
managerConfig: {
cursor: true,
},
// [4] (optional)
netlessApps: [],
});
const container = createContainer();
const ui = createUI(fastboard, container);
// .....
// destroy Fastboard UI
ui.destroy();
// .....
// destroy Fastboard (disconnect from the whiteboard room)
fastboard.destroy();
}
function createContainer() {
const container = document.createElement("div");
// Must give it a visible size
Object.assign(container.style, {
height: "400px",
border: "1px solid",
background: "#f1f2f3",
});
document.body.appendChild(container);
return container;
}
main().catch(console.error);
[1] Read more about the SDK config at Construct WhiteWebSDK object
[2] Read more about join room config at Construct Room and Player objects
[3] Read more about WindowManager config at WindowManager.mount()
Install @netless/fastboard-react
, use the <Fastboard />
component.
npm add @netless/fastboard-react @netless/window-manager white-web-sdk react react-dom
import { useFastboard, Fastboard } from "@netless/fastboard-react";
import React from "react";
import { createRoot } from "react-dom/client";
function App() {
const fastboard = useFastboard(() => ({
sdkConfig: {
appIdentifier: "whiteboard-appid",
region: "us-sv", // "cn-hz" | "us-sv" | "sg" | "in-mum" | "gb-lon"
},
joinRoom: {
uid: "unique_id_for_each_client",
uuid: "room-uuid",
roomToken: "NETLESSROOM_...",
},
}));
// Container must have a visible size
return (
<div
style={{
height: "400px",
border: "1px solid",
background: "#f1f2f3",
}}
>
<Fastboard app={fastboard} />
</div>
);
}
createRoot(document.getElementById("app")).render(<App />);
await fastboard.insertImage(fileUrl);
The fileUrl
is the url to load the image file, like "src" in <img src>
.
Fastboard itself does not contain any logic about upload/save a file.
fastboard.undo();
fastboard.redo();
fastboard.moveCamera({ centerX: 0, centerY: 0, scale: 1 });
fastboard.moveCameraToContain({ originX: -300, originY: -200, width: 600, height: 400 });
fastboard.setAppliance("pencil");
fastboard.setAppliance("shape", "triangle");
fastboard.setStrokeWidth(2);
fastboard.setStrokeColor([r, g, b]);
Except for built-in apps in Fastboard, you can also insert your own apps. To do that,
You have to register app at each client before entering room (createFastboard
):
import { register } from "@netless/fastboard";
import MyApp from "my-app";
register({ kind: MyApp.kind, src: MyApp });
Or you can set netlessApps
in createFastboard
config:
createFastboard({
..., // other config
netlessApps: [MyApp],
});
Then add app into the room via:
fastboard.manager.addApp({ kind: MyApp.kind });
// insert PDF/PPT/PPTX to the main whiteboard
const appId = await fastboard.insertDocs("filename.pptx", conversionResponse);
The conversionResponse
is the result of this api.
Note: If you're using the new projector api, please use the manual way:
const appId = await fastboard.insertDocs({ fileType: "pptx", scenePath: `/pptx/${response.uuid}`, taskId: response.uuid, title: "filename.pptx", });
const appId = await fastboard.insertMedia("filename.mp3", fileUrl);
The fileUrl
is the url to load the media file, like "src" in <video src>
.
Fastboard itself does not contain any logic about upload/save a file.
Insert @netless/app-monaco
const appId = await fastboard.manager.addApp({
kind: "Monaco",
options: { title: "Code Editor" },
});
Insert @netless/app-countdown
const appId = await fastboard.manager.addApp({
kind: "Countdown",
options: { title: "Countdown" },
});
Insert @netless/app-geogebra
const appId = await fastboard.manager.addApp({
kind: "GeoGebra",
options: { title: "GeoGebra" },
});
Insert @netless/app-plyr
const appId = await fastboard.manager.addApp({
kind: "Plyr",
options: { title: "YouTube" },
attributes: {
src: "https://www.youtube.com/embed/bTqVqk7FSmY",
provider: "youtube",
},
});
Insert @netless/app-embedded-page
const appId = await fastboard.manager.addApp({
kind: "EmbeddedPage",
options: { title: "Google Docs" },
attributes: {
src: "https://docs.google.com/document/d/1bd4SRb5BmTUjPGrFxU2V7KI2g_mQ-HQUBxKTxsEn5e4/edit?usp=sharing",
},
});
Note: EmbeddedPage uses
<iframe>
to display external web resources, you'd better not embedding 2 more nested iframes (i.e. webpage>iframe1>iframe2) in the same page.
More apps goto netless-app.
MIT @ netless