Create Thumbnail Showcase Demo Code Sample

Requirements
View Demo

Easily create high resolution thumbnail images from selected document pages.

This demo allows you to:

  • Choose your own document file
  • Create high-resolution thumbnails
  • Define PNG or JPEG image format
  • Specify scale factor [0.1, 10], where low values yield smaller thumbnail sizes

Implementation steps

To add Thumbnail Creation capability with WebViewer:
Step 1: Get started with WebViewer in your preferred web stack
Step 2: Add the ES6 JavaScript sample code provided in this guide

1// ES6 Compliant Syntax
2// GitHub Copilot v1.0, GPT-4.1, October 15, 2025
3// File: index.js
4
5import WebViewer from '@pdftron/webviewer';
6
7// Create Thumbnail Demo
8// This code demonstrates how to create a high resolution JPG or PNG thumbnail for a PDF document using the loadCanvas API.
9
10function initializeWebViewer() {
11
12 // This code initializes the WebViewer with the basic settings
13 WebViewer({
14 path: '/lib',
15 licenseKey: 'YOUR_LICENSE_KEY',
16 enableFilePicker: true,
17 loadAsPDF: true, // Ensure files are loaded as PDF documents for best thumbnail quality
18 }, document.getElementById('viewer')).then((instance) => {
19 // Enable the measurement toolbar so it appears with all the other tools, and disable Cloudy rectangular tool
20 const cloudyTools = [
21 instance.Core.Tools.ToolNames.CLOUDY_RECTANGULAR_AREA_MEASUREMENT,
22 instance.Core.Tools.ToolNames.CLOUDY_RECTANGULAR_AREA_MEASUREMENT2,
23 instance.Core.Tools.ToolNames.CLOUDY_RECTANGULAR_AREA_MEASUREMENT3,
24 instance.Core.Tools.ToolNames.CLOUDY_RECTANGULAR_AREA_MEASUREMENT4,
25 ];
26 instance.UI.enableFeatures([instance.UI.Feature.Measurement, instance.UI.Feature.Initials]);
27 instance.UI.disableTools(cloudyTools);
28 // Set default toolbar group to Annotate
29 instance.UI.setToolbarGroup('toolbarGroup-Annotate');
30 // Set default tool on mobile devices to Pan.
31 if (UIElements.isMobileDevice()) {
32 instance.UI.setToolMode(instance.Core.Tools.ToolNames.PAN);
33 }
34
35 instance.Core.documentViewer.addEventListener('documentUnloaded', () => {
36 if (searchParams.has('file')) {
37 searchParams.delete('file');
38 history.replaceState(null, '', '?' + searchParams.toString());
39 }
40 });
41
42 instance.Core.annotationManager.enableAnnotationNumbering();
43 instance.UI.NotesPanel.enableAttachmentPreview();
44 // Add the demo-specific functionality
45 customizeUI(instance).then(() => {
46 // Create UI controls after demo is initialized
47 UIElements.createUIControls(instance);
48 });
49 });
50}
51
52const searchParams = new URLSearchParams(window.location.search);
53const history = window.history || window.parent.history || window.top.history;
54
55window.pageNum = 1;
56window.scaleNum = 1.0;
57window.thumbnailName = 'thumbnail';
58window.thumbnailType = 'png';
59
60window.thumbnailOptions = ['PNG', 'JPEG'];
61
62
63const customizeUI = async (instance) => {
64 // Load the default document
65 await instance.UI.loadDocument('https://apryse.s3.us-west-1.amazonaws.com/public/files/samples/WebviewerDemoDoc.pdf');
66};
67
68// Function to handle the Create Thumbnail button click
69window.onThumbnailButtonClick = (instance) => {
70 // Get the document
71 const doc = instance.Core.documentViewer.getDocument();
72
73 // Get the page number from user input
74 let pageNumber = parseInt(window.pageNum, 10);
75
76 // Validate page number
77 if (isNaN(pageNumber) || pageNumber < 1 || pageNumber > doc.getPageCount()) {
78 alert('Please enter a valid page number between 1 and ' + doc.getPageCount());
79 return; // Exit if page number is invalid
80 }
81
82 // Clamp the page number to valid range
83 pageNumber = isNaN(pageNumber) ? 1 : Math.min(Math.max(pageNumber, 1), doc.getPageCount());
84
85 // Get the scale (zoom level) from user input
86 const zoom = parseFloat(window.scaleNum);
87 if (isNaN(zoom) || zoom <= 0 || zoom > 10) {
88 alert('Please enter a valid zoom level between 0.1 and 10');
89 return; // Exit if zoom is invalid
90 }
91
92 // Compensate for device pixel ratio to ensure consistent output across devices
93 // Normalize to standard DPR of 1.0 by dividing by actual DPR
94 const devicePixelRatio = window.devicePixelRatio || 1;
95 const adjustedZoom = zoom / devicePixelRatio;
96
97 console.log(`Device Pixel Ratio: ${devicePixelRatio}`);
98 console.log(`Original zoom: ${zoom}, Adjusted zoom: ${adjustedZoom}`);
99 console.log(`This should produce thumbnails equivalent to DPR=1.0 environment`);
100
101 // Get the file name and type from user input
102 const name = window.thumbnailName;
103 const type = window.thumbnailType;
104
105 // Save to blob using the loadCanvas API
106 doc.loadCanvas({
107 pageNumber,
108 zoom: adjustedZoom, // Use DPI-adjusted zoom for consistent output
109 drawComplete: async (thumbnail) => {
110 // Optionally, comment out "drawAnnotations" to exclude annotations
111 await instance.Core.documentViewer
112 .getAnnotationManager()
113 .drawAnnotations(pageNumber, thumbnail);
114 // thumbnail is a HTMLCanvasElement or HTMLImageElement
115 thumbnail.toBlob(
116 (blob) => {
117 saveAs(blob, name + '.' + type);
118 },
119 'image/' + type,
120 1
121 );
122 },
123 });
124};
125
126// Cleanup function for when the demo is closed or page is unloaded
127const cleanup = (instance) => {
128 if (typeof instance !== 'undefined' && instance.UI) {
129 if (instance.Core.documentViewer.getDocument()) {
130 // Insert any other cleanup code here
131 }
132 console.log('Cleaning up demo');
133 }
134};
135
136// Register cleanup for page unload
137window.addEventListener('beforeunload', () => cleanup(instance));
138window.addEventListener('unload', () => cleanup(instance));
139
140// UI Elements Script Loader
141// Loads the ui-elements.js script
142function loadUIElementsScript() {
143 return new Promise((resolve, reject) => {
144 if (window.UIElements) {
145 console.log('UIElements already loaded');
146 resolve();
147 return;
148 }
149 const script = document.createElement('script');
150 script.src = '/showcase-demos/create-thumbnail/ui-elements.js';
151 script.onload = function () {
152 console.log('✅ UIElements script loaded successfully');
153 resolve();
154 };
155 script.onerror = function () {
156 console.error('Failed to load UIElements script');
157 reject(new Error('Failed to load ui-elements.js'));
158 };
159 document.head.appendChild(script);
160 });
161}
162
163// Load UIElements script first, then initialize WebViewer
164loadUIElementsScript().then(() => {
165 initializeWebViewer();
166}).catch((error) => {
167 console.error('Failed to load UIElements:', error);
168});
169

Did you find this helpful?

Trial setup questions?

Ask experts on Discord

Need other help?

Contact Support

Pricing or product questions?

Contact Sales