当我尝试使用 HTML2Canvas 和 jsPDF 将图像转换为 PDF 文档时,特别是在 RadiobuttonWithForm 场景中,我遇到了浏览器冻结问题。我当前的代码为每个图像转换创建多个 HTML2Canvas 实例,导致浏览器主线程冻结并可能出现错误。
我尝试通过使用 Promise.all 异步并行执行图像转换来提高性能并解决问题。然而,我仍然遇到冻结问题
` downloadAlt: 函数(json) { // 从窗口对象导入jsPDF库 常量{ jsPDF } = window.jspdf;
// Create a jsPDF object with page orientation "portrait", measurement unit "mm", and page format "a4"
var doc = new jsPDF("p", "mm", "a4");
// Set the page dimensions
var pageWidth = doc.internal.pageSize.width;
var pageHeight = doc.internal.pageSize.height;
// Set the margins
var leftMargin = 10;
var rightMargin = pageWidth - 10;
var margin = 10;
// Current position on the page
var currentY = margin;
// Add the section titled "Procedure"
doc.setFont("Verdana", "bold");
doc.setFontSize(9);
doc.text("Procedure", leftMargin, currentY);
// Add a separating line below the word "Procedure"
doc.setLineWidth(0);
var addmorespace = 1;
var marginFactor = 2;
var space = 5;
var adjustspace = 10;
var distancefromtheline = 9;
doc.line(
leftMargin,
currentY + addmorespace,
rightMargin,
currentY + addmorespace,
"S"
);
currentY += distancefromtheline; // Distance from the line
var currentX = leftMargin; // Variable to keep track of the horizontal position
// Select all elements with the attribute "data-printpdf"
var elementsToPrint = document.querySelectorAll("[data-printpdf]");
// Iterate through the elements and add the information to the PDF document
for (var i = 0; i < elementsToPrint.length; i++) {
//fare un foreach
// This line retrieves the value of the "data-type" attribute associated with the current element.
var element = elementsToPrint[i];
// Retrieves the value of the "data-type" attribute from the current element
// and assigns it to the variable 'elementType'.
var elementType = element.getAttribute("data-type");
// Use a switch statement to handle different types of elements
switch (elementType) {
case "FirstTitle":
// Set font style and size for h2
doc.setFont("Verdana", "bold");
doc.setFontSize(13);
//is then used to calculate the maximum text parts size
// Split the text into parts that fit the page width
var textPartsH2 = doc.splitTextToSize(
element.textContent,
pageWidth - marginFactor * margin
);
textPartsH2.forEach((part, index) => {
// Check if the new current position exceeds the maximum height
if (currentY + space > pageHeight - margin) {
// Add a new page if the content exceeds the page height
doc.addPage();
currentY = margin; // Reset the vertical position on the new page
}
// Add the text to the PDF document
doc.text(part, leftMargin, currentY);
currentY += adjustspace; // You can adjust the line spacing here
});
break;
case "Text":
// Set font size and style for label
doc.setFontSize(10);
doc.setFont("Verdana", "normal");
// Split the text or value into parts that fit the page width
var textOrValuePartsLeft = doc.splitTextToSize(
element.textContent,
pageWidth - marginFactor * margin
);
textOrValuePartsLeft.forEach((part, index) => {
// Check if the new current position exceeds the maximum height
if (currentY + adjustspace > pageHeight - margin) {
// Add a new page if the content exceeds the page height
doc.addPage();
currentY = margin; // Reset the vertical position on the new page
}
// Add the text or value to the PDF document
doc.text(part, leftMargin, currentY);
currentY += adjustspace; // You can adjust the distance between lines here
});
break;
case "SecondTitle":
// Set font size and style for the second title
doc.setFontSize(11);
doc.setFont("Verdana", "bold");
// Split the text or value into parts that fit the page width
var textOrValuePartsLeft = doc.splitTextToSize(
element.textContent,
pageWidth - marginFactor * margin
);
textOrValuePartsLeft.forEach((part, index) => {
// Check if the new current position exceeds the maximum height
if (currentY + adjustspace > pageHeight - margin) {
// Add a new page if the content exceeds the page height
doc.addPage();
currentY = margin; // Reset the vertical position on the new page
}
// Add the text or value to the PDF document
doc.text(part, leftMargin, currentY);
currentY += adjustspace; // You can adjust the distance between lines here
});
break;
case "Title":
// Set font size and style for the title
doc.setFontSize(12);
doc.setFont("Verdana", "normal");
// Check if an inner element with a specific class exists within the element
if (
(innerElement = element.querySelector(
".espd-marginLeft1em.ng-binding"
))
) {
if (innerElement) {
// Get the trimmed text inside the div
var textInsideDiv = innerElement.innerText.trim();
// Check if there is text content
if (textInsideDiv.length > 0) {
// Split the text into parts that fit the page width
var textPartsDiv = doc.splitTextToSize(
textInsideDiv,
pageWidth - marginFactor * margin
);
textPartsDiv.forEach((part, index) => {
// Check if the new current position exceeds the maximum height
if (currentY + adjustspace > pageHeight - margin) {
// Add a new page if the content exceeds the page height
doc.addPage();
currentY = margin; // Reset the vertical position on the new page
}
// Calculate the height of the rectangle based on the number of lines of the divided text
var lines = doc.splitTextToSize(
part,
pageWidth - marginFactor * margin
);
var lineHeight = 10; // Height of a single line
var rectangleHeight = lines.length * lineHeight; // Total height of the rectangle
// Set fill color and draw a rectangle
doc.setFillColor(238, 226, 238);
doc.rect(
leftMargin,
currentY,
pageWidth - marginFactor * margin,
rectangleHeight,
"F"
);
// Position the text in the center of the rectangle's height
doc.text(
part,
leftMargin,
currentY + lineHeight / marginFactor
);
currentY += rectangleHeight + adjustspace; // Update the vertical position
});
}
}
}
break;
case "LabelRoleName":
// Set font style and size for the label
doc.setFont("Verdana", "bold");
doc.setFontSize(10);
// Split the text or value into parts that fit the page width
var textOrValuePartsLeft = doc.splitTextToSize(
element.textContent,
pageWidth / marginFactor - margin
);
textOrValuePartsLeft.forEach((part, index) => {
// Check if the new current position exceeds the maximum height
if (currentY + adjustspace > pageHeight - margin) {
// Add a new page if the content exceeds the page height
doc.addPage();
currentY = margin; // Reset the vertical position on the new page
}
const xOffset = 40; // Stores the horizontal offset value used for adjusting the x-coordinate in the document
// Use the variable in the code
doc.text(part, leftMargin - xOffset, currentY);
// Add the text or value to the PDF document
doc.text(part, leftMargin - xOffset, currentY);
// Update the current position on the page
currentY += space;
});
break;
case "LabelProcedure":
// Set font style and size for the label
doc.setFont("Verdana", "bold");
doc.setFontSize(10);
// Split the text or value into parts that fit half the page width
var textOrValuePartsLeft = doc.splitTextToSize(
element.textContent,
pageWidth / marginFactor - margin
);
textOrValuePartsLeft.forEach((part, index) => {
// Check if the new current position exceeds the maximum height
if (currentY + 10 > pageHeight - margin) {
// Add a new page if the content exceeds the page height
doc.addPage();
currentY = margin; // Reset the vertical position on the new page
}
// Add the text or value to the PDF document
doc.text(part, leftMargin - 37, currentY);
// Update the current position on the page
currentY += adjustspace; // You can adjust the distance between lines
});
break;
case "Label":
// Set font style and size for the label
doc.setFont("Verdana", "bold");
doc.setFontSize(10);
// Split the text or value into parts that fit half the page width
var textOrValuePartsLeft = doc.splitTextToSize(
element.textContent,
pageWidth / marginFactor - margin
);
textOrValuePartsLeft.forEach((part, index) => {
// Check if the new current position exceeds the maximum height
if (currentY + adjustspace > pageHeight - margin) {
// Add a new page if the content exceeds the page height
doc.addPage();
currentY = margin; // Reset the vertical position on the new page
}
// Add the text or value to the PDF document
doc.text(part, leftMargin, currentY);
// Update the current position on the page
currentY += adjustspace; // You can adjust the distance between lines
});
break;
case "Input":
// Set font and font size
doc.setFont("Verdana", "normal");
doc.setFontSize(10);
// Get the text or value of the field
var textContent =
elementType === "Input" &&
element &&
typeof element.value === "string" ?
element.value :
"";
var textContentParts = [];
// Split the text into parts adapted to the page width
var words = textContent.split(" ");
var currentLine = "";
// Iterate through the words in the text
for (var word of words) {
// Add the current word to the text line being built
var testLine = currentLine + word + " ";
// Calculate the width of the text line in points
var testWidth = doc.getStringUnitWidth(testLine) * adjustspace;
// Check if the text line width exceeds the page width, considering margins
if (testWidth > pageWidth - marginFactor * margin) {
// Add the current (complete) text line to the array of text parts
textContentParts.push(currentLine.trim());
// Start a new line with the current word
currentLine = word + " ";
} else {
// If the text line width doesn't exceed the limit, continue composing the line
currentLine = testLine;
}
}
// Add the last text part (after removing white spaces) to the array of text parts
textContentParts.push(currentLine.trim());
// Calculate the number of lines based on text content parts
var numberOfLines = textContentParts.length;
// Check if the current position (currentY) plus the number of text lines exceeds the maximum page height minus the bottom margin
if(currentY + numberOfLines > pageHeight - margin) {
// If true, add a new page to the document
doc.addPage();
// Set the new Y position to the top margin of the new page
// This ensures that the next text starts from the top margin of the newly added page
currentY = margin;
}
// Calculate rectangle X and Y positions
let rectangleOffsetX = 80;
let rectangleOffsetY = 15;
let rectangleX = rightMargin - rectangleOffsetX;
let rectangleY = currentY - rectangleOffsetY;
// Calculate text X and Y positions
let textXCoordinate = rectangleX;
// Define constants for calculations
const additionalLines = 5;
const divisionFactor = 4;
// Calculate text Y coordinate
let textYCoordinate = rectangleY+(numberOfLines + additionalLines) / divisionFactor;
// Draw the gray rectangle
doc.setFillColor(238, 238, 238);
doc.rect(
rectangleX,
rectangleY,
80,
numberOfLines * additionalLines + numberOfLines,
"F"
);
// Draw text only if there is content
if (textContent.trim() !== "") {
doc.setFont("Verdana", "normal");
doc.text(
textContentParts.join("\n"),
textXCoordinate,
textYCoordinate, {
align: "left",
baseline: "top",
}
);
doc.setFont("Verdana", "bold");
}
break;
case "RadiobuttonWithForm":
const divelement = element.getElementsByTagName("div");
let imagesProcessed = 0;
const promises = [];
for (const divElement of divelement) {
const div = divElement.querySelector(".col-lg-12.espd-divVanilla");
if (div) {
const promise = new Promise((resolve) => {
html2canvas(div).then((canvas) => {
const imageData = canvas.toDataURL('image/jpeg');
doc.addImage(imageData, 'JPEG', 10, 10, 100, 100);
imagesProcessed++;
resolve();
});
});
promises.push(promise);
}
}
Promise.all(promises).then(() => {
doc.save("informazioni.pdf");
});
break;
}
}
doc.save("informazioni.pdf");
}`
我尝试过的:我尝试在RadiobuttonWithForm场景中使用HTML2Canvas和jsPDF将多个图像转换为PDF文档。为了实现这一目标,我迭代了 div 元素,使用 HTML2Canvas 捕获图像,然后使用 jsPDF 将它们添加到 PDF。
预期结果:我希望图像能够异步转换并并行添加到 PDF,而不会冻结浏览器。我的目标是通过使用 Promise.all 同时处理异步图像转换过程来优化性能。
实际结果:然而,尽管实现了 Promise.all 进行异步处理并尝试并行处理,但浏览器在转换过程中仍然冻结。看来用于图像转换的 HTML2Canvas 实例过多导致了冻结,并且 PDF 生成无法顺利完成。
我正在寻求有关如何有效优化此异步过程的指导,以防止浏览器在 RadiobuttonWithForm 情况下创建 PDF 期间冻结。任何异步处理图像转换和 PDF 生成的见解或替代方法将不胜感激。
这不是答案,但你使用
Promise.all().then(...)
因此,它会占用您的所有文件,但之后等待所有承诺在 switch 内解决