背景介绍:
工作中产品提出需求“截图下载 并 要附加水印功能”
首先将需求分为大致几个步骤完成:
- 实现截屏
- 下载PDF
- 添加水印
截屏
关于截屏工具首先考虑到html2canvas:
html2canvas
const element = document.querySelector(`#${id}`);
const { scrollHeight, scrollWidth, offsetHeight, height } = element;
const opts = {
scale: 3, // 缩放比例,提高生成图片清晰度
useCORS: true, // 允许加载跨域的图片
allowTaint: false, // 允许图片跨域,和 useCORS 二者不可共同使用
tainttest: true, // 检测每张图片都已经加载完成
logging: true, // 日志开关,发布的时候记得改成 false
height: offsetHeight,
};
html2canvas(element, opts).then((canvas) => {
// 获取到所id为‘id’的元素canvas截图
})
下载PDF
关于PDF想到的工具是jsPDF:
jsPDF
将canvas转成PDF并下载
let contentWidth = canvas.width
let contentHeight = canvas.height
let pageHeight = contentWidth / 592.28 * 841.89 - 40
let leftHeight = contentHeight
let position = 20
let imgWidth = 570
let imgHeight = 592.28 / contentWidth * contentHeight
let pageData = canvas.toDataURL('image/jpeg', 1.0)
let PDF = new JsPDF('', 'pt', 'a4')
if (leftHeight < pageHeight) {
PDF.addImage(pageData, 'JPEG', 14, 20, imgWidth, imgHeight)
// addWatermark(PDF, 'TEST');
} else {
while (leftHeight > 0) {
PDF.addImage(pageData, 'JPEG', 14, position, imgWidth, imgHeight)
leftHeight -= pageHeight
position -= 841.89
if (leftHeight > 0) {
PDF.addPage()
}
}
}
// 添加水印(文章下面会说到这个方法)
PDF = addWatermark(PDF, watermarkText);
PDF.save(title + '.pdf');
添加水印
但是添加水印功能貌似用canvas和PDF都可以实现,两者我选择了用pdf实现:
先附代码:
const addWatermark = (pdf, watermarkText) => {
// 获取PDF页数,给PDF每一页添加水印
var totalPages = pdf.internal.getNumberOfPages();
for (let i = 1; i <= totalPages; i++) {
pdf.setPage(i);
addWatermarkFill(pdf, watermarkText);
}
return pdf;
}
const addWatermarkFill = (pdf, watermarkText) => {
let pdfW = pdf.internal.pageSize.getWidth();
let pdfH = pdf.internal.pageSize.getHeight();
// 250是可以根据水印的大小调整的 可以优化为单水印的长和宽
let xCount = pdfW / 250;
let yCount = pdfH / 250;
// 下面的for循环的作用是在页面上铺满水印
for (let y = 0; y < yCount; y++) {
let yLocation = y * 250;
for (let x = 0; x < xCount; x++) {
let xLocation = x * 250;
pdf.saveGraphicsState() // 保存图形状态
pdf.setFontSize(40); // 设置水印字体大小
pdf.setTextColor(200); // 设置水印颜色
pdf.setGState(pdf.GState({ opacity: 0.3 })) // 设置透明度为0.3
// 这里的SIMHEI是字体包 解决jsPDF 无法使用中文问题
pdf.setFont('SIMHEI');
pdf.text(watermarkText, xLocation, yLocation, { align: 'center', angle: -45});
pdf.restoreGraphicsState()
}
}
return pdf;
}
添加水印时遇到的问题:
- 添加水印如何铺满
上面方法中铺满问题用for循环解决了一下,感觉这个工具应该有自己封装的铺满方法,找了很多jsPDF的相关文章都没有找到合适的,于是用for循环设置x、y坐标解决了这个问题。 - 水印无法使用中文
找到的资料解释是jsPDF这玩意儿是老外做的,做的时候就没有考虑中文的情况,解决方案是在工程内添加XXXX.ttf的字体包,将格式为ttf的文件用转换工具(https://rawgit.com/MrRio/jsPDF/master/fontconverter/fontconverter.html)转成jsPDF可以用的js文件,导入到工程内用,在文件内引入,用jsPDF里的setFont方法加载一下字体包。
相关代码:
import "@/assets/js/SIMHEI-normal";
pdf.setFont('SIMHEI');
网友评论