vue3中使用pdf.js、实现移动端、PC端的PDF预览、支持绝大部分情况
之前一直使用的pdf.js+canvas的形式预览PDF,但是这有一个很大的弊端,就是canvas生成的图片太糊了,而且本质上这渲染的根本不是pdf,而是一张图片,很多pdf中带有的功能这里都不能实现。我的理解是,在手机端使用手势缩放放大缩小pdf后,出现了错乱的情况,这时候我再手动调用一下源码中自带的。我在源码中加了一个被我隐藏的按钮,并为其添加点击事件,在缩放完成后,调用点击事件,完成pdf的
业务场景
pdf.js可以说是预览PDF的全能插件,里面内置了很多方法供开发者使用。
之前一直使用的pdf.js+canvas的形式预览PDF,但是这有一个很大的弊端,就是canvas生成的图片太糊了,而且本质上这渲染的根本不是pdf,而是一张图片,很多pdf中带有的功能这里都不能实现
比如
- pdf全局搜索
- 缩小放大任能保持清晰度
- 指定页跳转,上下一页
- 对当前预览的文件,开启在线演示模式
- 支持在 viewer.html 添加水印
- …等等操作
本文只做最基础的,能让你在移动端,PC端正常预览PDF的功能,扩展操作不做解释
下载pdf.js源码
最新版下载地址,下载哪个自己选择,我没有细看他们之间的区别,我选择的下载第一个
历史版本下载地址
如果你需要下载历史版本的话,选择你想要的版本,点击Downloads进入下载页面
这里会告诉你这个版本都做哪些优化或者其他工作,之后拉到页面最下面,点击下载第一个

下载完成之后你会得到一个压缩包,(你可能会好奇,为什么不直接npm install这种下载形式,而要下载一个压缩包,没关系继续看)
会得到一个这样目录的压缩包
build文件夹
web文件夹
OK,到这里已经完成pdf.js的下载工作
接下来我会使用vite脚手架搭建一个新的vue3项目作为演示
引入PDF.JS并使用他来预览我们的第一份PDF文件
这是我创建的一个空的vue3项目,刚初始化完成的,我新建了一个 pdfJSDemo.vue 文件作为演示的入口

现在,将我们刚才下载好的pdf.js文件,放到项目的public文件下新建的pdfJS文件中(是不是public文件都无所谓,这里作为演示)
注意这里的viewer.html文件,你可能在其他博客中见到这个文件,他们指的都是这个文件,我们之后所有的操作都要针对这个文件进行
我们先打开一个pdf.js给我们提供的默认pdf看看效果,也就是下面这个文件

打开的方式是,启动你项目之后的 开发地址 + pdfJS/web/viewer.html (如果你是按照我的文件夹目录来的话,可以直接复制)

这是我的启动地址,所以拼接的地址就是 http://localhost:5173/pdfJS/web/viewer.html
如果你成功打开了这个页面,且没有任何报错,那就表示你的第一个预览PDF已经完成了

那么接下来我们来打开一个自己的PDF吧,自己的PDF有两种形式
- 本地的PDF文件,展示在页面上(那操作就和上面一模一样了,没啥好说的,重复上面的步骤就行)
- 后端返回的PDF链接,需要我们展示在页面上(这里以阿里云的PDF链接为例)
第二种预览形式,只需要在上面的连接上加上一个file=your-pdf-url就行了:开发地址 + pdfJS/web/viewer.html?file=your-pdf-url
举个例子 http://localhost:5173/pdfJS/web/viewer.html?file=http://wuneng-public.oss-cn-hangzhou.aliyuncs.com/wp/infoConfig/demo/NKRRQUGX20230908050411
这时,你可能会出现这么一个错误,然后pdf无法正确渲染出来,这是因为这个pdf链接发生了跨域

你要找到 throw new Error("file origin does not match viewer's"); 这段代码,并注释掉

保存之后刷新页面,这样一个链接形式的pdf就被渲染出来了

手机端的一个bug问题
因为我们使用pdfjs主要是解决手机端浏览器无法预览PDF的情况,但是pdfjs在手机端浏览器上有点bug
这是我使用微信浏览器打开的pdfjs官网给的一个demo页面,当在手机上进行缩放的时候,会导致显示错乱的情况,下面的图应该能很清楚的看到错乱情况
且很多其他浏览器,比如手机端的chrome浏览器,Safari浏览器,夸克浏览器会出现不同情况的缩放问题,总之很诡异。虽然官网上说他们的插件主要支持火狐浏览器,但是我试了火狐浏览器,还是有问题

手机端缩放bug,我的解决方式
- 限制页面不能进行缩放
user-scalable=no,这可以避免(Chrome、Safari浏览器之类的缩放问题)
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
- 设置页面属性zoom为1
body {
zoom: 1; /* 设置缩放比例为1,即不缩放 */
}
- 根据页面的按钮点击事件,找到对应的源码,修改源码的缩放事件
我的理解是,在手机端使用手势缩放放大缩小pdf后,出现了错乱的情况,这时候我再手动调用一下源码中自带的
update方法

我在源码中加了一个被我隐藏的按钮,并为其添加点击事件,在缩放完成后,调用点击事件,完成pdf的更新
.myBtn {
position: absolute;
opacity: 0;
}

在viewer.js源码文件里,在这里添加根据 ID 获取 DOM 元素
在viewer.js源码文件里,这一段代码中,注册DOM元素的点击事件





有很多地方的事件注册,我这里应该是截图完了,单也可能是哪里忘记截图了
- 手势结束事件后,手动触发upadte事件
const c_viewerContainer = document.getElementById('viewer')
c_viewerContainer.addEventListener('touchend', handleTouchEnd, false)
// 手势结束事件
function handleTouchEnd(event) {
myBtnUpdate.click()
}
抛砖引玉,我这个方法虽然可以解决,但是太僵硬了,为了解决而解决,肯定是有更好的办法的
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐


所有评论(0)