pdfjs+canvas,实现给pdf添加水印并打印出来,原理就是利用pdfjs读取pdf文件,并且绘制到canvas中,同时,将canvas绘制上水印,效果如下:
代码如下,注意点我已经写到代码的注释当中去了:
<template>
<button v-show="!isPrinting" @click="print">打印</button>
<div id="printArea"></div>
</template>
<script setup>
import { ref, reactive, onMounted } from 'vue'
import * as PdfJs from 'pdfjs-dist'
const scale = 1.5
let pageSize = 0
const isPrinting = ref(false)
const init = () => {
// 这个workerSrc必须设置,否则会报错
// npm install pdfjs-dist 后,我将 node_modules/pdfjs-dist/build/pdf.worker.mjs 文件拷贝到了public目录,然后直接指定这个路径
PdfJs.GlobalWorkerOptions.workerSrc = '/pdf.worker.mjs';
// 加载pdf
var loadingTask = PdfJs.getDocument('/1.pdf');
loadingTask.promise.then((pdf) => {
// 读取pdf页码
pageSize = pdf.numPages
// 根据页码,创建出相应数量的canvas
for(let i=1; i<=pageSize; i++) {
const canvas = document.createElement('canvas')
canvas.id = 'canvas'+i
document.querySelector('#printArea').appendChild(canvas)
}
// 将pdf内容渲染到canvas
for(let i=1; i<=pageSize; i++) {
pdf.getPage(i).then((page) => {
var viewport = page.getViewport({scale: scale}); // 设置缩放比例
var canvas = document.getElementById('canvas'+i);
const ctx = canvas.getContext('2d')
const dpr = window.devicePixelRatio || 1
const bsr = ctx.webkitBackingStorePixelRatio ||
ctx.mozBackingStorePixelRatio ||
ctx.msBackingStorePixelRatio ||
ctx.oBackingStorePixelRatio ||
ctx.backingStorePixelRatio ||
1
const ratio = dpr / bsr
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) // 设置当pdf文件处于缩小或放大状态时,可以拖动
canvas.height = viewport.height; // 设置canvas高度为第一页的高度
page.render({canvasContext: ctx, viewport: viewport});
// 这里是添加水印,等读取完pdf再写入,偷懒,没有查文档,按理说应该写入render回调里,我试了下then,报错了,所以直接定时器解决了
setTimeout(() => {
drawWatermark(canvas, '我爱模板网')
}, 300*i)
})
}
});
}
const drawWatermark = (canvas, watermarkText) => {
const ctx = canvas.getContext('2d');
ctx.font = '20px bold Arial';
ctx.fillStyle = 'rgba(0, 0, 0, 0.3)';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
const margin = 100; // 水印文字间距
// 获取水印的宽高
const textWidth = ctx.measureText(watermarkText).width;
const textHeight = parseInt('watermarkFont'); // 获取字体的高度
// 水印平铺
for (let x = 0; x < canvas.width; x += textWidth + margin) {
for (let y = 0; y < canvas.height; y += margin) {
ctx.save();
ctx.translate(x, y);
ctx.rotate(-30 * Math.PI / 180); // 设置水印倾斜角度
ctx.fillText(watermarkText, 0, 0);
ctx.restore();
}
}
};
function print() {
isPrinting.value = true
setTimeout(() => {
window.print()
isPrinting.value = false
}, 1000)
}
onMounted(() => {
init()
})
</script>
<style>
#printArea canvas{
display: block;
}
</style>