优雅地在网页中嵌入pdf且适配移动端浏览器

一、不需要考虑移动端显示效果的方法:

1、使用对象数据嵌入pdf

<object data="https://zzhanzhang.top/YOU_PDF.pdf"  height="800px" width="100%"></object>

优缺点:语法简洁,无需额外依赖,支持翻页缩放基础交互;但移动端适配差可控性低,安卓浏览器直接下载pdf文件了。

2、典中典<iframe>

<iframe>通过创建独立窗口加载 PDF,本质与<object>类似,都是依赖浏览器原生渲染。

<iframe src="https://zzhanzhang.top/YOU_PDF.pdf"  height="800px" width="100%"></iframe>

优缺点:与主页面隔离,避免 PDF 渲染影响页面其他元素,与<object>一样简洁,但移动端问题与<object>完全一致:渲染错乱、会触发直接下载;

3、<embed>标签嵌入

<embed>是早期用于嵌入多媒体资源的标签,功能与<object>高度重叠,现在已较少单独使用。

<embed src="https://zzhanzhang.top/YOU_PDF.pdf" type="application/pdf" width="100%"  height="800px" />

优缺点:移动端适配问题更严重:很多端浏览器会直接忽略<embed>标签,显示空白;兼容性最差。

二、借助第三方工具嵌入pdf并且自适应移动端浏览器

这里借助smallpdf这个在线工具生成一个容器可以放在网页中的任何部分,并且会自适应移动端浏览器的显示效果(本质是用 JS 封装了渲染逻辑)
免费将 PDF 嵌入你的网站https://smallpdf.com/cn/embed-pdf

<div 
  style="width: 100%; height: 580px; max-width: 1200px; margin: 0 auto;"  <!-- 加max-width避免桌面端过宽 -->
  class="smallpdf-widget" 
  data-pdf-url="https://zzhanzhang.top/YOU_PDF.pdf"
  data-download="false"  <!-- 可选:是否显示下载按钮(true/false) -->
  data-print="false"     <!-- 可选:是否显示打印按钮(true/false) -->
></div>
<!-- 引入SmallPDF的渲染脚本 -->
<script src="https://smallpdf.com/api/embed-widget.js"></script>

如图:

优点:
1、移动端会自动隐藏多余工具栏,仅保留翻页和缩放按钮;桌面端显示完整控件
2、无需写 JS 逻辑,配置属性即可自定义功能;
3、自动响应屏幕宽度,控件布局随设备调整;
4、支持基础自定义,可隐藏下载 / 打印按钮。

缺点:
1、若 SmallPDF 的 CDN 故障,PDF 将无法加载;
2、无法自定义主题色、无法监听页面切换事件;
3、查看器会带 SmallPDF 水印。

三、高级玩法,使用PDF.js达到完美的显示效果:

pdf.js简介:它是 Mozilla 开源的 PDF 渲染库,完全基于 JS 实现(不依赖浏览器原生能力),可精准控制移动端渲染逻辑。
这里需要引入PDF.js库和PDF工作者(worker):

  1. pdf.min.js:主库,负责 PDF 解析和渲染逻辑;
  2. pdf.worker.min.js:工作线程,负责异步解析 PDF(避免阻塞主线程)。

以下代码已优化移动端体验:自动适配屏幕宽度、支持垂直滚动、优化文本清晰度;

<div id="pdfContainer" style="width: 100%; height: 100vh; overflow-y: auto; overflow-x: hidden;"></div>

<!-- PDF.js库 -->
<script src="https://unpkg.com/pdfjs-dist@3.4.120/build/pdf.min.js"></script>
<script>
    const pdfjsLib = window['pdfjs-dist/build/pdf'];
    pdfjsLib.GlobalWorkerOptions.workerSrc = 
        'https://unpkg.com/pdfjs-dist@3.4.120/build/pdf.worker.min.js';
    const url = 'https://zzhanzhang.top/YOU_PDF.pdf';
    const container = document.getElementById('pdfContainer');
    const devicePixelRatio = window.devicePixelRatio || 1;
    const loadingTask = pdfjsLib.getDocument(url);
    loadingTask.promise.then(pdf => {
        const totalPages = pdf.numPages;
        for(let pageNum = 1; pageNum <= totalPages; pageNum++) {
            pdf.getPage(pageNum).then(page => {
                const canvas = document.createElement('canvas');
                canvas.id = `pdfCanvas-page-${pageNum}`;
                
                // 获取设备像素比
                const viewportWidth = window.innerWidth;
                const viewport = page.getViewport({ scale: 1.0 });
                const scale = (viewportWidth / viewport.width) * devicePixelRatio;
                const adaptedViewport = page.getViewport({ scale: scale });
                canvas.width = adaptedViewport.width;
                canvas.height = adaptedViewport.height;
                canvas.style.width = '100%';
                canvas.style.height = 'auto';
                canvas.style.display = 'block';
                canvas.style.margin = '0 auto';
                container.appendChild(canvas);
                // 渲染页面
                const renderContext = {
                    canvasContext: canvas.getContext('2d'),
                    viewport: adaptedViewport,
                    imageSmoothingEnabled: true,
                    textLayer: true
                };
                page.render(renderContext);
            });
        }
    });
</script>
  • 优点:
    1. 100% 可控,可自定义工具栏(如添加页码导航、缩放按钮)、主题色、批注功能;
    2. 移动端和桌面端渲染效果完全一致,无浏览器差异;
    3. 可下载库到本地部署,不依赖第三方服务;
  • 缺点:
    1. 需手动处理渲染逻辑、错误捕获、交互优化;
    2. 若 PDF 文件与网页不同域名,需要解决跨域问题;
    3. 针对大文件需自己实现分片加载或进度条(默认是一次性加载整个 PDF)。

四、我们还能做的其它事情

  • 压缩文件大小(用 SmallPDF、Adobe Acrobat 压缩),避免移动端加载过慢;
  • 大 PDF(超过 20 页)可实现「懒加载」(只渲染可视区域的页面),减少初始加载时间;