当前位置: 首页 > news >正文

vue使用pdf-dist实现pdf预览以及水印

vue使用pdf-dist实现pdf预览以及水印

一.使用pdf-dist插件将PDF文件转换为一张张canvas图片

npm install pdf-dist

二.页面引入插件

const pdfJS = require("pdfjs-dist");
pdfJS.GlobalWorkerOptions.workerSrc = require("pdfjs-dist/build/pdf.worker.entry");

三.渲染PDF

// 根据页码渲染相应的PDF
renderPage(num) {this.renderingPage = true;this.pdfData.promise.then((pdf) => {this.pdfPageNumber = pdf.numPages;pdf.getPage(num).then((page) => {// 获取DOM中为预览PDF准备好的canvasDOM对象let canvas = this.$refs.myCanvas;let ctx = canvas.getContext("2d");// 获取页面比率let ratio = this._getRatio(ctx);// 根据页面宽度和视口宽度的比率就是内容区的放大比率let dialogWidth = this.$refs["canvasCont"].offsetWidth;let pageWidth = page.view[2] * ratio;let scale = dialogWidth / pageWidth;let viewport = page.getViewport({ scale });// 记录内容区宽高,后期添加水印时需要this.width = viewport.width * ratio;this.height = viewport.height * ratio;canvas.width = this.width;canvas.height = this.height;// 缩放比率ctx.setTransform(ratio, 0, 0, ratio, 0, 0);let renderContext = {canvasContext: ctx,viewport: viewport,};page.render(renderContext).promise.then(() => {this.renderingPage = false;this.pageNo = num;// 添加水印this._renderWatermark();});});});
},
// 计算角度
_getRatio(ctx) {let dpr = window.devicePixelRatio || 1;let bsr =ctx.webkitBackingStorePixelRatio ||ctx.mozBackingStorePixelRatio ||ctx.msBackingStorePixelRatio ||ctx.oBackingStorePixelRatio ||ctx.backingStorePixelRatio ||1;return dpr / bsr;
},

四.添加水印

// 生成水印图片
_initWatermark() {let canvas = document.createElement("canvas");canvas.width = 200;canvas.height = 200;let ctx = canvas.getContext("2d");ctx.rotate((-18 * Math.PI) / 180);ctx.font = "10px Vedana";ctx.fillStyle = "rgba(0, 0, 0, 0.8)";ctx.textAlign = "left";ctx.textBaseline = "middle";ctx.fillText(this.watermark, 10, 100);return canvas;
},

五.完整代码(带翻页)

<template><div class="main-container"><input type="file" ref="fielinput" @change="uploadFile" /><div ref="canvasCont" class="canvas-container"><canvas ref="myCanvas" class="pdf-container"></canvas></div><div class="pagination-wrapper"><button @click="clickPre">上一页</button><span>{{ pageNo }} / {{ pdfPageNumber }}</span><button @click="clickNext">下一页</button></div></div>
</template><script>
const pdfJS = require("pdfjs-dist");pdfJS.GlobalWorkerOptions.workerSrc = require("pdfjs-dist/build/pdf.worker.entry");
export default {props: {watermark: {type: String,default: "水印文字水印文字水印文字",},},mounted() {},data() {return {pageNo: null,pdfPageNumber: null,renderingPage: false,pdfData: null, // PDF的base64scale: 1, // 缩放值width: "",height: "",};},methods: {uploadFile() {let inputDom = this.$refs.fielinput;let file = inputDom.files[0];let reader = new FileReader();reader.readAsDataURL(file);reader.onload = () => {let data = atob(reader.result.substring(reader.result.indexOf(",") + 1));this.loadPdfData(data);};},loadPdfData(data) {// 引入pdf.js的字体let CMAP_URL = "https://unpkg.com/pdfjs-dist@2.0.943/cmaps/";//读取base64的pdf流文件this.pdfData = pdfJS.getDocument({data: data, // PDF base64编码cMapUrl: CMAP_URL,cMapPacked: true,});this.renderPage(1);},// 根据页码渲染相应的PDFrenderPage(num) {this.renderingPage = true;this.pdfData.promise.then((pdf) => {this.pdfPageNumber = pdf.numPages;pdf.getPage(num).then((page) => {// 获取DOM中为预览PDF准备好的canvasDOM对象let canvas = this.$refs.myCanvas;let ctx = canvas.getContext("2d");// 获取页面比率let ratio = this._getRatio(ctx);// 根据页面宽度和视口宽度的比率就是内容区的放大比率let dialogWidth = this.$refs["canvasCont"].offsetWidth;let pageWidth = page.view[2] * ratio;let scale = dialogWidth / pageWidth;let viewport = page.getViewport({ scale });// 记录内容区宽高,后期添加水印时需要this.width = viewport.width * ratio;this.height = viewport.height * ratio;canvas.width = this.width;canvas.height = this.height;// 缩放比率ctx.setTransform(ratio, 0, 0, ratio, 0, 0);let renderContext = {canvasContext: ctx,viewport: viewport,};page.render(renderContext).promise.then(() => {this.renderingPage = false;this.pageNo = num;// 添加水印this._renderWatermark();});});});},// 计算角度_getRatio(ctx) {let dpr = window.devicePixelRatio || 1;let bsr =ctx.webkitBackingStorePixelRatio ||ctx.mozBackingStorePixelRatio ||ctx.msBackingStorePixelRatio ||ctx.oBackingStorePixelRatio ||ctx.backingStorePixelRatio ||1;return dpr / bsr;},// 在画布上渲染水印_renderWatermark() {let canvas = this.$refs.myCanvas;let ctx = canvas.getContext("2d");// 平铺水印let pattern = ctx.createPattern(this._initWatermark(), "repeat");ctx.rect(0, 0, this.width, this.height);ctx.fillStyle = pattern;ctx.fill();},// 生成水印图片_initWatermark() {let canvas = document.createElement("canvas");canvas.width = 200;canvas.height = 200;let ctx = canvas.getContext("2d");ctx.rotate((-18 * Math.PI) / 180);ctx.font = "10px Vedana";ctx.fillStyle = "rgba(0, 0, 0, 0.8)";ctx.textAlign = "left";ctx.textBaseline = "middle";ctx.fillText(this.watermark, 10, 100);return canvas;},clickPre() {if (!this.renderingPage && this.pageNo && this.pageNo > 1) {this.renderPage(this.pageNo - 1);}},clickNext() {if (!this.renderingPage &&this.pdfPageNumber &&this.pageNo &&this.pageNo < this.pdfPageNumber) {this.renderPage(this.pageNo + 1);}},},
};
</script><style scoped>
.main-container {display: flex;flex-direction: column;align-items: center;
}
.canvas-container {width: 100%;height: 100%;border: 1px dashed black;position: relative;display: flex;justify-content: center;
}
.pdf-container {width: 100%;height: 100%;
}.pagination-wrapper {display: flex;justify-content: center;align-items: center;
}
</style>

六.完整代码(滑动)

<template><div class="main-container"><input type="file" ref="fielinput" @change="uploadFile" /><div ref="canvasCont" class="canvas-container"><canvas v-for="pageIndex in pdfPageNumber" :ref="`myCanvas${pageIndex}`" :key="pageIndex" class="pdf-container"></canvas></div></div>
</template><script>
const pdfJS = require("pdfjs-dist");pdfJS.GlobalWorkerOptions.workerSrc = require("pdfjs-dist/build/pdf.worker.entry");
export default {props: {watermark: {type: String,default: "水印文字水印文字水印文字",},},mounted() {},data() {return {pageNo: null,pdfPageNumber: null,renderingPage: false,pdfData: null, // PDF的base64scale: 1, // 缩放值width: "",height: "",};},methods: {uploadFile() {let inputDom = this.$refs.fielinput;let file = inputDom.files[0];let reader = new FileReader();reader.readAsDataURL(file);reader.onload = () => {let data = atob(reader.result.substring(reader.result.indexOf(",") + 1));this.loadPdfData(data);};},loadPdfData(data) {// 引入pdf.js的字体let CMAP_URL = "https://unpkg.com/pdfjs-dist@2.0.943/cmaps/";//读取base64的pdf流文件this.pdfData = pdfJS.getDocument({data: data, // PDF base64编码cMapUrl: CMAP_URL,cMapPacked: true,});this.renderPage(1);},// 根据页码渲染相应的PDFrenderPage(num) {this.renderingPage = true;this.pdfData.promise.then((pdf) => {this.pdfPageNumber = pdf.numPages;pdf.getPage(num).then((page) => {// 获取DOM中为预览PDF准备好的canvasDOM对象let canvas = this.$refs[`myCanvas${num}`][0];let ctx = canvas.getContext("2d");// 获取页面比率let ratio = this._getRatio(ctx);// 根据页面宽度和视口宽度的比率就是内容区的放大比率let dialogWidth = this.$refs["canvasCont"].offsetWidth;let pageWidth = page.view[2] * ratio;let scale = dialogWidth / pageWidth;let viewport = page.getViewport({ scale });// 记录内容区宽高,后期添加水印时需要this.width = viewport.width * ratio;this.height = viewport.height * ratio;canvas.width = this.width;canvas.height = this.height;// 缩放比率ctx.setTransform(ratio, 0, 0, ratio, 0, 0);let renderContext = {canvasContext: ctx,viewport: viewport,};page.render(renderContext).promise.then(() => {this.renderingPage = false;this.pageNo = num;// 添加水印this._renderWatermark(num);if(num < this.pdfPageNumber){this.renderPage(num+1)}});});});},// 计算角度_getRatio(ctx) {let dpr = window.devicePixelRatio || 1;let bsr =ctx.webkitBackingStorePixelRatio ||ctx.mozBackingStorePixelRatio ||ctx.msBackingStorePixelRatio ||ctx.oBackingStorePixelRatio ||ctx.backingStorePixelRatio ||1;return dpr / bsr;},// 在画布上渲染水印_renderWatermark(num) {let canvas = this.$refs[`myCanvas${num}`][0];let ctx = canvas.getContext("2d");// 平铺水印let pattern = ctx.createPattern(this._initWatermark(), "repeat");ctx.rect(0, 0, this.width, this.height);ctx.fillStyle = pattern;ctx.fill();},// 生成水印图片_initWatermark() {let canvas = document.createElement("canvas");canvas.width = 200;canvas.height = 200;let ctx = canvas.getContext("2d");ctx.rotate((-18 * Math.PI) / 180);ctx.font = "10px Vedana";ctx.fillStyle = "rgba(0, 0, 0, 0.8)";ctx.textAlign = "left";ctx.textBaseline = "middle";ctx.fillText(this.watermark, 10, 100);return canvas;},},
};
</script><style scoped>
.main-container {display: flex;flex-direction: column;align-items: center;
}
.canvas-container {width: 100%;height: 100%;border: 1px dashed black;position: relative;/* display: flex; *//* justify-content: center; */
}
.pdf-container {width: 100%;height: 100%;
}
</style>

七.下载源码地址

下载地址

八.效果展示

在这里插入图片描述

http://www.lryc.cn/news/197220.html

相关文章:

  • [Python进阶] 操纵键盘:Pynput
  • 购药不烦恼:线上购药小程序的快捷方式
  • 10.17课上(七段显示器,递归异或与电路)
  • maven-plugin-shade 详解
  • cocosCreator 之 3.x使用NodePool对象池和封装
  • 三、RestClient操作索引库与文档
  • Hadoop3教程(五):NameNode和SecondaryNameNode
  • 腾讯云我的世界mc服务器多少钱一年?
  • modelsim实现二选一以及D触发器并仿真
  • 直线导轨在喷涂行业中的应用场景
  • 纯css+js自制下拉框
  • uniapp在App端如何动态修改原生导航栏?
  • Linux:CPUPower管理器 --- cpufreq解析
  • 【嵌入式开发问答】不是普通的嵌入式八股
  • 面试题-springboot篇-SpringBoot的注解
  • BaiChuan2保姆级微调范例
  • postgresql参数优化
  • 【极速发表】2-4区SCI (含CCF),平均录用周期仅2个月,最快11天见刊!
  • Git 提交规范
  • [Python进阶] 操纵鼠标:PyAutoGUI
  • JavaScript querySelector
  • Selenium自动化测试
  • Lua调用C#类
  • “react“: “^16.14.0“,打开弹窗数据发生变化
  • MySQL数据库varchar字段求和出现精度丢失
  • C++入门 第二篇( 引用、内联函数、auto关键字、指针空值nullptr)
  • 2023年煤气证模拟考试题库及煤气理论考试试题
  • 嵌入式面试经典30问
  • C++ 八股文: 构造函数
  • 自动切割短视频的软件推荐,一键生成1000条短视频,支持六大主流平台矩阵分发,快来免费试用