项目需求:有一个网页大概60000px的高度,现在需要导出为PDF
index.vue
<template>
<div class="ctn">
<div class="pdf-ctn">
<div class="pdf-panel" >
<div class="pdf-inside-panel" id="myList">
<div v-for="(item, index) in 3000" :key="index" style="height: 20px">
{{index}}---我是测试我是测试我是测试我是测试我是测试我是测试我是测试我是测试我是测试我是测试我是测试我是测试我是测试我是测试我是测试我的高度{{
(index+1)*20
}}
</div>
</div>
</div>
<div
class="pdf-header"
style="
font-weight: bold;
padding: 15px 8px;
width: 100%;
border-bottom: 1px solid rgba(0, 0, 0, 0.85);
color: rgba(0, 0, 0, 0.85);
position: fixed;
top: -100vh;
"
>
页头
</div>
<div
class="pdf-footer"
style="
font-weight: bold;
padding: 15px 8px;
width: 100%;
border-top: 1px solid rgba(0, 0, 0, 0.85);
position: fixed;
top: -100vh;
"
>
<div
style="
display: flex;
justify-content: center;
align-items: center;
padding-top: 5px;
"
>
我是页尾
</div>
<div
style="
display: flex;
justify-content: center;
align-items: center;
margin-top: 20px;
"
>
第
<div class="pdf-footer-page"></div>
页 / 第
<div class="pdf-footer-page-count"></div>
页
</div>
</div>
</div>
<div>
<a-button
style="top: 50px; left: 1450px; position: fixed"
@click="handleOutput"
>
测试导出
</a-button>
</div>
</div>
</template>
<script>
import { message } from "ant-design-vue";
import { outCanvas } from "../scroll";
export default {
name: "HelloWorld",
props: {
msg: String,
},
methods: {
async handleOutput() {
const element = document.querySelector("#myList");
const header = document.querySelector(".pdf-header");
const footer = document.querySelector(".pdf-footer");
await outCanvas(element);
let endTime = new Date().getTime();
let timeElapsed = endTime - startTime; // 获取时间差(毫秒)
console.log(`函数运行时间: ${timeElapsed} 毫秒`);
} catch (error) {
console.log(error)
message.error(
typeof error === "string" ? error : JSON.stringify(error)
);
}
},
}
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="less">
.ctn {
.pdf-ctn {
width: 1300px;
.pdf-panel {
position: relative;
}
}
}
</style>
JS
import html2canvas from 'html2canvas';
import jsPDF from 'jspdf';
import { message } from 'ant-design-vue';
// jsPDFs实例
let pdf = new jsPDF({
unit: 'pt',
format: 'a4',
orientation: 'p',
// format: [550, 550]
});
// 对图片进行等比缩放
function resizeImage(imgWidth, imgHeight, maxWidth = 590) {
// 计算当前图片的宽高比
const ratio = imgWidth / imgHeight;
// 如果最大宽度小于当前宽度,则按最大宽度进行缩放
if (imgWidth > maxWidth) {
return {
newWidth: maxWidth,
newHeight: maxWidth / ratio
};
} else { // 否则,图片本身就在允许的最大宽度内,不需要缩放
return {
newWidth: imgWidth,
newHeight: imgHeight
};
}
}
async function toCanvas(element,scrolledHeight=0,viewHeight=window.innerHeight) {
// 放大倍率
const scaleRatio = window.devicePixelRatio * 2
const canvas = await html2canvas(element, {
scale: scaleRatio,
useCORS: true,
width: document.querySelector("#myList").scrollWidth,
height: Math.min(element.scrollHeight, viewHeight),
windowWidth: document.querySelector("#myList").scrollWidth,
windowHeight: document.querySelector("#myList").scrollHeight,
x: 0,
y: scrolledHeight,
})
let canvasImg = canvas.toDataURL("image/jpeg",1);
return { width:canvas.width, height:canvas.height, data: canvasImg}
}
// 循环生成PDF
let pdfImgTop = 0
let pageHeight = 0
async function loopGeneratePDF(targetElement, scrolledHeight = 0, viewHeight =window.innerHeight) {
const A4_HEIGHT = 900
if (scrolledHeight >= targetElement.scrollHeight) {
message.success("生成PDF成功");
return;
}
const { data: imgData, height, width } = await toCanvas(targetElement, scrolledHeight, viewHeight);
// console.log("图片",imgData)
const { newWidth, newHeight } = resizeImage(width, height);
pdf.addImage(imgData, 'JPEG', 0, pdfImgTop, newWidth, newHeight);
const pages = pdf.internal.getNumberOfPages()
message.success(`生成第${pages}页`)
// 下一次需要截取的开始高度
scrolledHeight += Math.floor(height / 2);
pdfImgTop += newHeight;
// 如果当前页内容不足一页A4纸的高度,则递归调用并调整视图高度
if (A4_HEIGHT>scrolledHeight) {
// 剩余页面的高度
pageHeight = A4_HEIGHT - scrolledHeight;
return loopGeneratePDF(targetElement, scrolledHeight, pageHeight);
}
else {
if(targetElement.scrollHeight - scrolledHeight > A4_HEIGHT || pdfImgTop>A4_HEIGHT){
pdf.addPage();
pdfImgTop = 10;
}
return loopGeneratePDF(targetElement, scrolledHeight-20);
}
}
export const outCanvas = async function (targetElement) {
if (!(targetElement instanceof HTMLElement)) {
return;
}
await loopGeneratePDF(targetElement,0,window.innerHeight)
return pdf.save('test.pdf');
}