HTML2Canvas 和 jsPDF 问题导致 RadiobuttonWithForm 情况下浏览器冻结

问题描述 投票:0回答:1

当我尝试使用 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 生成的见解或替代方法将不胜感激。

javascript jspdf html2canvas
1个回答
0
投票

这不是答案,但你使用

Promise.all().then(...)
因此,它会占用您的所有文件,但之后等待所有承诺在 switch 内解决

© www.soinside.com 2019 - 2024. All rights reserved.