0

I am trying to Save ReactJS output(includes visual reports etc..) as PDF file.

I used html2canvas to take screenshot and then used jspdf for converting that to PDF. But the problem is when screen size is reduced(or in mobile view) even screenshots are of small size as it uses DOM styling. So PDF is not properly generated as it should be seen in Full View.

Mario Petrovic
  • 7,500
  • 14
  • 42
  • 62
Yog
  • 61
  • 1
  • 2
  • 6

1 Answers1

3

You can use dom-to-png plugin by npm to create your image first and then just put that image in your PDF File.

like this

export function printDetails(ref, fileName: string) {
    const pdf = new jsPDF('p', 'mm', 'a4');
    let height = pdf.internal.pageSize.height;
    let pageHeightInPixels = ref.clientHeight;
    let pageHeightInMM = pageHeightInPixels / 3.78;
    let pages = pageHeightInMM / height;
    const roundOff = Number(pages.toString().split('.')[1].substring(0, 1));
    const pageNo = (roundOff > 0 ? pages + 1 : pages);
    let pageCount = pages < 1 ? 1 : Math.trunc(pageNo);
    let imageHeight = height;
    domtoimage.toPng(ref, {
        height: ref.clientHeight,
        width: 665,
        style: {
            transform: 'unset',
            left: '0%',
            margin: 'unset',
            backgroundColor: 'white',
            maxHeight: '100%'
        },
    })
        .then(function (dataURL) {
            hidePrintPreviewModal();
            for (let i = 1; i <= pageCount; i++) {
                let pdfStartingHeight = height * (i - 1);
                pdf.addImage(dataURL, 'JPEG', 30, -pdfStartingHeight, 160, ref.clientHeight);
                if (i < pageCount) {
                    pdf.addPage();
                }
            }
            pdf.save(`${fileName}.pdf`);
        }).catch(function (error) {
            console.error('oops, something went wrong!', error);
        });
}

Using id

<html>
<body>
<div id="print">
{Whatever you want to print}
</div>
</body>
</html>

JS:

const ref = document.getElementById('print');
printDetails(ref, 'test')

Using ref

class Demo extends React.Component {

    refValue;

    printData = () => {
        const node = React.findDOMNode(this.refValue)
        printDetails(node, 'test');
    }

    render() {
        return (
            <div ref={(value) => { this.refValue = value }}>
                {Whatever you want to print}
    <button onClick={this.printData}>PRint</button>
            </div>

        )
    }
}

This function is using the dom to png and jspdf both to print the file. It is also calculating the no of pages so that nothing is missed.

You need to pass the node of your html element which you can get by ref or document.getElementById and that function will calculate the image with the height and width applied.

reference ->

dom-to-image

jspdf

Harish Soni
  • 1,796
  • 12
  • 27
  • Giving one error => TypeError: node.cloneNode is not a function – Yog Dec 27 '17 at 10:38
  • N one more thing. what should I pass for "ref"?? – Yog Dec 27 '17 at 10:38
  • ref the ID of your DOM node that you have to pass react provides ref i.e. reference to the DOM Node. – Harish Soni Dec 27 '17 at 11:50
  • The dom-to-image assumes that the `.toPng` 's first argument if a DOM node and it clones it recursively with all the styles applied in it. So if the argument is not a node than the function cloneNode can not be called on that I think that's why you are getting this error. – Harish Soni Dec 27 '17 at 12:01
  • I have added some extra code in my answer so that you can understand easily how that function is working. – Harish Soni Dec 27 '17 at 12:02
  • On reducing screen size its still not effective – Yog Dec 29 '17 at 04:40
  • Reducing screen size will not effect the printing whatever the browser will display this will print. – Harish Soni Dec 29 '17 at 06:29