效果如图:
1.安装
npm i pdfjs-dist
2.使用
// pdf.vue
<template>
<div class="wrap" v-loading="isLoading">
<div class="pdf-container">
<canvas ref="watermark" class="watermark"></canvas>
<canvas ref="myCanvas"></canvas>
</div>
<div class="pdf-control">
<div class="pdf-control-page">
<img src="@assets/img/cloud/left.png" @click="prev" />
<span class="page-number-container">
<input
type="number"
v-model="pageNum"
class="page-number-input"
@blur="queueRenderPage(pageNum)"
/>
/ {{ pageCount }}页
</span>
<img src="@assets/img/cloud/right.png" @click="next" />
</div>
<div class="pdf-control-zoom">
<img class="zoom-out" src="@assets/img/cloud/zoomOut.png" @click="minus" />
<img src="@assets/img/cloud/zoomIn.png" @click="addscale" />
</div>
</div>
</div>
</template>
<script>
import pdfJS from "pdfjs-dist";
export default {
data() {
return {
isLoading: false,
pdfUrl: "", // PDF的base64
pdfDoc: null, // pdfjs 生成的对象
pageNum: 0, // 当前页数
pageRendering: false,
pageNumPending: null,
scale: 1, // 放大倍数
page_num: 0, // 当前页数
pageCount: 0, // 总页数
maxscale: 5, // 最大放大倍数
minscale: 0.3, // 最小放大倍数
waterInfo: {}
};
},
computed: {
docid() {
return this.$route.query.docid;
}
},
async created() {
this.isLoading = true;
this.getPreviewossUrl();
this.waterInfo = await this.getWaterInfo()
if (this.waterInfo.enable) {
this.createWatermarkTemplate();
}
},
methods: {
// 获取水印信息
async getWaterInfo() {
return this.$api.cloud.getWaterInfo()
},
// 获取文件
getCloudFilePreviewoss() {
return this.$axios.post("cloud_disk/file/previewoss", {
docid: this.docid
});
},
async getPreviewossUrl() {
const res = await this.getCloudFilePreviewoss();
if (res.code == 10000) {
this.getBlob(res.result);
} else {
this.isLoading = false;
this.isError = true;
this.error = res.msg;
}
},
getBlob(result) {
this.$axios
.get(
result.previewUrl,
{ responseType: "blob" },
{
headers: {
"Access-Control-Allow-Origin": "*",
},
}
)
.then((res) => {
var blob = new Blob([res], {
type: "application/pdf;chartset=UTF-8",
});
let fileURL= URL.createObjectURL(blob)
this.pdfUrl = fileURL
this.init()
})
.catch((error) => {
this.isLoading = false;
console.log("error", error);
});
},
// 水印模板
createWatermarkTemplate() {
const width = 250 * this.scale,
height = 250 * this.scale;
const canvas = this.$refs.watermark;
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext("2d"); //返回一个用于在画布上绘图的环境
ctx.scale(this.scale, this.scale);
ctx.clearRect(0, 0, width, height); //绘制之前画布清除
ctx.rotate((-30 * Math.PI) / 180);
ctx.fillStyle = "rgba(100,100,100,0.1)";
ctx.font = "24px 黑体";
ctx.fillText(this.waterInfo.content, -10, 130);
ctx.font = "18px 黑体";
ctx.fillText(this.waterInfo.name + this.waterInfo.userAccount, -10, 160);
ctx.fillText(this.waterInfo.time, -10, 190);
ctx.rotate("30*Math.PI/180"); //坐标系还原
},
// 初始化pdf
init() {
pdfJS.getDocument(this.pdfUrl).promise.then((pdfDoc_)=> {
this.isLoading = false;
this.pdfDoc = pdfDoc_;
this.pageCount = this.pdfDoc.numPages;
this.pageNum = 1;
this.renderPage(this.pageNum);
});
},
// 渲染pdf
renderPage(num) {
this.pageRendering = true;
let canvas = this.$refs.myCanvas;
// Using promise to fetch the page
this.pdfDoc.getPage(num).then( (page)=> {
var viewport = page.getViewport(this.scale);
canvas.height = viewport.height;
canvas.width = viewport.width;
let ctx = canvas.getContext("2d")
var renderContext = {
canvasContext: ctx,
viewport: viewport,
};
var renderTask = page.render(renderContext);
renderTask.promise.then( ()=> {
ctx.fillStyle = ctx.createPattern(
this.$refs.watermark,
"repeat"
);
ctx.fillRect(0, 0, canvas.width, canvas.height);
this.pageRendering = false;
if (this.pageNumPending !== null) {
this.renderPage(this.pageNumPending);
this.pageNumPending = null;
}
});
});
},
// 放大
addscale() {
if (this.scale >= this.maxscale) {
return;
}
this.scale += 0.1;
this.queueRenderPage(this.pageNum);
},
// 缩小
minus() {
if (this.scale <= this.minscale) {
return;
}
this.scale -= 0.1;
this.queueRenderPage(this.pageNum);
},
// 上一页
prev() {
if (this.pageNum <= 1) {
return;
}
this.pageNum--;
this.queueRenderPage(this.pageNum);
},
// 下一页
next() {
if (this.pageNum >= this.pageCount) {
return;
}
this.pageNum++;
this.queueRenderPage(this.pageNum);
},
queueRenderPage(num) {
var number = Number(num);
if (this.pageRendering) {
this.pageNumPending = number;
} else {
this.renderPage(number);
}
},
},
};
</script>
<style scoped>
.wrap {
background-color: #fff !important;
display: flex;
flex-direction: column;
.pdf-container {
flex: 1;
overflow: auto;
text-align: center;
background-color: rgba(0,0,0,0.2);
.watermark {
display: none;
}
}
.pdf-control {
padding: 0px 16px;
height: 50px;
line-height: 50px;
background: rgba(103, 103, 103, 1);
display: flex;
justify-content: space-between;
font-size: 14px;
color: #fff;
img {
vertical-align: middle;
}
.pdf-control-page {
img {
width: 14px;
}
.page-number-container {
margin: 0px 7px;
.page-number-input {
width: 50px;
background-color: #363636;
border: none;
border-radius: 2px;
padding: 2px 4px;
box-sizing: border-box;
color: #fff;
}
}
}
.pdf-control-zoom {
img {
width: 24px;
}
.zoom-out {
margin-right: 20px;
}
}
}
}
</style>