/* eslint-disable prefer-destructuring */
// 不使用JQuery版的
import html2canvas from 'html2canvas';
import JsPDF from 'jspdf';
import _ from 'lodash';
/**
- @param ele 要生成 pdf 的DOM元素(容器)
- @param padfName PDF文件生成后的文件名字
- */
async function downloadPDF(ele, pdfName) {
const eleW = ele.offsetWidth; // 获得该容器的宽
const eleH = ele.offsetHeight; // 获得该容器的高
const eleOffsetTop = ele.offsetTop; // 获得该容器到文档顶部的距离
const eleOffsetLeft = ele.offsetLeft; // 获得该容器到文档最左的距离
const canvas = document.createElement('canvas');
let abs = 0;
const winIn = document.documentElement.clientWidth || document.body.clientWidth; // 获得当前可视窗口的宽度(不包含滚动条)
const winOut = window.innerWidth; // 获得当前窗口的宽度(包含滚动条)
if (winOut > winIn) {
abs = (winOut - winIn) / 2; // 获得滚动条宽度的一半
}
canvas.width = eleW * 2; // 将画布宽&&高放大两倍
canvas.height = eleH * 2;
const context = canvas.getContext('2d');
context.scale(2, 2);
context.translate(-eleOffsetLeft - abs, -eleOffsetTop);
// 缩放比例
const scale = 794 / eleW;
const handlerData = async el => {
const canvas = await html2canvas(el, {
dpi: 300,
useCORS: true,
});
const pageData = canvas.toDataURL('image/jpeg', 1.0);
const contentWidth = canvas.width;
const contentHeight = canvas.height;
const imgWidth = 595.28;
const imgHeight = (595.28 / contentWidth) * contentHeight;
return {
pageData,
imgWidth,
imgHeight,
};
};
// 元素分组
const handlerImage = e => {
if (_.isEmpty(e)) return [];
return _.map(e, el => {
if (el.offsetHeight * scale > 1123) {
return handlerImage(el.children);
}
return el;
});
};
const nodes = _.flattenDeep(handlerImage(ele.children));
// 元素分组
const data = []; // --------------
nodes.forEach((e, index) => {
if (!index) {
data.push([e]);
} else {
const h = _.sumBy(data[data.length - 1], 'offsetHeight') + e.offsetHeight;
if (h * scale > 1123) {
data.push([e]);
} else {
data[data.length - 1].push(e);
}
}
});
// 找到元素的offsetParent 为 main
const getoffsetTop = (e, h) => {
if (e.offsetParent.tagName === 'MAIN') {
return e.offsetTop + h;
}
return getoffsetTop(e.offsetParent, h);
};
const a = data.map(e => {
// --------------
if (e[0].offsetParent.tagName === 'MAIN') {
return e[0].offsetTop;
}
return getoffsetTop(e[0].offsetParent, e[0].offsetTop);
});
const image = a.map((e, index) => {
if (index === a.length - 1) return eleH - e - 24;
return Math.abs(a[index + 1] - e);
});
// imageData.pageData base64
const imageData = await handlerData(ele);
// create div
const div = document.createElement('div');
div.id = 'imgdiv';
const img = new Image();
img.src = imageData.pageData;
img.width = imageData.imgWidth;
img.height = imageData.imgHeight;
img.id = 'dowanloadImg';
div.appendChild(img);
document.getElementById('download').appendChild(div);
// 分块 画img
const canvasImage = (imgData, x, y, nHeight, index) => {
const canvasOther = document.createElement('canvas');
canvasOther.width = eleW;
canvasOther.height = nHeight;
canvasOther.id = id-${index}
;
canvasOther.type = 'canvasOther';
const ctx = canvasOther.getContext('2d');
ctx.drawImage(imgData, x, y, eleW, nHeight, 0, 0, eleW, nHeight); // 重绘
const data = canvasOther.toDataURL('image/jpeg', 1.0);
document.getElementById('imgdiv').appendChild(canvasOther);
const width = 595.28;
const height = (595.28 / eleW) * nHeight;
return {
data,
width,
height,
};
};
// imgData 整张图片信息
const imgData = document.getElementById('dowanloadImg');
imgData.onload = async () => {
// 根据image信息把imgData循环切割成多个图片
const imageArray = image.map(async (nHeight, index) => {
const data = await canvasImage(imgData, 0, _.sum(index ? _.chunk(image, index)[0] : [0]), nHeight, index);
return data;
});
// del node
document.getElementById('download').removeChild(document.getElementById('imgdiv'));
// img => pdf
const images = await Promise.all(imageArray);
const {
length,
} = images;
const pdf = new JsPDF('', 'pt', 'a4');
images.forEach((e, index) => {
const {
data,
width,
height,
} = e;
const h = index ? 10 : 0;
pdf.addImage(data, 'JPEG', -3, h, width, height);
if (index === length - 1) return;
pdf.addPage();
});
pdf.save(pdfName);
};
}
export default {
downloadPDF,
};
网友评论