🔥 用 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 行,功能却很实用。如果你有更好的想法或者遇到问题,欢迎在评论区留言交流!

相关推荐
Ali酱1 分钟前
远程这两年,我才真正感受到——工作,原来可以不必吞噬生活。
前端·面试·远程工作
金金金__6 分钟前
优化前端性能必读:浏览器渲染流程原理全揭秘
前端·浏览器
Data_Adventure10 分钟前
Vue 3 手机外观组件库
前端·github copilot
泯泷15 分钟前
Tiptap 深度教程(二):构建你的第一个编辑器
前端·架构·typescript
黑幕困兽21 分钟前
vue 项目给输入框增加trim()方法
vue.js
屁__啦22 分钟前
前端错误-null结构
前端
lichenyang45322 分钟前
从0开始的中后台管理系统-5(userList动态展示以及上传图片和弹出创建用户表单)
前端
未来之窗软件服务26 分钟前
解析 div 禁止换行与滚动条组合-CSS运用
前端·css
不远处的小阿秋1 小时前
2025年,前端还需要虚拟DOM吗
前端
DcTbnk1 小时前
tailwindcss、postcss、autoprefixer,这三个分别是干嘛的
前端