Save screen as PDF

배고픈 징징이 ㅣ 2025. 1. 2. 16:47

1. 서론

단순하게 화면을 PDF 파일로 저장하는 코드이다.

다만 너무 여러 글들에서 제대로 사이즈를 체크하지 않은채 화면을 PDF로 저장하게 해서, 화면이 잘리거나 중복으로 겹치는 부분들이 있어서 수정한 코드를 올리기로 했다.

 

준비물

1. html2canvas

2. jspdf

 

2. 코드

먼저 의존성 추가를 해준다.

npm i html2canvas
npm i jspdf

 

 

다음으로 각자 화면마다 달라지는 메소드 일 것이다.

화면의 CSS가 화면을 가져오는데 방해가되는 경우가 있다.

그럴경우 먼저 방해가 되는 부분을 제거하고 다시 복구해주는 메소드이다.

const prepareModalForCapture = (modalElement : any) => {    
    modalElement.parentNode.classList.remove("min-h-[670px]", "max-h-[670px]");

    return () => {
        modalElement.parentNode.classList.add("min-h-[670px]", "max-h-[670px]");
    };
};

 

그리고 이제 PDF 저장 메소드이다.

마진 10 기준으로 작성되었으며, postion 부분을 마진값이 변경될때마다 조금씩 바뀌어야한다.

완벽하게 맞는 계산식을 찾지 못했다...

18을 기준으로 조금씩 수정하면 된다.

const savePDF = () => {
    const modalElement : any = document.querySelector("#pdfSection");
    const restoreStyle = prepareModalForCapture(modalElement)

    try{
        html2canvas(modalElement, {
            scale: 2,
            width: modalElement.scrollWidth,
            height: modalElement.scrollHeight
        }).then(canvas => {
            const imgData = canvas.toDataURL('image/png');
            const margin = 10;
            const imgWidth = 210 - (margin * 2);
            const imgHeight = canvas.height * imgWidth / canvas.width;
            const pageHeight = imgWidth * 1.414;
            let heightLeft = imgHeight;
            let doc = new jsPDF('p', 'mm');
            let position = margin;

            doc.addImage(imgData, 'PNG', margin, position, imgWidth, imgHeight);
            heightLeft -= pageHeight;

            while (heightLeft >= 18) {
                position = heightLeft - imgHeight - 18;

                doc.addPage();
                doc.addImage(imgData, 'PNG', margin, position, imgWidth, imgHeight);
                heightLeft -= pageHeight;
            }

            // PDF를 새탭으로 열기
            //window.open(doc.output('bloburl'));

            // PDF를 바로 다운로드
            doc.save(`${demand.USE_MONTH.substring(0, 4) + "-" + demand.USE_MONTH.substring(4, 6)}.pdf`);
        })
    }finally{
        restoreStyle();   
    }
}

 

 

 

반응형