react-pdf 라이브러리를 사용해서 전용컴포넌트로 한땀한땀 쌓아올려서 pdf 파일을 만들어도 되지만 그건 너무나 귀찮습니다.
저희는 웹페이지의 화면을 캡쳐해서 pdf 파일로 다운로드 받는 편한 방법을 사용할 것입니다.
아래의 두 패키지를 설치합니다.
yarn add html2canvas jspdf
html2canvas 는 리액트 컴포넌트를 이미지로 변환해주는 라이브러리고
jspdf는 그 이미지를 pdf파일로 만들어주는 라이브러리 입니다.
이슈들
그런데 사용해보면 바로 이슈가 터져 나옵니다. 이슈 해결하면서 해결된 코드도 같이 보겠습니다.
이슈1 : 페이지 높이가 너무 높아서 (내용이 너무 길어서) pdf 파일안에 다 담기지 않고 잘리는 이슈
처음에 인터넷에서 흔한 코드 긁어와서 pdf파일의 width, height 를 설정해주었습니다.
잘 된 줄알고 기뻐하고 있는데 페이지 하단을 보니 내용이 잘려있습니다. 그래서 높이 부분을 무작정 건드렸더니 해상도가 깨집니다.
이것은 페이지 높이가 너무 길어서 발생하는 이슈였으며,
아래와 같이 코드 수정해주었더니 페이지 잘리지 않고 전체 페이지 내용이 잘 보여집니다.
import { useEffect, useRef, useState } from 'react'
import html2canvas from 'html2canvas'
import { jsPDF } from 'jspdf'
const 컴포넌트 = ()=>{
const printRef = useRef<HTMLElement>(null)
const handleDownloadPdf = async () => {
const element = printRef.current
if (!element) {
return
}
const canvas = await html2canvas(element)
const componentWidth = element.offsetWidth
const componentHeight = element.offsetHeight
const orientation = componentWidth >= componentHeight ? 'l' : 'p'
const imgData = canvas.toDataURL('image/png')
const pdf = new jsPDF({
orientation,
unit: 'px',
})
pdf.internal.pageSize.width = componentWidth
pdf.internal.pageSize.height = componentHeight
pdf.addImage(imgData, 'PNG', 0, 0, componentWidth, componentHeight)
pdf.save('대출제안서.pdf')
}
return (
<>
<section className="flex flex-col gap-20 py-20 px-30 bg-piper-grey-100"
ref={printRef}>
// 컴포넌트 내용...
</section>
<button onClick={handleDownloadPdf}>
<span>PDF 다운로드</span>
</button>
</>
)
}
이슈2 : 일부 글자가 바닥에 붙어버리는 이슈
보통 div 박스 안에 글자를 중앙에 정렬한 경우 공통적으로 발생했습니다. (아래 이미지 참고)
무슨 수를 써도 해결되지 않았는데 원인은 정말 뜬금없이 Tailwind.css 에 있었습니다.
이것이 마법입니다.
img 의 기본 스타일에 inline-block을 추가해주어야 했습니다. 아무래도 기본 스타일이 날라가버리면서 문제가 터졌던 것 같습니다.
/* global.css */
@tailwind base;
@layer base {
img {
@apply inline-block;
}
}
@tailwind components;
@tailwind utilities;
참고
- https://stackoverflow.com/a/64761137
- https://github.com/niklasvh/html2canvas/issues/2775#issuecomment-1204988157
'프론트엔드 개발 > React.js' 카테고리의 다른 글
리액트 렌더링 최적화를 위한 useDeferredValue 는 debounce 의 완전한 대체제가 아니다. (0) | 2023.12.29 |
---|---|
React Query 캐시 초기화 후 다시 받아오기 (0) | 2023.06.14 |
서버사이드 렌더링를 사용하더라도 결국 다운받는 HTML 파일 크기를 줄여야 사용자에게도 구글봇에게도 유리하다. (0) | 2023.02.05 |
Jotai 와 Zustand 는 무엇이 다른가요? (0) | 2023.02.05 |
웹 프론트엔드 유용한 링크 모음 (0) | 2023.02.04 |