작업 전.. html2canvas 및 jspdf 라이브러리에 대한 설명..
우선 2개의 라이브러리를 대충 설명하면
html2canvas : DOM을 기반으로 하여 전체 또는 특정 영역의 스크린샷을 생성하는 라이브러리
jsPDF : javascript로 PDF를 생성해주는 라이브러리
대충 위와 같은 기능을 제공하는 라이브러리인 것만 인지하고 아래 그림을 보도록 하자.
우리가 작성한 HTML을 PDF로 변환하는 과정은 위와 같다.
보통 인쇄 기능을 구현하거나, PDF로 변환할 때 사용자가 원하는 엘리먼트를 잡고
body를 변경해주거나, 직접 파라메터로 HTML 엘리먼트를 넣어주는데
여기서는 HTML 엘리먼트를 우선 이미지로 변환한 뒤, PDF로 변환해준다. ( 물론 인쇄도 된다. )
대충 이해 했으면 이제 설치 및 샘플코드를 보도록 하자.
html2canvas 및 jspdf 설치
npm 설치 명령어와 cdn링크를 달아놨으니, 각자 개발환경에 맞는 걸 갖다 쓰도록 하자.
html2canvas 설치 npm 명령어
npm i html2canvas
html2canvas CDN 링크
https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js
jspdf 설치 npm 명령어
npm i jspdf
jspdf CDN 링크
https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js
샘플코드
<template>
<div id="modalSheet" class="modal modal-sheet position-static d-block bg-secondary py-5" tabindex="-1"
role="dialog">
<div class="modal-dialog" role="document">
<div id="print-content" class="modal-content rounded-6 shadow">
<div class="modal-header border-bottom-0">
<h5 class="modal-title"><input :value="msg" /></h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body py-0">
<p>This is a modal sheet, a variation of the modal that docs itself to the bottom of the viewport
like the
newer share sheets in iOS.</p>
</div>
<div class="modal-footer flex-column border-top-0">
<button type="button" class="btn btn-lg btn-primary w-100 mx-0 mb-2" @click="showPrint()">인쇄
미리보기</button>
<button type="button" class="btn btn-lg btn-light w-100 mx-0" data-bs-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</template>
<script>
import 'bootstrap/dist/css/bootstrap.min.css'
import 'bootstrap'
import html2canvas from 'html2canvas'
import { jsPDF } from 'jspdf'
export default {
name: 'PrintComponent',
props: {
msg: String
},
methods: {
showPrint() {
html2canvas(document.querySelector('#print-content'), {
//allowTaint: true, // cross-origin allow
//useCORS: true, // CORS 사용한 서버로부터 이미지 로드할 것인지 여부
scale: 10 // 기본 96dpi에서 해상도를 두 배로 증가
}).then(function (canvas) {
// 캔버스를 이미지로 변환
let imgData = canvas.toDataURL('image/png')
let imgWidth = 120 // 이미지 가로 길이(mm)
let pageHeight = imgWidth * 1.414 // 출력 페이지 세로 길이
let imgHeight = canvas.height * imgWidth / canvas.width
let heightLeft = imgHeight
let margin = 45 // 출력 페이지 여백설정
let doc = new jsPDF('p', 'mm')
let position = 10
window.scrollTo(0, 0)
//첫 페이지 출력
doc.addImage(imgData, 'PNG', margin, position, imgWidth, imgHeight)
heightLeft -= pageHeight
//한 페이지 이상일 경우 루프 돌면서 출력
while (heightLeft >= 20) {
position = heightLeft - imgHeight
position = position - 20
doc.addPage()
doc.addImage(imgData, 'PNG', margin, position, imgWidth, imgHeight)
heightLeft -= pageHeight
}
// PDF를 새탭으로 열기
window.open(doc.output('bloburl'))
// PDF를 바로 다운로드
// doc.save('sample.pdf');
})
},
}
}
</script>
결과화면
실제 위 코드로 구현한 화면이다. (나는 Vue를 기반으로 했다.. 필요한 사람들은
showPrint함수만 따로 빼서 javascript에 함수를 만들어 사용하도록 하자..
위 화면에서 "인쇄 미리보기" 버튼을 클릭 할 경우 새탭이 열리며 PDF 미리보기가 된다.
다운로드 및 인쇄 가능..
만약 미리보기가 필요 없고, 바로 PDF파일을 다운로드 받고 싶다면
doc.svae() 부분을 주석해제 하여 사용하면 된다. 끝
'FrontEnd > JavaScript' 카테고리의 다른 글
[JS] import() 방식과 import ...from 방식의 차이점에 대한 이야기 :(feat. import시 undefined가 뜨는 현상) (0) | 2023.11.24 |
---|---|
[JS] ES6에서 import를 했는데 undefined값을 읽는 문제에 관한 이야기 (0) | 2023.11.23 |
[JS] Vue 컴포넌트의 내용을 인쇄하는 기능을 구현하며 생겼던 문제와 원인에 대한 정리 (0) | 2023.11.11 |
[JS] window.print()를 이용해서 특정영역을 인쇄하는 기능을 구현하는 방법 (0) | 2023.11.11 |
[JS] 자바스크립트의 콜백(Callback)함수에 대한 개념 및 샘플코드를 통해 이해해보자. (1) | 2023.05.21 |