Appearance
Quick Start
Install
sh
npm install @optellix/xviewr-sdkLicensing
Every viewer instance requires a valid license key. The key is an XVR1 ES256 token issued by Optellix. Pass it in viewer.licensing at construction. viewer.ready() will reject with a LicenseError if the key is missing or invalid.
ts
import { ViewerCore, LicenseError, LoaderPlugin, SelectionPlugin } from '@optellix/xviewr-sdk';
const container = document.getElementById('viewer') as HTMLElement;
const viewer = new ViewerCore(container, {
viewer: {
camera: {
type: 'perspective',
fov: 75,
position: { x: 5, y: 5, z: 5 },
target: { x: 0, y: 0, z: 0 },
},
licensing: {
key: process.env.XVIEWR_LICENSE_KEY!,
},
},
rendering: { antialias: true },
plugins: [],
});
try {
await viewer.ready();
await viewer.loadPlugin(new LoaderPlugin());
await viewer.loadPlugin(new SelectionPlugin());
} catch (err) {
if (err instanceof LicenseError) {
console.error('License invalid or expired:', err.message);
}
throw err;
}The container element must be in the document and have a non-zero size before you construct the viewer. The renderer canvas is appended to it automatically.
Load a Model
ts
const loader = viewer.pluginManager.getPlugin('loader') as LoaderPlugin;
// Progress
viewer.eventBus.on('file:loading-progress', ({ progress }) => {
setProgressBar(Math.round(progress * 100));
});
// Load GLB from URL
await loader.loadGlb('/models/assembly.glb');
// Or from a user-selected File
input.addEventListener('change', async () => {
const file = input.files?.[0];
if (file) await loader.loadFile(file);
});The loaded model is added to viewer.root. After loading, the camera does not auto-fit — call CameraService.fitToScene() if you want that:
ts
import { CameraService } from '@optellix/xviewr-sdk';
const camera = viewer.getService<CameraService>('camera');
camera?.fitToScene();Subscribe to Events
All events flow through viewer.eventBus. Handlers run synchronously on the emitting thread.
ts
viewer.eventBus.on('model:loaded', ({ model }) => {
console.log('loaded', model.name);
});
viewer.eventBus.on('selection:changed', ({ selected }) => {
console.log('selected objects:', selected.length);
});Selection
SelectionPlugin is active after loading it with viewer.loadPlugin(new SelectionPlugin()). Click-to-select is on by default.
ts
const selection = viewer.pluginManager.getPlugin('selection') as SelectionPlugin;
// Programmatic select
selection.selectAll();
selection.focusOnSelection();
selection.clearSelection();
// Handle clicks yourself
viewer.renderer.domElement.addEventListener('click', (e) => {
selection.clickToSelect(e.clientX, e.clientY);
});Measurement
ts
import { MeasurementPlugin } from '@optellix/xviewr-sdk';
await viewer.loadPlugin(new MeasurementPlugin());
const measure = viewer.pluginManager.getPlugin('measurement') as MeasurementPlugin;
measure.enable();
measure.setMeasurementMode('distance'); // click two points to measure
viewer.eventBus.on('measurement:created', ({ measurement }) => {
console.log(measurement.result);
});
// To stop measuring
measure.disable();Available modes: distance, angle, area, multi-point, aabb, obb, volume, circle, arc.
Export a Screenshot
ts
import { CanvasExportPlugin } from '@optellix/xviewr-sdk';
await viewer.loadPlugin(new CanvasExportPlugin());
const exporter = viewer.pluginManager.getPlugin('canvas-export') as CanvasExportPlugin;
// Download a 1920x1080 PNG
await exporter.downloadImage({ width: 1920, height: 1080, format: 'png' });
// Or get a data URL
const url = await exporter.exportImage({ format: 'jpeg', quality: 0.92 });Cleanup
Always dispose the viewer when the host component unmounts:
ts
await viewer.dispose();dispose() unloads all plugins, shuts down services, disposes GPU resources, and removes the renderer canvas from the DOM. It is idempotent.
Next Steps
| Topic | Reference |
|---|---|
| Full configuration options | types/configuration.md |
| All available plugins | overview.md |
| All available services | overview.md |
| Loading chunked/LOD models | plugins/LoaderPlugin.md |
| Custom measurement types | services/MeasurementService.md |
| License inspection and feature gating | services/LicenseService.md |
| Error types | errors.md |