회사 웹사이트에서 특정영역을 pdf 파일로 다운로드가 필요하여 라이브러리를 찾아보게 되었고
html2pdf.js와 vue-html2pdf가 있었다.
> vue-html2pdf
"vue html to pdf" 라고 구글에 검색하면 가장 먼저 나오고 사용량이 가장 많은 vue-html2pdf은
html2pdf.js를 vue 컴포넌트 형식으로 제공한다.
기존 html2pdf.js와 다르게 미리보기 창을 띄워주는 preview-modal 옵션처럼 장점이 있는 반면,
slot으로 pdf에 들어갈 내용을 넣어야 하는데 slot안에 내용이 있는 태그들을 넣게 되면 해당 태그들은 웹에서 보여지지 않기 때문에
같은 내용을 한번 더 써줘야 하는 번거로움이 생긴다.
단시간에 단순구조로 pdf를 다운로드 할 수 있도록 하는 것이 목표였기 때문에
원래 vue-html2pdf도 html2canvas와 jsPDF 기반으로 만들어져있어 본래의 html2pdf을 사용하기로 결정했다.
※ 참고답변
stackoverflow.com/questions/60204249/impossible-to-convert-html-code-to-pdf-with-vue-html2pdf
> html2pdf.js
vue 컴포넌트 형식의 라이브러리는 아니지만 plugin으로 만들어서 사용하니 간단했다.
설치
공식 github에서 최신 버전이 아닌 0.9.3버전을 추천하여 해당 버전을 설치한다.
https://github.com/eKoopmans/html2pdf.js/tree/bugfix/clone-nodes-BUILD
$yarn add html2pdf.js@^0.9.3
html2pdf.js를 vue plugin으로 설정
html2pdf.js를 vue plugin으로 등록해 놓으면 프로젝트 내에서 import할 필요 없어 코드를 줄일 수 있어 설정했다.
파일 이름 및 경로: src/plugins/htmlToPdf.js
/* htmlToPdf.js */
import html2pdf from "html2pdf.js";
const methods = {
htmlToPdf: (location, fileName) => {
html2pdf()
.set({
margin: 0, // 다운로드된 pdf 파일의 마진 여백
filename:
navigator.userAgent.indexOf("MSIE") !== -1 ||
navigator.appVersion.indexOf("Trident/") > -1
? `${fileName}.pdf`
: fileName,
// filename에서 IE11은 .pdf를 자동으로 넣어주지 않아 .pdf를 파일명에 넣어줘야 한다.
pagebreak: { mode: "avoid-all" },
image: { type: "jpeg", quality: 1 }, // pdf 들어갈 영역을 사진을 찍어 변환 하는 이미지 퀄리티
html2canvas: {
width: 793.7, // a4 width
height: 1122.5, // a4 height
useCORS: true, // 영역 안에 로컬 이미지를 삽입 할 때 옵션 필요
scrollY: 0, // 스크롤 이슈 ⭐️
scale: 3, // browsers device pixel ratio
dpi: 300,
letterRendering: true,
allowTaint: false, // useCORS를 true로 설정시 반드시 allowTaint를 false 해주어야함
},
jsPDF: { orientation: "portrait", unit: "mm", format: "a4" },
})
.from(location)
.save();
},
};
export default {
install(Vue) {
Vue.prototype.$htmlToPdf = methods.htmlToPdf;
},
};
⭐️ 스크롤이 맨 아래에 가있는 상태에서 download버튼을 누르면,
pdf의 이미지캡처가 해당스크롤을 기준으로 출력하므로 앞부분의 page가 빈 상태로 나오는 문제가 생긴다.
그러므로 scrollY: 0 옵션을 추가하여 세로 scroll위치 0부터 pdf를 전부 출력하도록 하자.
main.js에 가서 plugins/htmlToPdf.js를 import 후 등록해준다.
/* main.js */
import htmlToPdf from "./plugins/htmlToPdf";
Vue.use(htmlToPdf);
vue 예시 파일
<template>
<div>
// ...
<!-- pdf에 들어갈 내용 -->
<article class="pdf-wrapper" ref="pdfArea" :key="pdfKey">
// ...
</article>
<!-- pdf 다운로드 버튼 -->
<section class="pdf-button" @click="htmlToPDF">PDF 내려받기</section>
</div>
</template>
<script>
export default {
data: () => ({
pdfKey: 0,
}),
methods: {
htmlToPDF() {
const name = 'document';
this.$htmlToPdf(this.$refs.pdfArea, name);
this.pdfKey += 1;
},
},
};
</script>
pdf로 변환 후 radio box에 있던 값이 사라지는 버그가 생긴다면
그걸 방지하기 위해 pdf 변환 후 강제로 컴포넌트를 다시 load해줘야 한다.
간편하게 하기 위해 pdf의 영역 컴포넌트에 key로 변수를 넣고 해당 변수를 pdf변환 끝날 때 +1를 해주어 key를 변경시킨다.
key가 변경되면 해당 컴포넌트를 다시 load 시켜준다.
[참고 URL]
https://velog.io/@adc0612/vue-html2pdf.js-%EC%A0%81%EC%9A%A9
A4 용지 크기
가로: 21cm 👉 793.7px
세로: 29.7cm 👉 1122.5px
/* pdf에 들어갈 내용 */
.pdf-wrapper {
width: 793.7px;
height: 1122.5px;
}
🚫 CSS rules are not getting applied
PDF 파일을 다운로드 받았을때 외부 스타일시트(scss파일 등)가 적용되지 않는 이슈가 발생할 수 있다.
1. 인라인 스타일로 직접 작성
https://github.com/eKoopmans/html2pdf.js/issues/219#issuecomment-499819399
2. sass사용시 unnesting
https://github.com/eKoopmans/html2pdf.js/issues/219#issuecomment-768583651
'Vue.js' 카테고리의 다른 글
딥셀렉터(v-deep) 설정하는 방법 (0) | 2022.12.13 |
---|---|
v-if와 v-show의 차이점과 사용 방법 (0) | 2022.11.23 |
구글 애널리틱스 적용하기 1편(vue-gtag) (0) | 2022.10.20 |
Vue 초기 세팅 (0) | 2021.08.08 |
댓글