使用
vue-pdf中,使用base64文件格式实现展示,或者路径直接展示的方法,为包增加补丁使用patch-package
首先下载包
yarn安装
yarn install vue-pdf
npm安装
npm install --save vue-pdf
项目实际使用
<!--## 关于使用PreviewPdf组件-->
<!-- - 需要将node_modules >> vue-pdf >> src >> pdfjsWrapper.js文件中第196-198行改为-->
<!--pdfRender.cancel();这是因为报错问题,下面讲怎么设置补丁,其他人更包也可以直接使用-->
<template>
<div class="TopClass">
<div class="preview-pdf-wrapper" ref="handlePicture">
<div class="preview-pdf" ref="handleImg" @wheel="handleWheel" @mousedown="handleMousedown" @dblclick="magnify">
<pdf :src="path" :page="page" :rotate="rotate" @num-pages="pagesCount"></pdf>
</div>
</div>
</div>
</template>
<script>
import pdf from 'vue-pdf' // 这是pdf的引入
import CMapReaderFactory from 'vue-pdf/src/CMapReaderFactory.js' //这个引入是因为pdf汉字可能乱码,需要引入这个
export default {
name: 'PreviewPdf',
components: {
pdf },
props: {
src: {
type: String },
showsection: {
type: Boolean, default: false },
pathurl: {
type: String },
RefDate:{
type: String }
},
data() {
return {
// src: '../../../static/pdf/111.pdf', // 如果是本地引入,一定要放在public下面,不然可能加载不出来
path: '',
page: 1,
pageCount: 0,
rotate: 0,
dragging: false,
lastLeft: 0,
lastTop: 0,
parentWidth: null,
parentHeight: null,
}
},
created() {
this.pdfData()
},
mounted() {
this.$nextTick(() => {
const {
width: parentWidth, height: parentHeight } = this.$refs.handlePicture.getBoundingClientRect()
this.parentWidth = parentWidth
this.parentHeight = parentHeight
this.dragDialog()
})
},
methods: {
magnify(){
window.open(this.pathurl) //这是为了预览大图使用,就是在浏览器直接打卡,赋值路径就可以了可以后端返,也可以使用base64下面的方法转后,直接把path给它
},
// 赋值给页面转base64
pdfData() {
let datas = `data:application/pdf;base64,${
this.src}` // 这是因为项目中遇到跨域,需要使用base64格式来展示,所以这样做,如果项目不涉及跨域,直接用下面这个就可以了,传路径就可以出来了
// this.path = pdf.createLoadingTask({ url: datas, CMapReaderFactory });
pdf.createLoadingTask(datas, {
CMapReaderFactory }).promise.then(pdf => {
this.path = pdf.loadingTask })
},
pagesCount($event) {
this.pageCount = $event
},
//pdf翻页上一页
changePage(type) {
this.resetSize()
this.rotate = 0
if (type === 'prev' && this.page > 1) {
this.page -= 1
} else if (type === 'next' && this.page < this.pageCount) {
this.page += 1
}
},
// 左右旋转使用
rotateRight(type){
if (type === 'L' ) {
this.rotate -= 90
} else if (type === 'R' ) {
this.rotate += 90
}
},
//旋转
rotatePDF() {
this.rotate += 90
},
//放大缩小
handleWheel(e) {
if(this.showsection !== true) return
e.preventDefault()
let el = e.currentTarget
let delta = (e.wheelDelta && (e.wheelDelta > 0 ? 1 : -1))
if (delta > 0) {
//放大
// 向上滚
let oWidth = el.offsetWidth//取得图片的实际宽度
let oHeight = el.offsetHeight //取得图片的实际高度
el.style.width = (oWidth + 50) + 'px'
el.style.height = (oHeight + 50 / oWidth * oHeight) + 'px'
} else if (delta < 0) {
//缩小
//向下滚
let oWidth = el.offsetWidth //取得图片的实际宽度
let oHeight = el.offsetHeight //取得图片的实际高度
if (el.offsetLeft < 0 || el.offsetTop < 0) {
this.$refs.handleImg.style.left = 0
this.$refs.handleImg.style.top = 0
}
if (el.offsetWidth > this.parentWidth || el.offsetHeight > this.parentHeight) {
//判断如果图片缩小到原图大小就停止缩小(不能小于包裹它的父元素的宽高)
el.style.width = oWidth - 50 + 'px'
el.style.height = oHeight - 50 / oWidth * oHeight + 'px'
}
}
},
//还原尺寸
resetSize() {
this.$refs.handleImg.style.minwidth = '100%'
this.$refs.handleImg.style.minheight = '100%'
this.$refs.handleImg.style.left = 0
this.$refs.handleImg.style.top = 0
},
//鼠标在图片上落下,可拖动
handleMousedown($event) {
if(this.showsection !== true) return
$event.preventDefault()
this.lastLeft = $event.clientX
this.lastTop = $event.clientY
this.dragging = true
},
//拖动
startDragging(e) {
if (this.dragging) {
this.calculateDragging(e) }
},
//停止拖动
stopDrag() {
this.dragging = false
},
dragDialog() {
document.addEventListener('mousemove', this.startDragging)
document.addEventListener('mouseup', this.stopDrag)
},
calculateDragging(e) {
let deltaX = e.clientX - this.lastLeft
let deltaY = e.clientY - this.lastTop
const {
offsetLeft, offsetTop } = this.$refs.handleImg
let resultX = this.calculateBeyond('x', offsetLeft + deltaX)
let resultY = this.calculateBeyond('y', offsetTop + deltaY)
this.$refs.handleImg.style.left = resultX + 'px'
this.$refs.handleImg.style.top = resultY + 'px'
this.lastLeft = e.clientX
this.lastTop = e.clientY
},
calculateBeyond(type, result) {
const {
width, height } = this.$refs.handleImg.getBoundingClientRect()
if (type === 'x') {
if (width <= this.parentWidth) return //仅当图片宽度超出父级元素的宽度时才能被拖动
if (result < -(width - this.parentWidth)) {
return -(width - this.parentWidth)
} else if (result > 0) {
return 0
} else {
return result
}
} else if (type === 'y') {
if (height <= this.parentHeight) return //仅当图片高度超出父级元素的高度时才能被拖动
if (result < -(height - this.parentHeight)) {
return -(height - this.parentHeight)
} else if (result > 0) {
return 0
} else {
return result
}
}
}
},
}
</script>
<style scoped lang='scss'>
.TopClass {
width: 100%;
height: 100%;
.preview-pdf-wrapper {
width: 100%;
height: 98%;
position: relative;
overflow: hidden;
.preview-pdf {
min-width: 100%;
min-height: 100%;
position: absolute;
left: 0;
top: 0;
transition: transform 0.25s linear;
}
}
.btnclass {
position: absolute;
height: 100%;
right: 20px;
.BtnClass {
display: flex;
justify-content: flex-end;
.el-button {
margin: 5px;
}
}
}
}</style>
遇到的问题
1、使用中,有遇到包内保存,最上面已经写了怎么解决,找到包
将这里的内容修改
2、循环遍历出来的组件,在使用中,一定要将vue-pdf组件销毁注释掉,如果组件没有加载完成,pdf.createLoadingTask不会出数据
3、在多个pdf文件渲染中,出现一个问题,出现有数据无法加载,渲染的问题,好像是pdf使用的promise给数据,数据没有取到,就会出现这种情况,单个的pdf组件没有出现这个问题,但是我是使用的多个遍历出来的,所以遇到问题有点坑,最后是使用的这个解决
获取到再赋值,这样就不会拿不到了
pdf.createLoadingTask(datas, {
CMapReaderFactory }).promise.then(pdf => {
this.path = pdf.loadingTask })
patch-package的使用
npm安装
npm i patch-package
yarn安装
// v1.x:
yarn add patch-package postinstall-postinstall
// v2.x
yarn patch
在文件中,找到package.json加入
"postinstall": "patch-package"
修改了node_modules内的依赖后,运行一下命令
npm patch-package +包名
如npm patch-package vue-pdf
yarn patch-package +包名
如yarn patch-package vue-pdf
运行后,会多一个文件,
这个里面会有添加的补丁内容,下次新增会在里面继续更新