基于pdf.js的网页PDF展示:移动端无法旋转、缩放问题排查
解决PDF.js移动端显示过小、无法缩放旋转的问题
问题根源
- 固定Canvas尺寸导致适配失效:原代码里canvas硬编码了
width="2000",移动端屏幕宽度远小于该值,页面渲染时会压缩canvas显示,导致内容过小;同时未考虑设备像素比(DPR),渲染的PDF会出现模糊。 - 缺少缩放、旋转逻辑:原代码没有维护缩放比例和旋转角度的变量,也没有对应的交互控制逻辑。
解决方案
1. 修改HTML与基础样式
调整结构,给PDF容器添加适配样式,移除canvas的固定宽度,同时增加缩放旋转控制按钮:
<div class="slides-player__body bg-grey-light" style="position: relative; overflow: auto; height: 100vh;"> <div id="pdf-contents"> <!-- 移除固定width,由JS动态设置 --> <canvas id="pdf-canvas" class="start-image"></canvas> <div id="page-loader" style="padding-top:20px; text-align:center;"> <p>Loading page ... <i class="fa fa-spinner fa-spin"></i></p> </div> </div> <!-- 添加缩放旋转、翻页控制按钮 --> <div style="position: fixed; bottom: 20px; left: 50%; transform: translateX(-50%); display: flex; gap: 10px; background: #fff; padding: 8px 12px; border-radius: 20px;"> <button id="pdf-zoom-out" style="border: none; background: transparent; font-size: 18px; padding: 0 8px;">-</button> <button id="pdf-zoom-in" style="border: none; background: transparent; font-size: 18px; padding: 0 8px;">+</button> <button id="pdf-rotate" style="border: none; background: transparent; font-size: 18px; padding: 0 8px;">↻</button> <span style="border-left: 1px solid #eee; height: 20px;"></span> <button id="pdf-prev" style="border: none; background: transparent; font-size: 18px; padding: 0 8px;">←</button> <button id="pdf-next" style="border: none; background: transparent; font-size: 18px; padding: 0 8px;">→</button> </div> </div>
2. 优化JS逻辑(适配+缩放+旋转)
修改JS代码,添加视口适配、设备像素比处理、缩放旋转功能,同时监听窗口resize事件:
var __PDF_DOC, __CURRENT_PAGE, __TOTAL_PAGES, __PAGE_RENDERING_IN_PROGRESS = 0, __CANVAS = $('#pdf-canvas').get(0), __CANVAS_CTX = __CANVAS.getContext('2d'), __SCALE = 1.0, // 初始缩放比例 __ROTATE = 0; // 初始旋转角度(0/90/180/270) var location_pdf = "https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/web/compressed.tracemonkey-pldi-09.pdf"; showPDF(location_pdf); // 监听窗口尺寸变化,重新渲染当前页 window.addEventListener('resize', function() { if (__PDF_DOC && !__PAGE_RENDERING_IN_PROGRESS) { showPage(__CURRENT_PAGE); } }); // 绑定缩放旋转按钮事件 $('#pdf-zoom-in').click(function() { if (__SCALE < 2.5) { // 限制最大缩放比例 __SCALE += 0.2; showPage(__CURRENT_PAGE); } }); $('#pdf-zoom-out').click(function() { if (__SCALE > 0.5) { // 限制最小缩放比例 __SCALE -= 0.2; showPage(__CURRENT_PAGE); } }); $('#pdf-rotate').click(function() { __ROTATE = (__ROTATE + 90) % 360; showPage(__CURRENT_PAGE); }); // 翻页按钮逻辑 $('#pdf-prev').click(function() { if (__CURRENT_PAGE > 1) { showPage(__CURRENT_PAGE - 1); } }); $('#pdf-next').click(function() { if (__CURRENT_PAGE < __TOTAL_PAGES) { showPage(__CURRENT_PAGE + 1); } }); function showPDF(pdf_url) { $("#pdf-loader").show(); PDFJS.getDocument({ url: pdf_url }).then(function(pdf_doc) { __PDF_DOC = pdf_doc; __TOTAL_PAGES = __PDF_DOC.numPages; $("#pdf-loader").hide(); $("#pdf-contents").show(); $("#pdf-total-pages").text(__TOTAL_PAGES); // 默认显示第一页(兼容current_slide不存在的情况) var pg = document.getElementById("current_slide")?.value || 1; showPage(parseInt(pg)); }).catch(function(error) { $("#pdf-loader").hide(); $("#upload-button").show(); alert(error.message); }); } function showPage(page_no) { __PAGE_RENDERING_IN_PROGRESS = 1; __CURRENT_PAGE = page_no; // 禁用所有控制按钮直到渲染完成 $("#pdf-next, #pdf-prev, #pdf-zoom-in, #pdf-zoom-out, #pdf-rotate").attr('disabled', 'disabled'); $("#pdf-canvas").hide(); $("#page-loader").show(); $("#pdf-current-page").text(page_no); __PDF_DOC.getPage(page_no).then(function(page) { // 获取容器宽度,适配移动端屏幕 var containerWidth = $('#pdf-contents').width(); // 计算基础缩放比例:让PDF宽度适配容器,叠加自定义缩放比例 var viewport = page.getViewport({ scale: __SCALE, rotation: __ROTATE }); // 考虑设备像素比,避免PDF渲染模糊 var dpr = window.devicePixelRatio || 1; __CANVAS.width = viewport.width * dpr; __CANVAS.height = viewport.height * dpr; __CANVAS.style.width = viewport.width + 'px'; __CANVAS.style.height = viewport.height + 'px'; __CANVAS_CTX.scale(dpr, dpr); var renderContext = { canvasContext: __CANVAS_CTX, viewport: viewport }; page.render(renderContext).then(function() { __PAGE_RENDERING_IN_PROGRESS = 0; // 重新启用控制按钮 $("#pdf-next, #pdf-prev, #pdf-zoom-in, #pdf-zoom-out, #pdf-rotate").removeAttr('disabled'); $("#pdf-canvas").show(); $("#page-loader").hide(); }); }); }
关键改动说明
- 移动端适配:不再固定canvas宽度,根据容器宽度动态计算渲染尺寸,同时加入设备像素比处理,解决PDF模糊问题。
- 缩放功能:通过
__SCALE变量控制渲染比例,绑定按钮实现缩放增减,限制缩放范围避免显示异常。 - 旋转功能:通过
__ROTATE变量控制页面旋转角度,每次点击增加90度,循环生效。 - 窗口resize监听:屏幕尺寸变化时自动重新渲染,保持PDF始终适配当前屏幕。
内容的提问来源于stack exchange,提问作者irwan dwiyanto
相关产品推荐
相关产品推荐

