新闻详情

新闻详情

首页 / 资讯中心 / 详情

PDF.js 如何在 HiDPI 屏幕上把 PDF 页面渲染得清晰?(devicePixelRatio 与 viewport 缩放)

发布时间:2026/9/9 23:01:33来源:尧图网络
PDF.js 如何在 HiDPI 屏幕上把 PDF 页面渲染得清晰?(devicePixelRatio 与 viewport 缩放)
PDF.js 如何在 HiDPI 屏幕上把 PDF 页面渲染得清晰devicePixelRatio 与 viewport 缩放【免费下载链接】pdf.jsPDF Reader in JavaScript项目地址: https://gitcode.com/gh_mirrors/pd/pdf.js在浏览器里用 canvas 渲染 PDF 页面时一个常见的问题是页面能显示但放在高分屏Retina、devicePixelRatio 1上会发虚。原因是 canvas 的内部分辨率只按 CSS 像素设置没有按设备的物理像素密度放大。pdf.js 的官方示例给出的做法是用page.getViewport()决定页面的布局尺寸再用window.devicePixelRatio放大 canvas 的像素缓冲区并通过render的transform参数把绘制内容同步放大。本文按 官方示例文档 和 helloworld 示例 把这条操作路径走一遍。viewport 在渲染中起什么作用文档对 viewport 的说明是每个 PDF 页面都有自己的 viewport它定义像素72DPI尺寸和初始旋转默认情况下 viewport 缩放为 PDF 的原始大小也可以通过修改 viewport 改变缩放。创建 viewport 时会同时生成一个初始变换矩阵考虑期望的缩放和旋转并转换坐标系PDF 文档中 (0,0) 在左下角而 canvas 的 (0,0) 在左上角。对应 API 是PDFPageProxy.getViewport()参数为scale、rotation、offsetX、offsetY、dontFlip返回一个包含width、height属性以及渲染所需变换的PageViewport实现在 src/display/api.jsgetViewport({ scale, rotation this.rotate, offsetX 0, offsetY 0, dontFlip false, } {}) { return new PageViewport({ viewBox: this.view, userUnit: this.userUnit, scale, rotation, offsetX, offsetY, dontFlip, }); }所以scale控制的是“页面内容占多大”而 canvas 上的清晰度还取决于另一件事canvas 自身按多少物理像素绘制。这就是 HiDPI 处理要补上的一环。主路径按 helloworld 示例渲染第一页示例文件 examples/learning/helloworld.html 引用的是本地构建产物路径../../node_modules/pdfjs-dist/build/pdf.mjs和pdf.worker.mjs因此先在项目根目录安装依赖再在浏览器中打开该 HTML 文件即可复现。准备部分是三件事加载 pdfjs 模块、指定 worker 脚本、拿到第一页。示例中的注释明确workerSrc必须指定当 worker 脚本与 PDF.js 主文件不在同一目录时pdfjsLib.GlobalWorkerOptions.workerSrc ../../node_modules/pdfjs-dist/build/pdf.worker.mjs; const loadingTask pdfjsLib.getDocument({ url: ./helloworld.pdf }); const pdf await loadingTask.promise; const page await pdf.getPage(1);然后是 HiDPI 渲染的核心代码与 文档中的写法 一致const scale 1.5; const viewport page.getViewport({ scale }); // Support HiDPI-screens. const outputScale window.devicePixelRatio || 1; const canvas document.getElementById(the-canvas); const 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; const transform outputScale ! 1 ? [outputScale, 0, 0, outputScale, 0, 0] : null; const renderContext { canvasContext: context, transform, viewport, }; page.render(renderContext);逐行看关键是三处canvas.width/canvas.height按viewport × outputScale设置这是 canvas 的物理像素缓冲区决定实际绘制精度canvas.style.width/canvas.style.height只按viewport设置 CSS 像素页面上的布局尺寸不变outputScale ! 1时给renderContext传入[outputScale, 0, 0, outputScale, 0, 0]这个缩放变换矩阵让渲染内容跟随缓冲区放大outputScale为 1 时transform传null不做额外变换。代码库自身的渲染路径也用同样的兜底策略src/display/display_utils.js 中统一以globalThis.devicePixelRatio || 1获取像素密度即读不到devicePixelRatio时按 1 处理。按示例代码执行后的结果是canvas 的 CSS 尺寸等于viewport.width/height内部分辨率再乘以devicePixelRatio页面内容按transform同步放大绘制——这正是文档注释里 “Support HiDPI-screens” 所指的清晰度做法。可选分支指定 canvas 的 CSS 像素宽度如果你不是按固定scale渲染而是想让 canvas 呈现某个特定宽度文档给出的算法是先用scale: 1的 viewport 求出目标缩放再重新创建 viewport文档示例var desiredWidth 100; var viewport page.getViewport({ scale: 1, }); var scale desiredWidth / viewport.width; var scaledViewport page.getViewport({ scale: scale, });之后把scaledViewport传给渲染HiDPI 处理方式与主路径相同。多页翻页时同一 canvas 不能同时画两页如果页面支持前后翻页还要注意文档指出的一点同一个 canvas 不能同时用于绘制两页必须先等上一次渲染完成。prevnext 示例 展示了完整做法HiDPI 部分代码与主路径相同额外加了一个排队逻辑var renderTask page.render(renderContext); // Wait for rendering to finish renderTask.promise.then(function () { pageRendering false; if (pageNumPending ! null) { // New page rendering is pending renderPage(pageNumPending); pageNumPending null; } });queueRenderPage(num)的逻辑是若正在渲染pageRendering为true把请求记到pageNumPending等renderTask.promise完成后再触发否则直接渲染。这样翻页按钮快速连点时不会让两次render竞争同一个 canvas。限制说明上述代码依赖浏览器环境下的window.devicePixelRatio示例代码和代码库都用|| 1兜底取值失败时退化为普通像素密度渲染。viewport定义的是 72DPI 下的像素尺寸scale改变的是页面在 viewport 中的大小清晰度由 canvas 缓冲区outputScale与transform共同保证两者要配套使用。文档没有对“渲染清晰”给出量化判定标准验证方式就是运行示例页面在devicePixelRatio 1的环境下canvas.width应等于Math.floor(viewport.width * outputScale)而 CSS 尺寸保持viewport.width不变。【免费下载链接】pdf.jsPDF Reader in JavaScript项目地址: https://gitcode.com/gh_mirrors/pd/pdf.js创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

分布式计算检查点机制:原理、实现与调优实战 2026/9/9 23:43:40

分布式计算检查点机制:原理、实现与调优实战

没做检查点之前,我一直觉得分布式计算的任务挂了大不了重跑一遍,直到第一次跑一个十几个小时的离线任务在最后一步挂在凌晨三点,第二天早上才发现需要从头再来,那个滋味谁经历过谁知道。后来认真研究并实践了检查点机制&#xff0…

阅读更多 →
用15个Claude智能体重构研发流程:多Agent协作实战指南 2026/9/9 23:43:40

用15个Claude智能体重构研发流程:多Agent协作实战指南

"一个人要干一整个公司的活"这话换在五年前我是打死不信的,直到我认真跟这个由YC掌门人带火的开源玩法死磕了两周,用一整套Claude智能体矩阵把原本至少需要七八个人的研发流程硬生生扛了下来。这篇文章不聊虚的,就讲15个硬核Agent怎…

阅读更多 →
MFC+CSocket聊天室开发实战:原理、代码与避坑指南 2026/9/9 23:43:40

MFC+CSocket聊天室开发实战:原理、代码与避坑指南

简介:基于VS2010和CSocket编写的MFC聊天室服务器端程序,面向需要完成网络编程课程设计或毕业设计的开发者,也适合对Socket通信机制感兴趣的中初级程序员。服务器端启动后可与多个客户端同时建立连接,并支撑客户端之间相互转发消息…

阅读更多 →
Ultralytics 平台团队角色与权限体系详解:Owner、Admin、Editor、Viewer 的 RBAC 指南 2026/9/9 23:43:40

Ultralytics 平台团队角色与权限体系详解:Owner、Admin、Editor、Viewer 的 RBAC 指南

Ultralytics 平台团队角色与权限体系详解:Owner、Admin、Editor、Viewer 的 RBAC 指南 【免费下载链接】ultralytics Ultralytics YOLO26, YOLO11, YOLOv8 — object detection, instance segmentation, semantic segmentation, image classification, pose estimat…

阅读更多 →
旧Mac免费升级指南:OpenCore Legacy Patcher让老设备装上macOS Sonoma 2026/9/9 23:43:40

旧Mac免费升级指南:OpenCore Legacy Patcher让老设备装上macOS Sonoma

旧Mac免费升级指南:OpenCore Legacy Patcher让老设备装上macOS Sonoma 【免费下载链接】OpenCore-Legacy-Patcher Experience macOS just like before 项目地址: https://gitcode.com/GitHub_Trending/op/OpenCore-Legacy-Patcher OpenCore Legacy Patcher&a…

阅读更多 →
FastAPI 附加状态码(Additional Status Codes):在同一路径操作中返回 200 与 201 2026/9/9 23:40:40

FastAPI 附加状态码(Additional Status Codes):在同一路径操作中返回 200 与 201

FastAPI 附加状态码(Additional Status Codes):在同一路径操作中返回 200 与 201 【免费下载链接】fastapi FastAPI framework, high performance, easy to learn, fast to code, ready for production 项目地址: https://gitcode.com/GitH…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞