Whiteboard
This guide covers whiteboard initialization, toolbar operations, navigation, courseware management, and permission control.
Initialization
Automatic Initialization (Recommended)
Pass board.domId in the constructor. The whiteboard initializes automatically when joining a classroom:
const classroom = new TencentClassroom({
board: {
domId: 'board-container', // Whiteboard mount container DOM ID
ratio: '16:9', // Aspect ratio
style: {
brushColor: '#ff0000',
brushThin: 100,
},
},
});Manual Initialization
If board.domId was not set in the constructor, initialize manually after joining:
const result = await classroom.initBoard({
domId: 'board-container',
ratio: '16:9',
});
if (!result.ok) {
console.error('Board initialization failed:', result.message);
}Whiteboard Ready State
// Subscribe to board readiness
classroom.state.boardReady$.subscribe(ready => {
if (ready) {
console.log('Whiteboard is ready');
}
});
// Listen for board ready event
classroom.on(TEvent.BOARD_READY, () => {
console.log('Whiteboard history sync complete');
});
// Listen for board errors
classroom.on(TEvent.BOARD_ERROR, ({ code, message }) => {
console.error(`Board error [${code}]:`, message);
});Toolbar Operations
Set Active Tool
import { BoardToolType } from '@tencent-classroom/sdk';
classroom.setBoardToolType(BoardToolType.Pen); // Freehand pen
classroom.setBoardToolType(BoardToolType.Mouse); // Select/pointer
classroom.setBoardToolType(BoardToolType.Text); // Text input
classroom.setBoardToolType(BoardToolType.Eraser); // Eraser
classroom.setBoardToolType(BoardToolType.Laser); // Laser pointer
classroom.setBoardToolType(BoardToolType.Line); // Straight line
classroom.setBoardToolType(BoardToolType.Rect); // Rectangle
classroom.setBoardToolType(BoardToolType.ZoomDrag); // Pan and zoomBrush Settings
// Set brush color
classroom.setBrushColor('#ff0000');
// Set brush thickness
classroom.setBrushThin(100);
// Enable/disable handwriting effect
classroom.setHandwritingEnable(true);Text Settings
// Text style (0=normal, 1=bold, 2=italic, 3=bold+italic)
classroom.setTextStyle(1);
// Text size
classroom.setTextSize(24);
// Text color
classroom.setTextColor('#333333');Drawing Permission
// Enable/disable drawing
classroom.setBoardDrawEnable(true);
classroom.setBoardDrawEnable(false);Undo / Redo / Clear
classroom.undoBoard(); // Undo
classroom.redoBoard(); // Redo
classroom.clearBoard(); // Clear current pageNavigation & Zoom
Page Navigation
// Previous / next page
classroom.prevBoard();
classroom.nextBoard();
// Jump to a specific page number
classroom.gotoBoardPage(3);
// Get current page and total pages
const currentPage = classroom.getBoardCurrentPage();
const totalPages = classroom.getBoardTotalPages();
console.log(`Page ${currentPage} / ${totalPages}`);Zoom
// Get current scale factor
const scale = classroom.getBoardScale();
// Set scale factor
classroom.setBoardScale(150); // 150%
// Set zoom anchor point
classroom.setScaleAnchor(0.5, 0.5); // Center zoomContent Fit Mode
import { BoardFitMode } from '@tencent-classroom/sdk';
classroom.setBoardContentFitMode(BoardFitMode.Contain);Background
// Set background color
classroom.setBoardBackgroundColor('#f5f5f5');
// Set background image
classroom.setBoardBackgroundImage('https://example.com/bg.png');Courseware Management
Upload Courseware
import { CoursewarePermission, TEvent } from '@tencent-classroom/sdk';
const result = await classroom.uploadCourseware({
file: selectedFile,
schoolId: 100,
permission: CoursewarePermission.Private,
docType: 'pptx',
onReady: (taskId) => {
console.log('Upload task ID:', taskId);
},
onProgress: (loaded, total, speed, percent) => {
console.log(`Upload progress: ${Math.round(percent * 100)}%`);
},
});
if (!result.ok) {
console.error('Upload failed:', result.message);
return;
}
console.log('Upload complete, docId:', result.data.docId);Listen for Upload/Transcode Progress
classroom.on(TEvent.DOC_UPLOAD_PROGRESS, (progress) => {
switch (progress.status) {
case UploadTrackStatus.Uploading:
setUploadBar(progress.filePercent);
break;
case UploadTrackStatus.Transcoding:
setTranscodeBar(progress.transcodeProgress);
break;
case UploadTrackStatus.Completed:
showToast('Courseware ready');
break;
case UploadTrackStatus.Failed:
showError('Courseware processing failed');
break;
}
});Load Courseware to Board
// Load courseware to whiteboard
classroom.loadCourseware(docInfo);
// Force reload (refresh at class start)
classroom.loadCourseware(docInfo, true);Courseware List Management
// Get current classroom's courseware list (schoolId/classId filled automatically by SDK)
const listResult = await classroom.getClassCoursewares({
page: 1,
limit: 20,
});
if (listResult.ok) {
console.log('Courseware list:', listResult.data.documents);
}
// Get school courseware library (for search/management scenarios)
const schoolDocs = await classroom.getSchoolCoursewares({
page: 1,
limit: 20,
permission: [0, 1], // [0]=private [1]=public
keyword: 'Chapter 1',
});
// Delete courseware
await classroom.deleteDocument('doc_001');
// Bind courseware to classroom
await classroom.bindDocumentToClass('doc_001');
// Unbind
await classroom.unbindDocumentFromClass('doc_001');File Format Validation
// Validate file format and size before upload (sync, no network request)
const validateResult = classroom.validateUploadFile(file);
if (!validateResult.ok) {
showToast(validateResult.message); // e.g. "Unsupported file format"
return;
}Board File Operations
// Add a transcoded file
const fileId = classroom.addBoardTranscodeFile(transcodeResult);
// Add image files
classroom.addBoardImagesFile(['url1.png', 'url2.png'], 'Image Collection');
// Add video file
classroom.addBoardVideoFile('https://example.com/video.mp4', 'Lecture Video');
// Switch to a file
classroom.switchBoardFile(fileId);
// Delete a file
classroom.deleteBoardFile(fileId);
// Get file list
const fileList = classroom.getBoardFileInfoList();Whiteboard Permission Control
Role Capabilities
| Capability | Teacher | Assistant | Student | Supervisor |
|---|---|---|---|---|
| Drawing | ✅ | ✅ | Requires grant | ❌ |
| Toolbar tools | ✅ | ✅ | Requires grant | ❌ |
| Page navigation | ✅ | ✅ | Requires grant | ❌ |
| Load courseware | ✅ | ✅ | ❌ | ❌ |
| View whiteboard | ✅ | ✅ | ✅ | ✅ |
| H5 PPT interaction (click video/popup) | ✅ | ✅ | ✅ | ✅ |
- Teacher/Assistant: Full whiteboard permission by default on join
- Student: No whiteboard permission by default (view-only); teacher must grant permission for drawing and tools
- Supervisor: View-only, no operations allowed
Permission Check
// Check whiteboard permission (drawing, tools, navigation — all board operations)
classroom.canOperateBoard(); // => boolean
// Subscribe to whiteboard permission changes
classroom.state.boardPermission$.subscribe((hasPermission) => {
if (hasPermission) {
showBoardToolbar(); // Show toolbar
} else {
hideBoardToolbar(); // Hide toolbar
}
});Unified Whiteboard Permission
The backend issues a single board permission field covering drawing, tool switching, page navigation, and all other whiteboard operations.
Dynamic Permission Grant / Revoke
Teachers/assistants can dynamically grant or revoke whiteboard permission for students via memberAction:
import { MemberActionType } from '@tencent-classroom/sdk';
// Grant whiteboard permission to a student
await classroom.memberAction({
userId: 'student_001',
action: MemberActionType.Board_Enable,
});
// Revoke whiteboard permission
await classroom.memberAction({
userId: 'student_001',
action: MemberActionType.Board_Disable,
});After granting, the student's boardPermission$ automatically becomes true, and the SDK internally:
setDrawEnable(true)— enables drawing inputsetDataSyncEnable(true)— syncs operations to other participants- Auto-switches tool to Pen
After revoking:
setDrawEnable(false)— disables drawing inputsetDataSyncEnable(false)— operations are not synced- Auto-switches tool to MOUSE (H5 PPT interaction still preserved)
Permission and Class Status Coupling
- Before class starts: Regardless of permission, board operations are not synced (
setDataSyncEnable(false)), useful for pre-class prep drawing - During class: Operations are synced based on permission. The SDK automatically clears local pre-class operations at the moment class starts
More Board Events
In addition to BOARD_READY and BOARD_ERROR, the SDK provides the following board-related events:
import { TEvent } from '@tencent-classroom/sdk';
// Board DOM mounted, history sync in progress (board visible but not yet operable)
classroom.on(TEvent.BOARD_INIT, () => {
showBoardLoading();
});
// Board signature/auth error (does not trigger retry)
classroom.on(TEvent.BOARD_SIG_ERROR, ({ code, message }) => {
console.error('Board auth error:', code, message);
});
// Board warning (e.g., page limit exceeded, code=10)
classroom.on(TEvent.BOARD_WARN, ({ code, message }) => {
console.warn(`Board warning [${code}]:`, message);
});
// Transcoded courseware loaded to board successfully
classroom.on(TEvent.BOARD_ADD_TRANSCODE_FILE, (fileId) => {
console.log('Courseware loaded to board, fileId:', fileId);
});
// H5 PPT status changed
classroom.on(TEvent.BOARD_H5PPT_STATUS_CHANGED, (status, data) => {
console.log('H5PPT status changed:', status);
});
// Embedded video status changed
classroom.on(TEvent.BOARD_VIDEO_STATUS_CHANGED, (data) => {
console.log('Board video status:', data);
});
// H5PPT media playback status (teacher side for video sync)
classroom.on(TEvent.BOARD_MEDIA_STATUS_CHANGED, (fileId, mediaId, status, currentTime) => {
// Sync playback progress from teacher to students
});
// Board image load status (1=error, 2=timeout)
classroom.on(TEvent.BOARD_IMAGE_STATUS_CHANGED, (status, data) => {
if (status === 1) console.error('Board image failed to load');
});
// Courseware list updated
classroom.on(TEvent.DOC_LIST_UPDATED, ({ documents }) => {
refreshCoursewarePanel(documents);
});
// Courseware being loaded to board
classroom.on(TEvent.DOC_LOAD_COURSEWARE, ({ type, docInfo }) => {
console.log('Loading courseware:', docInfo.name);
});Related APIs
- Board API Reference — Full method list
- Events Reference — Board and courseware events
- State Reference — Board-related signals