html2pdf

juhojung·2022년 2월 20일
0

react.js

목록 보기
2/4

html 에서 보이는것들을 pdf 로 만든 과정

A2B 라고 적는건 아주 센스가 있어보여서 좋다.

여러 문서를 다루는 회사 프로젝트를 진행하다보니, 문서를 import/export 하는 과정이 많아졌다.
그런 중 WYSIWYG Editor 도 지원을 했는데,
그러다보니 당연하게도 보이는걸 출력도 할 수 있게 해달라고 요청을 해왔다.
출력물을 관리할 필요는 없다고 판단, Front-End 에서 다운로드 받을 수 있게 해봤다.

import html2canvas from "html2canvas";
import jsPDF from "jspdf";

export type Html2PDFProps = {
    elementId: string;
    classId?: string;
    filename?: string;
    element?: any;
    whiteSpace?: number;
    isSave?: boolean;
    extraClass?: string;
    extraId ?: string;
};
interface FinalHtml2PDFProps extends Html2PDFProps {}
export const Html2PdfComponent = async (
    props: FinalHtml2PDFProps
): Promise<any | null> => {
    var el = document.getElementById(props.elementId);
    if (props.classId && props.classId.length > 0) {
        let el_list = document.getElementsByClassName(props.classId);
        if (el_list.length > 0) el = el_list[0] as HTMLElement;
    }
    if (props.element) el = props.element;
    let res = await new Promise((r) => {
        if (el) {
        	// Style, Class, Id 등등 canvas 에 그리기전에 미리 세팅
            el.setAttribute(
                "style",
                "width:1080px; margin:0; line-height: 160%"
            );
            el.setAttribute("id", props.extraId ? props.extraId : "");
            if (props.extraClass) el.classList.add(props.extraClass);
            //
            html2canvas(el, {
                width: 1080,
                height: el.scrollHeight,
                useCORS: true, // 외부 url 로드하는 Image 등이 껴있을경우를 위해
            }).then((canvas) => {
                const imgData = canvas.toDataURL("image/png", 1.0);
                // A4 기준 비율 스크린이 딱 맞게 하기위해
                var imgWidth = 210;
                var pageHeight = imgWidth * 1.414; 
                //
                var imgHeight = (canvas.height * imgWidth) / canvas.width;
                var heightLeft = imgHeight;
                const pdf = new jsPDF("p", "mm", "a4", 1);
                const widthSpace = props.whiteSpace ? props.whiteSpace : 0;
                var position = props.whiteSpace ? props.whiteSpace : 0;
                pdf.addImage(
                    imgData,
                    "PNG",
                    widthSpace,
                    position,
                    imgWidth - widthSpace * 2, // 여백을 준다.
                    imgHeight - widthSpace * 2,
                    "",
                    "FAST" // 해당 옵션을 안주면 용량은 훨씬큰데, 품질은 비슷한 pdf가 만들어져서 용량 차원에서 옵션을 넣었다.
                );
				// 한 page 안에 다 못그릴 경우
                heightLeft -= pageHeight;
                while (heightLeft >= 0) {
                    position = heightLeft - imgHeight;
                    pdf.addPage();
                    pdf.addImage(
                        imgData,
                        "PNG",
                        widthSpace,
                        position,
                        imgWidth - widthSpace * 2,
                        imgHeight - widthSpace * 2,
                        "",
                        "FAST"
                    );
                    heightLeft -= pageHeight;
                }
                //
                // 저장한다면 바로 pdf 다운로드 진행
                if (props.isSave)
                    pdf.save(props.filename ? props.filename : "preview.pdf");
                // console.log(imgData);
                // Canvas 에 그린후 Image Data 를 raw data 로 추출
                r(imgData);
            });
        }
    });
    if (el) el.setAttribute("style", "");
    return res;
};

나의 경우 특정 데이터를 껴넣어야(?) 할 필요가 있어 직접 만들었다.
단순하게 html2pdf 기능은 아래 library 를 참고하면 될 듯 싶다.

https://ekoopmans.github.io/html2pdf.js/

그럼 안녕👋

profile
"어찌 할 수 없는 일에 대해 고민하는 시간은 낭비일 뿐이다."

0개의 댓글