如何在使用Canvas元素的PdfJs 3.4.120中显示标准工具栏?
问题描述
在Spring Boot-MVC应用的JSP页面中使用PDF.js 3.4.120版本展示PDF文件,遇到以下问题:
- 用
iframe嵌入viewer.html能显示标准工具栏,但需求限制无法使用iframe - 自行通过Canvas渲染PDF仅能显示文档内容,缺少工具栏功能
当前使用的代码如下:
$.ajax({ //some code }).done(function(data, textStatus, jqXHR) { var pdfData = new Uint8Array(data); var pdfContainer = document.getElementById('pdfContainer'); pdfjsLib.GlobalWorkerOptions.workerSrc = "pdf.worker.min.js"; pdfjsLib.getDocument({ data: pdfData }).promise.then(function(pdf) { for(pageNum = 1; pageNum <= pdf.numPages; pageNum++) { pdf.getPage(pageNum).then(page => { const canvas = document.createElement('canvas'); var scale = 1.5; var viewport = page.getViewport({ scale: scale, }); var outputScale = window.devicePixelRatio || 1; var context = canvas.getContext('2d'); canvas.width = Math.floor(viewport.width * outputScale); canvas.height = Math.floor(viewport.height * outputScale); canvas.style.width = Math.floor(viewport.width) + "px"; canvas.style.height = Math.floor(viewport.height) + "px"; var transform = outputScale !== 1 ? [outputScale, 0, 0, outputScale, 0, 0] : null; var renderContext = { canvasContext: context, transform: transform, viewport: viewport }; page.render(renderContext); pdfContainer.appendChild(canvas); }); } }); })
页面容器:
<div id="pdfContainer"></div>
解决方案:手动实现基础工具栏功能
直接用Canvas渲染仅会绘制PDF页面内容,PDF.js不会自动提供工具栏,需要自行构建UI并绑定操作逻辑。
步骤1:添加工具栏HTML结构
在页面中插入工具栏容器,包含常用操作按钮:
<div id="pdfToolbar"> <button id="prevPage">上一页</button> <span id="pageInfo">第 <span id="currentPage">1</span> 页 / 共 <span id="totalPages">0</span> 页</span> <button id="nextPage">下一页</button> <button id="zoomIn">放大</button> <button id="zoomOut">缩小</button> </div> <div id="pdfContainer"></div>
步骤2:修改JavaScript代码,添加状态管理与工具栏逻辑
维护PDF实例、当前页码、缩放比例等状态,为按钮绑定对应操作:
// 全局状态变量 let pdfInstance = null; let currentPageNum = 1; let scale = 1.5; const pdfContainer = document.getElementById('pdfContainer'); const currentPageEl = document.getElementById('currentPage'); const totalPagesEl = document.getElementById('totalPages'); // 渲染指定页码的页面 function renderPage(pageNum) { // 清空容器 pdfContainer.innerHTML = ''; pdfInstance.getPage(pageNum).then(page => { const canvas = document.createElement('canvas'); const outputScale = window.devicePixelRatio || 1; const viewport = page.getViewport({ scale: scale }); canvas.width = Math.floor(viewport.width * outputScale); canvas.height = Math.floor(viewport.height * outputScale); canvas.style.width = Math.floor(viewport.width) + "px"; canvas.style.height = Math.floor(viewport.height) + "px"; const transform = outputScale !== 1 ? [outputScale, 0, 0, outputScale, 0, 0] : null; const renderContext = { canvasContext: canvas.getContext('2d'), transform: transform, viewport: viewport }; page.render(renderContext); pdfContainer.appendChild(canvas); // 更新页码显示 currentPageEl.textContent = pageNum; }); } // 绑定工具栏事件 function bindToolbarEvents() { document.getElementById('prevPage').addEventListener('click', () => { if (currentPageNum > 1) { currentPageNum--; renderPage(currentPageNum); } }); document.getElementById('nextPage').addEventListener('click', () => { if (currentPageNum < pdfInstance.numPages) { currentPageNum++; renderPage(currentPageNum); } }); document.getElementById('zoomIn').addEventListener('click', () => { scale += 0.2; renderPage(currentPageNum); }); document.getElementById('zoomOut').addEventListener('click', () => { if (scale > 0.5) { scale -= 0.2; renderPage(currentPageNum); } }); } // 加载PDF并初始化 $.ajax({ // 补充AJAX配置,务必设置responseType为arraybuffer以获取二进制数据 responseType: 'arraybuffer' }).done(function(data, textStatus, jqXHR) { const pdfData = new Uint8Array(data); pdfjsLib.GlobalWorkerOptions.workerSrc = "pdf.worker.min.js"; pdfjsLib.getDocument({ data: pdfData }).promise.then(function(pdf) { pdfInstance = pdf; totalPagesEl.textContent = pdf.numPages; // 渲染第一页 renderPage(currentPageNum); // 绑定工具栏事件 bindToolbarEvents(); }); });
注意事项
- 必须将AJAX请求的
responseType设置为arraybuffer,否则无法正确解析PDF二进制数据 - 可根据需求扩展工具栏功能:比如添加打印按钮(调用
window.print())、下载按钮(通过pdfInstance.getData()获取原始数据生成下载链接)、旋转按钮(修改page.getViewport的rotation参数)
进阶方案:复用PDF.js Viewer的UI组件
如果项目允许引入额外资源,可直接复用官方Viewer的工具栏组件:
- 从PDF.js发布包中引入
viewer.css、viewer.js(注意依赖顺序) - 复制
viewer.html中的核心DOM结构到JSP页面 - 通过
PDFViewerApplicationAPI加载PDF数据,无需自行渲染Canvas
这种方式能快速获得完整工具栏功能,避免重复开发,但需要引入官方的Viewer资源文件。
内容的提问来源于stack exchange,提问作者Akshay Sumbe
相关产品推荐
相关产品推荐

