共计 4074 个字符,预计需要花费 11 分钟才能阅读完成。
var pdfContent = document.getElementById("pdfDiv"); | |
var width = pdfContent.offsetWidth; // 获取 dom 宽度 | |
var height = pdfContent.offsetHeight; // 获取 dom 高度 | |
var canvas = document.createElement("canvas"); // 创立一个 canvas 节点 | |
var scale = 3; // 定义任意放大倍数 反对小数,越大越清晰 | |
var offsetTop = pdfContent.offsetTop; | |
var rect = pdfContent.getBoundingClientRect();// 获取元素绝对于视察的偏移量 | |
canvas.width = width * scale; // 定义 canvas 宽度 * 缩放 | |
canvas.height = (height + offsetTop) * scale; // 定义 canvas(高度 + 偏移量)* 缩放 | |
var content = canvas.getContext("2d"); | |
content.scale(scale, scale); // 获取 context, 设置 scale | |
content.translate(-rect.left, -rect.top);// 设置 context 地位,值为绝对于视窗的偏移量负值,让图片复位 | |
// content.translate(-rect.left, -rect.top + 135);// 设置 context 地位,值为绝对于视窗的偏移量负值,让图片复位 | |
var opts = { | |
background: "#fff", | |
scale: scale, // 增加的 scale 参数 | |
canvas: canvas, // 自定义 canvas | |
// logging: true, // 日志开关,便于查看 html2canvas 的外部执行流程 | |
width: width, //dom 原始宽度 | |
height: height, | |
useCORS: true, //【重要】开启跨域配置 | |
allowTaint: true, | |
taintTest: false, | |
// scrollY: 0, | |
// scrollX: 0 | |
}; | |
html2canvas(pdfContent,opts).then(function (canvas) {downloadCanvasWithMargin(canvas); | |
}) | |
//----------------------- | |
function downloadCanvasWithMargin(canvas){ | |
// 敞开锯齿 | |
var context = canvas.getContext('2d'); | |
context.mozImageSmoothingEnabled = false; | |
context.webkitImageSmoothingEnabled = false; | |
context.msImageSmoothingEnabled = false; | |
context.imageSmoothingEnabled = false; | |
let contentWidth = canvas.width; | |
let contentHeight = canvas.height; | |
// 一页 pdf 显示 html 页面生成的 canvas 高度; | |
let pageHeight = contentWidth / 595.28 * 841.89; | |
// 未生成 pdf 的 html 页面高度 | |
let leftHeight = contentHeight; | |
let cutStartHeight = 0; | |
let canvasArr = []; | |
if(leftHeight > pageHeight) {while (leftHeight > 0) {// 复制出 (0, cutStartHeight) 开始,contentWidth 宽和 pageHeight 高的图片 | |
let cutImage = context.getImageData(0, cutStartHeight, contentWidth, pageHeight); | |
// 以通明背景开始,抛弃 | |
if(cutImage.data[0] === 0 ){ | |
leftHeight -= pageHeight; | |
cutStartHeight += pageHeight; | |
continue; | |
} | |
// 从图像底部开始校验色彩,直到验证到已红色结尾才开始切图像 | |
let moveUpPx = 0; // 上移 px 数 | |
let totalLength = cutImage.data.length; | |
let lineLength = 4 * contentWidth * 1; // 一行的 data 容量 | |
let leftLength = totalLength - lineLength; | |
let rightLength = totalLength; | |
let circle = 0; // 循环次数 | |
let pointRatio = 0.98; // 一行非给定色彩的占比系数 | |
let pointRatioNum = contentWidth * pointRatio; | |
while(circle === moveUpPx){ | |
circle ++; | |
let ignorePoint = 0; | |
for(let i = leftLength; i< rightLength ; i+=4){if(cutImage.data[i] === 255 || cutImage.data[i] === 251){if(cutImage.data[i] === cutImage.data[i+1] && cutImage.data[i] === cutImage.data[i+2]){ignorePoint++;} | |
} | |
} | |
if(ignorePoint < pointRatioNum){ | |
leftLength -= lineLength; | |
rightLength -= lineLength; | |
moveUpPx ++; | |
} | |
} | |
if(moveUpPx > 0){cutImage = context.getImageData(0, cutStartHeight, contentWidth, pageHeight - moveUpPx); | |
} | |
leftHeight -= pageHeight + moveUpPx; | |
cutStartHeight += pageHeight - moveUpPx; | |
// 创立新图片 | |
let nCanvas = document.createElement("canvas"); // 创立一个 canvas 节点 | |
nCanvas.width = canvas.width; | |
nCanvas.height = pageHeight - moveUpPx; | |
let nContext = nCanvas.getContext("2d"); | |
nContext.mozImageSmoothingEnabled = false; | |
nContext.webkitImageSmoothingEnabled = false; | |
nContext.msImageSmoothingEnabled = false; | |
nContext.imageSmoothingEnabled = false; | |
nContext.putImageData(cutImage, 0, 0) | |
canvasArr.push(nCanvas); | |
} | |
}else{canvasArr.push(canvas); | |
} | |
// 解决尾页图片通明背景 | |
let lastCanvas = canvasArr[canvasArr.length - 1]; | |
let ctx = lastCanvas.getContext("2d"); | |
// 将 canvas 的通明背景设置成红色 -- 解决 translate 后便彩色背景的问题 | |
let imageData = ctx.getImageData(0, 0, lastCanvas.width, lastCanvas.height); | |
for(var i = 0; i < imageData.data.length; i += 4) { | |
// 当该像素是通明的,则设置成红色 | |
if(imageData.data[i + 3] === 0) {imageData.data[i] = 255; | |
imageData.data[i + 1] = 255; | |
imageData.data[i + 2] = 255; | |
imageData.data[i + 3] = 255; | |
} | |
} | |
ctx.putImageData(imageData, 0, 0); | |
var pdf = new jsPDF('','pt','a4'); | |
let leftMargin = 20; | |
let topMargin = 20; | |
let a4Width = 595.28; | |
let a4Height = 841.89; | |
let imgWidth = a4Width - leftMargin * 2; | |
let imgHeight = a4Height - 2 * topMargin; | |
for(let i =0; i < canvasArr.length; i++){let curCanvas = canvasArr[i]; | |
let pageData = curCanvas.toDataURL('image/jpeg', 1.0); | |
// 小于切分的高度,要换算比例高 | |
if(curCanvas.height < pageHeight){ | |
let ratioHeight = imgWidth / curCanvas.width * curCanvas.height; | |
pdf.addImage(pageData, 'JPEG', leftMargin, topMargin, imgWidth, ratioHeight); | |
}else{pdf.addImage(pageData, 'JPEG', leftMargin, topMargin, imgWidth, imgHeight); | |
} | |
if(i < (canvasArr.length-1)){pdf.addPage(); | |
} | |
} | |
let date = new Date(); | |
let year = date.getFullYear(); | |
let month = date.getMonth() + 1; | |
let day = date.getDate(); | |
let milliSeconds = date.getMilliseconds(); | |
pdf.save(year + month + day + milliSeconds +'.pdf'); | |
} |
正文完
发表至: javascript
2021-05-13