背景介紹:
工作中產(chǎn)品提出需求“截圖下載 并 要附加水印功能”
首先將需求分為大致幾個步驟完成:
- 實(shí)現(xiàn)截屏
- 下載PDF
- 添加水印
截屏
關(guān)于截屏工具首先考慮到html2canvas:
html2canvas
const element = document.querySelector(`#${id}`);
const { scrollHeight, scrollWidth, offsetHeight, height } = element;
const opts = {
scale: 3, // 縮放比例,提高生成圖片清晰度
useCORS: true, // 允許加載跨域的圖片
allowTaint: false, // 允許圖片跨域尝江,和 useCORS 二者不可共同使用
tainttest: true, // 檢測每張圖片都已經(jīng)加載完成
logging: true, // 日志開關(guān)八匠,發(fā)布的時候記得改成 false
height: offsetHeight,
};
html2canvas(element, opts).then((canvas) => {
// 獲取到所id為‘id’的元素canvas截圖
})
下載PDF
關(guān)于PDF想到的工具是jsPDF:
jsPDF
將canvas轉(zhuǎn)成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都可以實(shí)現(xiàn),兩者我選擇了用pdf實(shí)現(xiàn):
先附代碼:
const addWatermark = (pdf, watermarkText) => {
// 獲取PDF頁數(shù)堪置,給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是可以根據(jù)水印的大小調(diào)整的 可以優(yōu)化為單水印的長和寬
let xCount = pdfW / 250;
let yCount = pdfH / 250;
// 下面的for循環(huán)的作用是在頁面上鋪滿水印
for (let y = 0; y < yCount; y++) {
let yLocation = y * 250;
for (let x = 0; x < xCount; x++) {
let xLocation = x * 250;
pdf.saveGraphicsState() // 保存圖形狀態(tài)
pdf.setFontSize(40); // 設(shè)置水印字體大小
pdf.setTextColor(200); // 設(shè)置水印顏色
pdf.setGState(pdf.GState({ opacity: 0.3 })) // 設(shè)置透明度為0.3
// 這里的SIMHEI是字體包 解決jsPDF 無法使用中文問題
pdf.setFont('SIMHEI');
pdf.text(watermarkText, xLocation, yLocation, { align: 'center', angle: -45});
pdf.restoreGraphicsState()
}
}
return pdf;
}
添加水印時遇到的問題:
- 添加水印如何鋪滿
上面方法中鋪滿問題用for循環(huán)解決了一下,感覺這個工具應(yīng)該有自己封裝的鋪滿方法,找了很多jsPDF的相關(guān)文章都沒有找到合適的剖毯,于是用for循環(huán)設(shè)置x、y坐標(biāo)解決了這個問題教馆。 - 水印無法使用中文
找到的資料解釋是jsPDF這玩意兒是老外做的速兔,做的時候就沒有考慮中文的情況,解決方案是在工程內(nèi)添加XXXX.ttf的字體包活玲,將格式為ttf的文件用轉(zhuǎn)換工具(https://rawgit.com/MrRio/jsPDF/master/fontconverter/fontconverter.html)轉(zhuǎn)成jsPDF可以用的js文件涣狗,導(dǎo)入到工程內(nèi)用,在文件內(nèi)引入舒憾,用jsPDF里的setFont方法加載一下字體包镀钓。
相關(guān)代碼:
import "@/assets/js/SIMHEI-normal";
pdf.setFont('SIMHEI');