基于版本 2.0.489 实现预览pdf
npm install pdfjs-dist@2.0.489
如果选用了其他版本,在调用getDocument的时候报错,建议直接打印一下 PDFJS 这个方法,因为在不同的大版本时,会有不同的调用方法
首先引入对应的依赖依赖以及数据流
<script>
import PDFJS from "pdfjs-dist";
import { baseData } from "./base64Data"; // 这里引入pdf数据流,如果是直接拿远程pdf文件,会出现跨域的情况.可以让后端转化成base64数据流返回
</script>
创建canvas画布,每一页的pdf对应一个canvas.
<template>
<div>
<canvas :id="'canvasPdf'+page" v-for="page in count" :key="page"></canvas>
</div>
</template>
methods: {
// 页面初始化方法
init() {
const _this = this;
let pdfBase64Data = atob(baseData); //解码base64编码字符串
PDFJS.getDocument({ data: pdfBase64Data }).then(res => {
_this.pdfDoc = res;
_this.count = res.numPages; //pdf的页数
_this.$nextTick(() => {
_this.renderPage(1);
});
});
},
renderPage(num) {
const _this = this;
_this.pdfDoc.getPage(num).then((page) => {
// 拿到对应的canvas的id
let canvas = document.getElementById("canvasPdf" + num);
let ctx = canvas.getContext("2d");
let dpr = window.devicePixelRatio || 1;
let bsr =
ctx.webkitBackingStorePixelRatio ||
ctx.mozBackingStorePixelRatio ||
ctx.msBackingStorePixelRatio ||
ctx.oBackingStorePixelRatio ||
ctx.backingStorePixelRatio ||
1;
let ratio = dpr / bsr;
let scale = _this.pdfWidth / page.getViewport(1).width;
let viewport = page.getViewport(scale);
canvas.width = viewport.width * ratio;
canvas.height = viewport.height * ratio;
canvas.style.width = viewport.width + "px";
canvas.style.height = viewport.height + "px";
ctx.setTransform(ratio, 0, 0, ratio, 0, 0);
let renderContext = {
canvasContext: ctx,
viewport: viewport,
};
page.render(renderContext);
// 绘制pdf做递归处理,当pdf的页数小于传入的页数,跳出递归
if (_this.count > num) {
setTimeout(() => {
_this.renderPage(num + 1);
}, 500);
}
});
}
}
完整代码支持些许功能,参数如下.往大佬指点
属性
名字 | 必输 | 类型 | 默认值 | 说明 |
---|---|---|---|---|
pdfUrl | true | string | 传入pdf的地址url | |
pdfWidth | true | number | 显示pdf内容的宽 | |
pdfHeight | true | number | 显示pdf内容的高 | |
pdfTitle | false | string | pdf头部标题 | |
isNeedButton | false | boolean | false | 是否需要按钮 |
isCountDown | false | boolean | false | 当isNeedButton为true生效,是否需要倒计时 |
countDown | false | number | 30 | 倒计事件(秒) |
事件
名字 | 事件说明 | 备注 |
---|---|---|
on-click | click | 点击按钮,返回值 |
caseError | error | 接口请求失败/渲染出错返回错误信息 |
<template>
<div class="pdf" :style="{'width': pdfWidth + 'px', 'height': pdfHeight + 'px'}">
<div class="pdf-title" v-if="pdfTitle">{{pdfTitle}}</div>
<div class="pdf-content">
<canvas :id="'canvasPdf'+page" v-for="page in count" :key="page"></canvas>
</div>
<div v-if="isNeedButton">
<div v-if="!isCountDown" class="bottomBtn" :style="buttonActive" @click="submit(true)">确定</div>
<div
@click="submit(false)"
v-if="isCountDown"
class="bottomBtn"
:style="countDown == 0 ? buttonActive : buttonDisabled"
>确定{{` ${countDown}`}}</div>
</div>
</div>
</template>
<script>
import PDFJS from "pdfjs-dist";
import { baseData } from "./base64Data"; // 此处为引入的base64数据流,需要更改
export default {
props: {
// PDF内容宽
pdfWidth: {
type: Number,
default: 0,
},
// PDF内容高
pdfHeight: {
type: Number,
default: 0,
},
// 是否需要按钮
isNeedButton: {
type: Boolean,
default: false,
},
// 是否按钮需要倒计时
isCountDown: {
type: Boolean,
default: false,
},
// 倒计时
countDown: {
type: Number,
default: 30,
},
pdfUrl: {
type: String,
defaut: "",
},
pdfTitle: {
type: String,
defaut: "",
},
},
data() {
return {
pdfDoc: "",
count: 0,
buttonActive: {
background: "#ea2c1d",
color: "white",
},
buttonDisabled: {
background: "#D3D3D3",
color: "#696969",
},
};
},
watch: {
// 按钮倒计时
countDown(val) {
if (val == 0) {
clearInterval(this.setIntervalID);
this.countDown = "";
}
},
},
methods: {
init() {
const _this = this;
let pdfBase64Data = atob(baseData);
PDFJS.getDocument({ data: pdfBase64Data }).then(res => {
this.setIntervalID = setInterval(() => {
_this.countDown--;
}, 1000);
_this.pdfDoc = res;
_this.count = res.numPages;
_this.$nextTick(() => {
_this.renderPage(1);
});
});
},
// 渲染pdf
renderPage(num) {
const _this = this;
_this.pdfDoc.getPage(num).then(page => {
let canvas = document.getElementById("canvasPdf" + num);
let ctx = canvas.getContext("2d");
let dpr = window.devicePixelRatio || 1;
let bsr =
ctx.webkitBackingStorePixelRatio ||
ctx.mozBackingStorePixelRatio ||
ctx.msBackingStorePixelRatio ||
ctx.oBackingStorePixelRatio ||
ctx.backingStorePixelRatio ||
1;
let ratio = dpr / bsr;
console.log("screen.availWidth", screen.availWidth);
let scale = _this.pdfWidth / page.getViewport(1).width;
console.log("scale", scale);
let viewport = page.getViewport(scale);
canvas.width = viewport.width * ratio;
canvas.height = viewport.height * ratio;
canvas.style.width = viewport.width + "px";
canvas.style.height = viewport.height + "px";
ctx.setTransform(ratio, 0, 0, ratio, 0, 0);
let renderContext = {
canvasContext: ctx,
viewport: viewport,
};
page.render(renderContext);
if (_this.count > num) {
setTimeout(() => {
_this.renderPage(num + 1);
}, 500);
}
});
},
submit(flag) {
if (flag) {
this.$emit("on-click", true);
} else {
if (this.countDown > 0) {
return;
} else {
this.$emit("on-click", true);
}
}
},
},
created() {
this.init();
},
};
</script>
<style scoped>
.pdf {
overflow-y: scroll;
}
.pdf-title {
margin: 10px 0;
text-align: center;
}
.pdf-content {
display: flex;
flex-direction: column;
}
.bottomBtn {
width: 80%;
height: 45px;
margin: 15px 0;
position: relative;
left: 50%;
transform: translateX(-50%);
text-align: center;
line-height: 45px;
}
</style>