实现效果:

实现原理:将PDF文件一页一页的渲染在画布上面,然后将水印文字也渲染在画布上面。

在网上也找了很多教程,自己试了一下,或多或少有点问题,最后结合了一下,做了些修改实现了。

使用到的插件 pdfjs-dist,这个版本需要注意,太低或太高版本都不行。我最后选的是2.6.347,成功运行了。

package.json配置文件:

{"name": "pdf","version": "0.1.0","private": true,"scripts": {"serve": "vue-cli-service serve","build": "vue-cli-service build","lint": "vue-cli-service lint"},"dependencies": {"core-js": "^3.8.3","pdfjs-dist": "^2.6.347","vue": "^2.6.14"},"devDependencies": {"@babel/core": "^7.12.16","@babel/eslint-parser": "^7.12.16","@vue/cli-plugin-babel": "~5.0.0","@vue/cli-plugin-eslint": "~5.0.0","@vue/cli-service": "~5.0.0","eslint": "^7.32.0","eslint-plugin-vue": "^8.0.3","vue-template-compiler": "^2.6.14"},"eslintConfig": {"root": true,"env": {"node": true},"extends": ["plugin:vue/essential","eslint:recommended"],"parserOptions": {"parser": "@babel/eslint-parser"},"rules": {}},"browserslist": ["> 1%","last 2 versions","not dead"]
}

vue代码:


<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,});console.log(this.pdfData);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 = "14px Vedana";ctx.fillStyle = "rgba(0, 0, 0, 0.8)";ctx.textAlign = "left";ctx.textBaseline = "middle";ctx.fillText(this.watermark, 50, 50);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: 600px;height: 700px;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>

前端vue实现给pdf添加水印相关推荐

  1. 前端vue项目(使用pdf.js) pdf展示及pdf工具栏放大缩小功能实现

    前端vue项目(使用pdf.js) pdf展示及pdf工具栏放大缩小功能实现 1.vue项目pdf展示 2.pdf工具栏放大缩小功能 文章目录 前端vue项目(使用pdf.js) pdf展示及pdf工 ...

  2. 前端vue实现pdf文件的在线预览

    3.前端vue实现pdf文件的在线预览 我是通过 <iframe> 标签就可以满足我工作的 pdf预览需求 如果<iframe> 无法满足需求 , 可以使用pdf.js这个插件 ...

  3. vue 前端png转pdf_Vue前端HTML保存为PDF的两种常用方式 「干货分享」

    Vue前端HTML保存为PDF常用方式有两种.使用html2Canvas和JsPDF库,转化为图片后保存PDF. 调用浏览器window.print(),然后手动保存为PDF. 第一种 优点没有预览点 ...

  4. PDF.js + Vue 浏览器以只读方式打开PDF,后台返回文件流,前端实现预览pdf

    如果你想光前端完成 office(xls,doc,ppt) 文件的预览,只能提供你这些库来使用 PDF http://mozilla.github.com/pdf.js/ XLS https://gi ...

  5. SpringBoot+Vue+mybatis生成pdf文件(表头跟页码,适应上传linux服务器后的操作)

    SpringBoot+Vue+mybatis生成pdf文件(表头跟页码,适应上传linux服务器后的操作) 为什么使用后端去生成 说明 依赖 后端目录 控制器代码 模板代码 前端代碼 最終效果 为什么 ...

  6. 文件下载:从服务器上下载,自动给下载的PDF添加水印(一)

    javaweb 项目,前端页面点击下载指定文件,后端执行过程. 给文件添加水印方法的代码,放在下一篇:<给指定的PDF添加水印(二)> 从服务器文件下载,自动添加水印 一.从服务器文件下载 ...

  7. vue 页面转pdf 并下载

    最近需要做一个下载vue页面为pdf格式的功能,网上方案有很多,也尝试了其他方案,最终采用的方案 流程就是点击下载报告按钮,则请求后端一个接口,例如接口地址为example.cn/file/downl ...

  8. php vue pdf预览,Vue项目使用pdf.js

    前段时间有个支持在线学习功能的项目,有需要在线预览pdf格式课件的功能,我就想在线预览pdf多简单,因为大部分浏览器都支持打开pdf文件,所以直接放个iframe然后src是pdf文件的地址不就行了吗 ...

  9. 常见的前端vue面试题

    常见的前端vue面试题 1.请讲述下VUE的MVVM的理解? MVVM 是 Model-View-ViewModel的缩写,即将数据模型与数据表现层通过数据驱动进行分离,从而只需要关系数据模型的开发, ...

最新文章

  1. linux进程故障如何修复,33.Linux开机过程及启动故障修复
  2. mysql 线程缓存_浅析MySQL内存的使用说明(全局缓存+线程缓存)
  3. 【Android】SlidingTabs
  4. 计算机组成要素二:布尔运算:ALU算术运算器
  5. 红衣大炮的飞秋实现原理
  6. ubuntu facebook/C3D视频特征提取
  7. 仓库体积过大,如何减小?
  8. 计算机主机光驱弹不出来怎么办,光驱弹不出来怎么办,教你win10光驱弹不出来的应对办法...
  9. php股票指标,最精准的换手率选股法股票指标 通达信公式(附图)
  10. ssb的有效性最好_在AM、DSB、SSB、FM系统中,有效性最好的是AM
  11. 【问题解决】panic: qtls.ClientHelloInfo doesn‘t match goroutine 1 [running]: github.com/marten-seemann/qt
  12. 无线网ppp服务器连接失败,关于无线上网PPP拨号问题
  13. Ubuntu18.04安装NVIDIA 显卡驱动(GTX 1060)
  14. 【蓝桥杯经典数学题】杨辉三角形
  15. vue+vant仿微信聊天画面做了个点击按钮出现土味情话的界面
  16. NR-PRACH:接入场景和接入流程
  17. vmware和hyper-v的一个坑
  18. 浅谈AI模型的可解释性、安全性与正义性(中)
  19. IT业的《大腕》经典台词
  20. 从n个不同元素中取出m个元素排列组合

热门文章

  1. ok6410linux开发环境搭建,飞凌嵌入式知识汇021期:OK6410裸机程序之开始模板(Linux环境)...
  2. oculusquest2第三方游戏应用下载安装方法 (附百度云资源)安装教程VR一体机分享 Quest2游戏推荐安装教程2021
  3. 编译原理:素短语、短语、直接短语、句柄的基本概念
  4. python少儿趣味编程 pdf-趣学python编程
  5. Redis 几种数据类型的详细介绍
  6. 简单上手ECharts
  7. 【Vant Weapp】van-cell 单元格
  8. 电影配音怎么做?短视频解说配音小技巧,其实很简单
  9. OBS插件开发以及OBS插件的选择(obs直播插件)研究思路
  10. Unity实现第三人称角色转向摄像机朝向的方向