// ES6 Compliant Syntax
// GitHub Copilot v1.0, GPT-4.1, September 29, 2025
// File: index.js
import WebViewer from '@pdftron/webviewer';
const licenseKey = 'YOUR_WEBVIEWER_LICENSE_KEY';
// CAD Viewer Demo
//
// This code demonstrates how to view CAD files directly in the browser with the Apryse JavaScript document SDK.
// It shows how to create a display and visualization tool for AutoCAD floor plans and drawings.
// Allowing users to view, edit, and annotate AutoCAD DWG CAD files from the browser using the WebViewer Server.
//
// **Important**
// 1. You must get a license key from Apryse for the server to run.
// A trial key can be obtained from:
// https://docs.apryse.com/core/guides/get-started/trial-key
//
// 2. You need to also run the `npm install` command at /cad-viewer/server/ location to install the `@pdftron/pdfnet-node` and `@pdftron/cad` packages.
// Initialize WebViewer with the specified settings
function initializeWebViewer() {
// This code initializes the WebViewer with the basic settings
WebViewer({
path: '/lib',
licenseKey: licenseKey,
enableFilePicker: false,
}, element).then((instance) => {
// Enable the measurement toolbar so it appears with all the other tools, and disable Cloudy rectangular tool
const cloudyTools = [
instance.Core.Tools.ToolNames.CLOUDY_RECTANGULAR_AREA_MEASUREMENT,
instance.Core.Tools.ToolNames.CLOUDY_RECTANGULAR_AREA_MEASUREMENT2,
instance.Core.Tools.ToolNames.CLOUDY_RECTANGULAR_AREA_MEASUREMENT3,
instance.Core.Tools.ToolNames.CLOUDY_RECTANGULAR_AREA_MEASUREMENT4,
];
instance.UI.enableFeatures([instance.UI.Feature.Measurement, instance.UI.Feature.Initials]);
instance.UI.disableTools(cloudyTools);
// Set default toolbar group to Annotate
instance.UI.setToolbarGroup('toolbarGroup-Annotate');
// Set default tool on mobile devices to Pan.
if (UIElements.isMobileDevice()) {
instance.UI.setToolMode(instance.Core.Tools.ToolNames.PAN);
}
instance.Core.documentViewer.addEventListener('documentUnloaded', () => {
if (searchParams.has('file')) {
searchParams.delete('file');
history.replaceState(null, '', '?' + searchParams.toString());
}
});
instance.Core.annotationManager.enableAnnotationNumbering();
instance.UI.NotesPanel.enableAttachmentPreview();
// Add the demo-specific functionality
customizeUI(instance).then(() => {
// Create UI controls after demo is initialized
UIElements.createUIControls(instance);
});
});
}
// CAD files, Key is the file name, value is the URL
const CAD_FILES = {
'DWG': 'https://apryse.s3.us-west-1.amazonaws.com/public/files/samples/construction%20drawings%20color.dwg',
'DXF': 'PROVIDE_URL_HERE/*.dxf',
};
const defaultDoc = CAD_FILES['DWG']; // Default CAD file to load
// Default styles for measurement tools
const DEFAULT_FONT_SIZE = 16;
window.DEFAULT_FONT_SIZE = DEFAULT_FONT_SIZE;
const DEFAULT_STROKE_THICKNESS = 2;
window.DEFAULT_STROKE_THICKNESS = DEFAULT_STROKE_THICKNESS;
const MEASUREMENT_TOOLS = [
'AnnotationCreateDistanceMeasurement',
'AnnotationCreatePerimeterMeasurement',
'AnnotationCreateAreaMeasurement',
];
window.MEASUREMENT_TOOLS = MEASUREMENT_TOOLS;
const customizeUI = async (instance) => {
const { Feature } = instance.UI;
const { Annotations, documentViewer } = instance.Core;
instance.UI.enableFeatures([Feature.Measurement]);
instance.UI.enableTools(MEASUREMENT_TOOLS);
instance.UI.openElements(['tabPanel']);
instance.UI.setActiveLeftPanel('layersPanel');
// Update default tool styles
MEASUREMENT_TOOLS.forEach((tool, index) => {
documentViewer.getTool(tool).setStyles({
StrokeThickness: DEFAULT_STROKE_THICKNESS / documentViewer.getZoomLevel(),
StrokeColor: new Annotations.Color(
255 * Number(index === 0),
255 * Number(index === 1),
255 * Number(index === 2),
),
});
});
// Update font size to be larger
Annotations.LineAnnotation.prototype['constant']['FONT_SIZE'] = DEFAULT_FONT_SIZE / documentViewer.getZoomLevel() + 'px';
Annotations.LineAnnotation.prototype['constant']['TEXT_COLOR'] = '#FF0000';
documentViewer.addEventListener('zoomUpdated', (zoom) => UIElements.zoomUpdated(instance, zoom));
// Using the Apryse CAD Module, Convert and Load default document
const cadUrl = defaultDoc;
const cadFilename = cadUrl.split('/').pop();
const response = await fetch(defaultDoc);
if (!response.ok) {
throw new Error(`Failed to fetch CAD: ${response.status}`);
}
const cadBuffer = await response.arrayBuffer();
const pdfBuffer = await convertCadtoPdf(cadBuffer, cadFilename);
instance.UI.loadDocument(pdfBuffer, {
extension: 'pdf',
});
};
const convertCadtoPdf = async (cadBuffer, cadFilename) => {
// Send the CAD to the server to be converted to PDF
console.log('Sending CAD to server for conversion...');
const cadBlob = new Blob([cadBuffer]);
const formData = new FormData();
formData.append('cadfile', cadBlob, cadFilename);
const postResponse = await fetch('http://localhost:5050/server/handler.js', {
method: 'POST',
body: formData,
});
if (postResponse.status !== 200) {
throw new Error(`Server error during CAD upload: ${postResponse.status}`);
}
const buffer = await postResponse.arrayBuffer();
return buffer;
};
// Make convertCadtoPdf globally available
window.convertCadtoPdf = convertCadtoPdf;
const searchParams = new URLSearchParams(window.location.search);
const history = window.history || window.parent.history || window.top.history;
const element = document.getElementById('viewer');
// Cleanup function for when the demo is closed or page is unloaded
const cleanup = (instance) => {
const { Feature } = instance.UI;
if (typeof instance !== 'undefined' && instance.UI) {
instance.UI.disableTools(MEASUREMENT_TOOLS);
instance.UI.disableFeatures([Feature.Measurement]);
instance.UI.closeElements(['leftPanel']);
console.log('Cleaning up cad-viewer demo');
}
};
// Register cleanup for page unload
window.addEventListener('beforeunload', () => cleanup(instance));
window.addEventListener('unload', () => cleanup(instance));
//helper function to load the ui-elements.js script
function loadUIElementsScript() {
return new Promise((resolve, reject) => {
if (window.UIElements) {
console.log('UIElements already loaded');
resolve();
return;
}
const script = document.createElement('script');
script.src = '/showcase-demos/cad-viewer/client/ui-elements.js';
script.onload = function () {
console.log('✅ UIElements script loaded successfully');
resolve();
};
script.onerror = function () {
console.error('Failed to load UIElements script');
reject(new Error('Failed to load ui-elements.js'));
};
document.head.appendChild(script);
});
}
// Load UIElements script first, then initialize WebViewer
loadUIElementsScript().then(() => {
initializeWebViewer();
}).catch((error) => {
console.error('Failed to load UIElements:', error);
});