Skip to content

Multipage : PDF content breaking #3874

@AnuradhaS3

Description

@AnuradhaS3

I am using jsPDF + html2canvas to create a PDF document. However, I am encountering an issue where the content breaks when transitioning from one page to the next, especially since we are dealing with a substantial amount of content for conversion.

Image Image

Facing this issue on all Mobile devices (IOS/Android)

Code Reference
async printBodyAsPDF(content) {
if (this.appUtility?.isMobileAppView() && this.appUtility?.isPageEligibleForPrintInMobile()) {
let nodes = content.querySelectorAll(".al-print-only");
if (nodes && nodes.length > 0) {
[].forEach.call(nodes, (ele) => {
ele.classList.remove("al-print-only");
});
}
// Adds float:right !important to the .al-w100 class dynamically
const style = document.createElement('style');
style.id = 'af-print-w100';
style.innerHTML = .al-w100 { float: none !important; };
document.head.appendChild(style);
// fix words spacing issue in IOS mobile app
if (this.appUtility.isIOS()) {
const styleelm = document.createElement('style');
styleelm.id = 'letter-spacing-fix';
// Add the CSS rule to the style element
styleelm.innerHTML = 'b, strong { letter-spacing: 0.02em !important; }';
document.head.appendChild(styleelm);
}
try {
// Render the desired element to canvas
const canvas = await html2canvas(content, { scale: 2 });
const imgData = canvas.toDataURL("image/png");
const pdf = new (window as any).jspdf.jsPDF({
orientation: 'portrait',
unit: 'mm',
format: 'a4',
putOnlyUsedFonts: true,
floatPrecision: 16,
});
// PDF page size in mm (A4)
const pdfWidth = 210;
const pdfHeight = 297;
// Canvas size in px
const imgWidth = pdfWidth;
let imgHeight = (canvas.height * pdfWidth) / canvas.width;
let remainingHeight = imgHeight;
// If content fits on one page
if (imgHeight <= pdfHeight) {
pdf.addImage(imgData, "PNG", 0, 0, imgWidth, imgHeight);
} else {
// Multi-page logic
let pageHeight = pdfHeight;
let pageCanvas = document.createElement("canvas");
let pageCtx = pageCanvas.getContext("2d");
let sX = 0, sY = 0, sWidth = canvas.width, sHeight = (canvas.width * pageHeight) / pdfWidth;

                while (remainingHeight > 0) {
                    pageCanvas.width = canvas.width;
                    pageCanvas.height = Math.min(sHeight, canvas.height - sY);

                    pageCtx.clearRect(0, 0, pageCanvas.width, pageCanvas.height);
                    pageCtx.drawImage(canvas, sX, sY, sWidth, pageCanvas.height, 0, 0, sWidth, pageCanvas.height);

                    let pageImgData = pageCanvas.toDataURL("image/png");
                    pdf.addImage(pageImgData, "PNG", 0, 0, imgWidth, (pageCanvas.height * pdfWidth) / canvas.width);

                    remainingHeight -= pageHeight;
                    sY += sHeight;

                    if (remainingHeight > 0) {
                        pdf.addPage();
                    }
                }
            }
            if (this.appUtility.isIOS()) {
                // Save PDF after a short delay to ensure all resources are loaded
                const currentDate = new Date();
                const pageUrl = window.location.href;
                const current_awl_page = this.appUtility.getPageName(pageUrl);
                const filename = `${current_awl_page}_${currentDate.getFullYear()}_${currentDate.getMonth() + 1}_${currentDate.getDate()}_${currentDate.getHours()}_${currentDate.getMinutes()}_${currentDate.getSeconds()}.pdf`;
                pdf.save(filename);
                this.hideShowPDFLoader = false;
            } else {
                // Generate PDF as Blob
                let blobUrl = pdf.output('bloburl');
                window.open(blobUrl, "_blank");
                // Added timer to clean browser memory 
                setTimeout(() => {
                    URL.revokeObjectURL(blobUrl.toString());
                }, 5000);
                // Hide the print loader
                this.hideShowPDFLoader = false;
                // show open as PDF button again
                if (content) {
                    content.classList.add("al-print-only");
                }
                const allNode = document.querySelectorAll("body > *");
                if (allNode && allNode.length > 0) {
                    [].forEach.call(allNode, (ele) => {
                        ele.classList.remove("al-print-no");
                    });
                }
                const lightBoxEle = document.querySelectorAll(".al-print-light-box");
                [].forEach.call(lightBoxEle, (ele) => {
                    ele.remove();
                });
                // remove float:right !important to the .al-w100 class style 
                let styleTag = document.getElementById('af-print-w100');
                if (styleTag) {
                    styleTag.remove();
                }
                let elm = document.getElementById('letter-spacing-fix');
                if (elm) {
                    elm.remove();
                }
            }
        } finally {
               
        }
    } 
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions