Complete guide to creating, managing, and inserting symbol libraries. Both local storage and server storage are supported.
| Storage Method | Service | Features |
|---|
| Local storage | getLocalStorageService() | Stored in IndexedDB, available offline |
| Server storage | Engine.service | Cloud storage, requires network and permissions |
const {
LineEnt, CircleEnt, Engine,
getLocalStorageService,
buildSymbolVcadData,
generateThumbnailFromEntities
} = vjcad;
// 1. Create entities as symbol content
const line1 = new LineEnt([-10, 0], [10, 0]);
const line2 = new LineEnt([0, -10], [0, 10]);
const circle = new CircleEnt([0, 0], 8);
line1.setDefaults();
line2.setDefaults();
circle.setDefaults();
// 2. Get local storage service
const localService = getLocalStorageService();
// 3. Create or get category
let categories = await localService.getLocalSymbolCategories();
let category = categories.find(c => c.name === "My Symbols");
if (!category) {
category = await localService.createLocalSymbolCategory("My Symbols");
}
// 4. Build symbol data
const entities = [line1, line2, circle];
const vcadData = await buildSymbolVcadData(entities, false);
// 5. Generate thumbnail
const thumbnail = await generateThumbnailFromEntities(entities, 128, 128);
// 6. Save symbol
const symbol = await localService.saveLocalSymbol({
categoryId: category.id,
name: "Cross Circle Symbol",
basePoint: [0, 0], // Symbol base point (reference point when inserted)
thumbnail: thumbnail,
vcadData: vcadData
});
console.log("Symbol saved, ID:", symbol.id);
const {
LineEnt, Engine,
buildSymbolVcadData,
compressSymbolData,
uint8ArrayToBase64,
generateThumbnailFromEntities
} = vjcad;
// 1. Create entities
const line1 = new LineEnt([0, 0], [20, 0]);
const line2 = new LineEnt([20, 0], [15, 3]);
const line3 = new LineEnt([20, 0], [15, -3]);
line1.setDefaults();
line2.setDefaults();
line3.setDefaults();
// 2. Get service
const service = Engine.service;
// 3. Get or create category
const categories = await service.getSymbolCategories();
let category = categories.find(c => c.name === "User Custom");
if (!category) {
category = await service.createSymbolCategory("User Custom");
}
// 4. Build symbol data
const entities = [line1, line2, line3];
const vcadData = await buildSymbolVcadData(entities, false);
// 5. Compress data (required for server storage)
const compressedData = await compressSymbolData(vcadData, 6);
const base64Data = uint8ArrayToBase64(compressedData);
// 6. Generate thumbnail
const thumbnail = await generateThumbnailFromEntities(entities, 128, 128);
// 7. Save symbol
const symbol = await service.createSymbol({
categoryId: category.id,
name: "Arrow Symbol",
basePoint: [0, 0],
thumbnail: thumbnail,
data: base64Data
});
console.log("Symbol saved, ID:", symbol.id);
const {
Point2D, Engine,
getLocalStorageService,
parseSymbolVcadData,
mergeSymbolToDocument,
regen
} = vjcad;
// 1. Get symbol data
const localService = getLocalStorageService();
const categories = await localService.getLocalSymbolCategories();
const symbols = await localService.getLocalSymbolList(categories[0].id);
const symbolData = await localService.getLocalSymbol(symbols[0].id);
// 2. Parse symbol data
const symbolDoc = await parseSymbolVcadData(symbolData.vcadData);
// 3. Insert parameters
const insertPoint = new Point2D(50, 50); // Insert point
const basePoint = symbolData.basePoint; // Symbol base point
const scale = 1.5; // Scale factor
const rotation = 45; // Rotation angle (degrees)
// 4. Merge into current document
const addedEntities = mergeSymbolToDocument(
symbolDoc,
insertPoint,
basePoint,
scale,
rotation,
false // Do not clear source drawing info
);
console.log("Inserted entity count:", addedEntities.length);
// 5. Refresh view
regen();
Engine.zoomExtents();
const {
Point2D, Engine,
decompressSymbolData,
parseSymbolVcadData,
mergeSymbolToDocument
} = vjcad;
const service = Engine.service;
// 1. Get symbol list
const categories = await service.getSymbolCategories();
const category = categories.find(c => c.name === "User Custom");
const result = await service.getSymbolList(category.id);
// 2. Get symbol details
const fullSymbol = await service.getSymbol(result.list[0].id);
// 3. Decompress data
const vcadData = await decompressSymbolData(fullSymbol.data);
// 4. Parse and insert
const symbolDoc = await parseSymbolVcadData(vcadData);
const insertPoint = new Point2D(100, 100);
const addedEntities = mergeSymbolToDocument(
symbolDoc,
insertPoint,
fullSymbol.basePoint,
1, // Scale
0, // Rotation
false
);
const {
Engine,
getLocalStorageService,
insertSymbolInteractive,
CommandRegistry, CommandDefinition, CommandOptions
} = vjcad;
class InsertSymbolCommand {
async main() {
// 1. Get symbol data
const localService = getLocalStorageService();
const categories = await localService.getLocalSymbolCategories();
const symbols = await localService.getLocalSymbolList(categories[0].id);
const symbolData = await localService.getLocalSymbol(symbols[0].id);
// 2. Interactive insertion
// Prompts the user for: insertion point, scale, rotation
const entities = await insertSymbolInteractive(
symbolData.vcadData,
symbolData.basePoint,
{
allowScale: true, // Allow specifying scale
allowRotation: true, // Allow specifying rotation
clearSourceInfo: false
}
);
if (entities) {
console.log("Symbol inserted successfully, entity count:", entities.length);
Engine.zoomExtents();
} else {
console.log("Symbol insertion canceled");
}
}
}
// Register command
const cmdDef = new CommandDefinition('MYINSERTSYMBOL', 'Insert Symbol Interactively', InsertSymbolCommand);
CommandRegistry.regist(cmdDef);
// Execute command
await Engine.editor.executerWithOp('MYINSERTSYMBOL');
const localService = getLocalStorageService();
// Get all categories
const categories = await localService.getLocalSymbolCategories();
// Create category
const newCategory = await localService.createLocalSymbolCategory("New Category");
// Update category name
await localService.updateLocalSymbolCategory(newCategory.id, "New Name");
// Delete category
await localService.deleteLocalSymbolCategory(newCategory.id);
const service = Engine.service;
// Get all categories
const categories = await service.getSymbolCategories();
// Create category (requires permission)
const newCategory = await service.createSymbolCategory("New Category");
// Update category name
await service.updateSymbolCategory(newCategory.id, "New Name");
// Delete category
await service.deleteSymbolCategory(newCategory.id);
const localService = getLocalStorageService();
// Get symbol list
const symbols = await localService.getLocalSymbolList(categoryId);
// Get symbol details (includes vcadData)
const detail = await localService.getLocalSymbol(symbolId);
// Delete symbol
await localService.deleteLocalSymbol(symbolId);
// Get statistics
const stats = await localService.getLocalSymbolStats();
console.log("Category count:", stats.categoryCount);
console.log("Symbol count:", stats.symbolCount);
console.log("Total size:", stats.totalSize);
const service = Engine.service;
// Get symbol list (supports pagination and search)
const result = await service.getSymbolList(categoryId, {
page: 1,
pageSize: 10,
keyword: "arrow" // Optional: keyword search
});
console.log("Total:", result.total);
console.log("Current page:", result.page);
console.log("List:", result.list);
// Get symbol details (includes compressed data)
const fullSymbol = await service.getSymbol(symbolId);
// Delete symbol (requires permission)
await service.deleteSymbol(symbolId);
| Function | Description |
|---|
buildSymbolVcadData(entities, clearSourceInfo) | Convert an entity array into symbol data |
generateThumbnailFromEntities(entities, width, height) | Generate thumbnail |
parseSymbolVcadData(vcadData) | Parse symbol data into CadDocument |
mergeSymbolToDocument(doc, insertPt, basePt, scale, rotation, clearInfo) | Merge symbol into current document |
insertSymbolInteractive(vcadData, basePoint, options) | Interactively insert symbol |
compressSymbolData(data, level) | Compress symbol data (for server storage) |
decompressSymbolData(base64Data) | Decompress symbol data |
uint8ArrayToBase64(uint8Array) | Convert Uint8Array to Base64 |
| Field | Description |
|---|
id | Symbol ID |
name | Symbol name |
categoryId | Category ID |
basePoint | Symbol base point [x, y] |
thumbnail | Thumbnail (Base64 or Data URL) |
vcadData / data | Symbol data (raw data locally, compressed Base64 on the server) |
createTime | Creation time |
const {
Engine, CommandRegistry, CommandDefinition, CommandOptions,
getLocalStorageService, insertSymbolInteractive,
showSelectDialog, message
} = vjcad;
class SymbolLibraryCommand {
async main() {
const localService = getLocalStorageService();
// 1. Get all categories
const categories = await localService.getLocalSymbolCategories();
if (categories.length === 0) {
message.error("No symbol categories");
return;
}
// 2. Choose category
const categoryResult = await showSelectDialog({
title: "Select Symbol Category",
label: "Please choose a category:",
options: categories.map(c => ({ value: c.id, label: c.name }))
});
if (!categoryResult.confirmed) return;
// 3. Get symbol list
const symbols = await localService.getLocalSymbolList(categoryResult.value);
if (symbols.length === 0) {
message.error("No symbols in this category");
return;
}
// 4. Choose symbol
const symbolResult = await showSelectDialog({
title: "Select Symbol",
label: "Please choose the symbol to insert:",
options: symbols.map(s => ({ value: s.id, label: s.name }))
});
if (!symbolResult.confirmed) return;
// 5. Get symbol details
const symbolData = await localService.getLocalSymbol(symbolResult.value);
const symbolMeta = symbols.find(s => s.id === symbolResult.value);
// 6. Interactive insertion
const entities = await insertSymbolInteractive(
symbolData.vcadData,
symbolMeta.basePoint,
{ allowScale: true, allowRotation: true }
);
if (entities) {
message.info(`Inserted symbol: ${symbolMeta.name}`);
Engine.zoomExtents();
}
}
}
// Register command
CommandRegistry.regist(new CommandDefinition(
'MYSYMBOLLIBRARY',
'Symbol Library',
SymbolLibraryCommand
));