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

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions