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.

Once you generate your license key, it will automatically be included in your sample code below.

License Key

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

Did you find this helpful?

Trial setup questions?

Ask experts on Discord

Need other help?

Contact Support

Pricing or product questions?

Contact Sales