如何使用PDFObject显示PDF文件(不限字体)
一、问题背景及PDFObject简介
1、问题背景
在无纸化看图的项目中,使用VUE—PDF插件进行图纸的预览,但是出现了个别图纸乱码的现象。
针对该问题,初步确定为字体问题,于是安装了字体样式,但是没有效果,并且切换了PDF-distjs、VUE-office-pdf等插件都无效。查阅大量资料后,选择使用PDFObject进行预览效果实现。
2、PDFObject简介
PDFObject 是一个用于在网页上嵌入 PDF 文档的 JavaScript 库。它提供了一种简单的方式来嵌入 PDF 文件,让用户可以在网页上直接查看和交互式地操作 PDF。
PDFObject实际上也是通过iframe标签中的embed标签实现的媒体文件显示,在控制台中可以看到显示的标签为embed。
相较于iframe显示,PDFObject有以下五个优点:
- 跨浏览器支持:PDFObject 支持各种主流浏览器,包括 Chrome、Firefox、Safari、Edge 等。它会自动检测浏览器的支持情况,并使用适当的方法来嵌入 PDF 文件。
- 简单易用:PDFObject 的使用非常简单,只需要引入库文件,并使用几行代码即可完成嵌入操作。你可以指定 PDF 文件的 URL,或者直接使用文件的路径进行嵌入。
- 各种配置选项:PDFObject 提供了一些配置选项,以便你可以自定义嵌入的 PDF 文件的外观和行为。你可以设置宽度和高度、自动调整大小、显示信息、替代文本等等。
- 提供回退选项:如果用户的浏览器不支持嵌入 PDF 或者没有合适的 PDF 阅读器插件,PDFObject 会提供一个回退选项,让用户可以下载 PDF 文件或者在新窗口中打开。
- 支持响应式布局:PDFObject 可以与响应式布局一起使用,以适应不同屏幕尺寸和设备。你可以根据需要调整容器的大小和样式,以实现适应性布局。
附上官网地址
二、PDFObject使用
1、引入
npm i pdfobject --save
2、页面中使用
<template>
<div>
<div id="pdfContent" v-show='pdfdata' >
<div v-show='pdfdata' id="pdfContainer" style="height: 79vh;width: 100%;" ></div>
</div>
</div>
</template>
<script>
import PDFObject from 'pdfobject'
export default {
name: 'ViewPDF',
data() {
return {
pdfdata:'',//pdf的dataurl
pdfOptions:{ //显示的配置信息
pdfOpenParams: {
toolbar: 0, // 设置为0来隐藏头部工具栏
zoom:100 //大小设置
},
}
}
},
mounted() {
this.getData();
},
methods: {
getData() {
//从接口获取pdf数据
......
//渲染PDF的方法,固定格式
if(PDFObject.supportsPDFs){//检测浏览器是否支持显示pdf
PDFObject.embed(this.pdfdata, "#pdfContainer", this.pdfOptions);
} else {
this.$message({
message: '该浏览器不支持切换,请更换浏览器',
type: 'warning'
});
}
}
}
}
</script>
以上为pdf显示的大致方法,PDFObject还能够设置是否强制使用pdfjs显示,更多配置请见官网。需要注意的是,div中需要设置id,随后渲染函数能够找到是哪个div。
三、控制下载
在上述操作中,已经实现了PDF的显示,但是这种显示与iframe显示差异不大。在无纸化看图的应用场景中,需要控制用户不能右键自己下载图纸,只能通过接口下载。针对该功能,有以下两种解决方案:
1、阻止鼠标右键事件
//在显示pdf的div中添加 οncοntextmenu="return false;"
<div v-show='pdfdata' id="pdfContainer" style="height: 79vh;width: 100%;" oncontextmenu="return false;"></div>
//或者加上这段代码,禁止鼠标右键功能
document.oncontextmenu = function () {
return false;
}
但是这种方式在嵌套很较深的页面中,有可能会无法获取到页面元素,因此提供了第二种方法。
2、设置遮罩层阻挡鼠标
//添加如下css代码,position属性需要注意子绝父相
#pdfContent {
position: absolute;
width: 100%;
height: 100%;
}
#pdfContent::before {
content: "";
position: absolute;
/*将右侧滚动条与下方滚动条露出来*/
width: calc(100% - 15px);
height: calc(100% - 20px);
/* 添加半透明的遮罩层 */
background-color: rgba(0, 0, 0, 0.01);
/* 设置遮罩层可以捕捉鼠标事件 */
pointer-events: auto;
/* 将遮罩层放在子元素上面 */
z-index: 2;
}
#pdfContainer {
position: relative;
/* 将子元素放在遮罩层下面 */
z-index: 1;
}
使用这种方法可以实现鼠标无法直接点击到pdf上,而是点击在遮罩层上,但是使用这种方法,无法顺滑的放大缩小,因此需要手动写一个放大缩小功能,示例代码如下。
//放大
this.pdfOptions.pdfOpenParams.zoom+=10
//缩小
this.pdfOptions.pdfOpenParams.zoom-=10
//刷新页面
this.$nextTick(()=>{
PDFObject.embed(this.pdfdata, "#pdfContainer", this.pdfOptions);
})
实现效果:
四、注意事项
在ELectron客户端的开发中使用PDFObject,发现无法使用pdfOptions属性来控制PDF的显示属性,但是好在客户端中右键可以自主控制,所以只需要控制显示的操作栏。