🔥 用 Vue2 + PDF.js 手撸一个「PDF 连续预览器」,自适应屏幕、支持缩放,直接拿来用!

🌈 前言

最近做项目,产品丢过来一个需求: "我们要一个像掘金文章那样的 PDF 连续预览功能,要自适应屏幕,还要支持放大缩小!"

我心想,这需求简单啊,直接搜一波现成的库,结果一看,要么太重,要么不支持连续预览,要么缩放体验差,要么样式丑。

于是,干脆自己撸一个!用 Vue2 + PDF.js ,花了一个下午,效果还不错,直接分享给大家,代码已经整理好了,复制粘贴就能用!

🚀 效果展示

  • ✅ 支持 PDF 文件上传预览
  • 连续滚动 显示所有页面,像浏览网页一样
  • 自适应屏幕宽度,窗口大小变化自动调整
  • 支持缩放(放大、缩小、重置)
  • 加载进度提示,体验更友好
  • 样式美观,代码简洁易读

📦 技术栈

  • Vue2:熟悉的响应式框架
  • PDF.js:Mozilla 出品的 PDF 渲染库,功能强大
  • FontAwesome:图标库,让按钮更美观

🛠️ 核心实现思路

1. 引入依赖

js 复制代码
<!-- Vue2 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<!-- PDF.js -->
<script src="https://cdn.jsdelivr.net/npm/pdfjs-dist@3.4.120/build/pdf.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/pdfjs-dist@3.4.120/build/pdf.worker.min.js"></script>
<!-- FontAwesome -->
<link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">

2. 文件上传

使用 <input type="file" accept=".pdf"> 实现文件选择,通过 FileReader 读取文件内容:

jshandleFileUpload(e) 复制代码
  const file = e.target.files[0];
  if (!file || file.type !== 'application/pdf') {
    this.errorMessage = '请上传PDF格式的文件';
    return;
  }

  const fileReader = new FileReader();
  fileReader.onload = (event) => {
    const typedArray = new Uint8Array(event.target.result);
    this.loadPdf(typedArray);
  };
  fileReader.readAsArrayBuffer(file);
}

3. 渲染 PDF 页面

使用 PDF.js 的 getDocument 方法加载 PDF,然后逐页渲染:

js 复制代码
renderPage(pageNum, containerWidth) {
  this.pdfDoc.getPage(pageNum).then(page => {
    const canvas = document.createElement('canvas');
    const context = canvas.getContext('2d');

    // 计算缩放比例,自适应容器宽度
    const viewport = page.getViewport({ scale: 1 });
    const baseScale = Math.min(containerWidth / viewport.width, 2);
    const scale = baseScale * this.zoom;
    const scaledViewport = page.getViewport({ scale });

    canvas.height = scaledViewport.height;
    canvas.width = scaledViewport.width;

    const renderContext = {
      canvasContext: context,
      viewport: scaledViewport
    };

    page.render(renderContext).promise.then(() => {
      this.loadedPages++;
    });
  });
}

4. 缩放功能

通过调整 zoom 值,重新渲染所有页面:

js 复制代码
zoomIn() {
  if (this.zoom < 3) {
    this.zoom += 0.1;
    this.reRenderAllPages();
  }
},
zoomOut() {
  if (this.zoom > 0.3) {
    this.zoom -= 0.1;
    this.reRenderAllPages();
  }
},
resetZoom() {
  this.zoom = 1.0;
  this.reRenderAllPages();
}

5. 自适应屏幕

监听窗口大小变化,自动重新渲染:

js 复制代码
mounted() {
  window.addEventListener('resize', () => {
    if (this.pdfDoc && this.showViewer) {
      this.reRenderAllPages();
    }
  });
}

📝 使用方式

  1. 复制文章开头提供的完整 HTML 代码
  2. 保存为 index.html
  3. 直接双击打开即可使用

🏁 结语

一个简单的 PDF 连续预览器就完成了,代码不到 300 行,功能却很实用。如果你有更好的想法或者遇到问题,欢迎在评论区留言交流!

相关推荐
水瓶夜之2 分钟前
.NET 中的新增功能系列文章——.NET SDK中的新增功能
前端·chrome·.net
笨笨狗吞噬者37 分钟前
VS Code 内置浏览器打开网页
前端
SamChan9038 分钟前
WebSocket实现PDF翻译进度实时推送:Go后端+React前端的完整方案
前端·websocket·pdf·c#·react·机器翻译
甲维斯1 小时前
DeepSeekFlash前端依旧拉垮,而且变慢了很多!
前端·人工智能
奈斯先生Vector1 小时前
大模型 Agentic Workflow 架构解构:异构 API 调度与 Token 路由的多模态系统设计
开发语言·前端·架构·prompt·aigc·音视频
海带紫菜菠萝汤1 小时前
FFmpeg.wasm 实践:在浏览器中运行 FFmpeg 的能力边界与性能瓶颈
前端·javascript·ffmpeg·音视频·wasm
名字还没想好☜1 小时前
React 受控输入框光标跳到末尾:格式化输入时的 selection 丢失 bug 与修复
前端·javascript·react.js·bug·react·next.js
Access开发易登软件1 小时前
Access 怎么做前后端分离?用 Web API 读写 SQL Server
前端·数据库·人工智能·microsoft·excel·access
10share1 小时前
React 新一代样式隔离方案 —— 编译时、零运行时、原生写法
前端·react.js
upgrador1 小时前
桌面应用开发:Electron 与 NSIS 的关系、打包流程及 Windows 本地构建实战
javascript·windows·electron