Web/javascript
[javascript] 웹페이지 잘리지 않게 PDF 파일로 만들기
Try&Catch
2020. 3. 21. 17:09
먼저 준비물
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bluebird/3.7.2/bluebird.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.5.3/jspdf.min.js"></script>
<script src="https://unpkg.com/html2canvas@1.0.0-rc.5/dist/html2canvas.js"></script>
bluebird는 익스플로러에서 작동하게 하려면 꼭 필요하다.
jspdf는 pdf 생성해주는 라이브러리,
html2canvas는 html 페이지를 이미지로 만들어주는 라이브러리이다.
주의사항
html2canvas는 html페이지와 같은 도메인에 올라가 있는 이미지만 불러올 수 있는 것 같다.
외부 cdn 이미지를 이용하면 출력되지 않는다.
(https://stackoverflow.com/questions/31509227/html2canvas-not-rendering-cdn-images)
pixabay에 있는 이미지 주소로 이미지를 넣고 실행하니까 전혀 나오지 않아서 찾아보니 이런 내용이 있다.
그래서 따로 호스팅을 파서 같이 올리니 실행이 됨.
데모
http://gyl13.dothome.co.kr/demo/createPdf.html
상단의 PDF 만들기 버튼을 누르면 PDF 파일이 다운로드된다.
var renderedImg = new Array;
var contWidth = 200, // 너비(mm) (a4에 맞춤)
padding = 5; //상하좌우 여백(mm)
function createPdf() { //이미지를 pdf로 만들기
document.getElementById("loader").style.display = "block"; //로딩 시작
var lists = document.querySelectorAll("ul.pdfArea > li"),
deferreds = [],
doc = new jsPDF("p", "mm", "a4"),
listsLeng = lists.length;
for (var i = 0; i < listsLeng; i++) { // li 개수만큼 이미지 생성
var deferred = $.Deferred();
deferreds.push(deferred.promise());
generateCanvas(i, doc, deferred, lists[i]);
}
$.when.apply($, deferreds).then(function () { // 이미지 렌더링이 끝난 후
var sorted = renderedImg.sort(function(a,b){return a.num < b.num ? -1 : 1;}), // 순서대로 정렬
curHeight = padding, //위 여백 (이미지가 들어가기 시작할 y축)
sortedLeng = sorted.length;
for (var i = 0; i < sortedLeng; i++) {
var sortedHeight = sorted[i].height, //이미지 높이
sortedImage = sorted[i].image; //이미지
if( curHeight + sortedHeight > 297 - padding * 2 ){ // a4 높이에 맞게 남은 공간이 이미지높이보다 작을 경우 페이지 추가
doc.addPage(); // 페이지를 추가함
curHeight = padding; // 이미지가 들어갈 y축을 초기 여백값으로 초기화
doc.addImage(sortedImage, 'jpeg', padding , curHeight, contWidth, sortedHeight); //이미지 넣기
curHeight += sortedHeight; // y축 = 여백 + 새로 들어간 이미지 높이
} else { // 페이지에 남은 공간보다 이미지가 작으면 페이지 추가하지 않음
doc.addImage(sortedImage, 'jpeg', padding , curHeight, contWidth, sortedHeight); //이미지 넣기
curHeight += sortedHeight; // y축 = 기존y축 + 새로들어간 이미지 높이
}
}
doc.save('pdf_test.pdf'); //pdf 저장
document.getElementById("loader").style.display = "none"; //로딩 끝
curHeight = padding; //y축 초기화
renderedImg = new Array; //이미지 배열 초기화
});
}
function generateCanvas(i, doc, deferred, curList){ //페이지를 이미지로 만들기
var pdfWidth = $(curList).outerWidth() * 0.2645, //px -> mm로 변환
pdfHeight = $(curList).outerHeight() * 0.2645,
heightCalc = contWidth * pdfHeight / pdfWidth; //비율에 맞게 높이 조절
html2canvas( curList ).then(
function (canvas) {
var img = canvas.toDataURL('image/jpeg', 1.0); //이미지 형식 지정
renderedImg.push({num:i, image:img, height:heightCalc}); //renderedImg 배열에 이미지 데이터 저장(뒤죽박죽 방지)
deferred.resolve(); //결과 보내기
}
);
}
pdf 파일 안의 이미지 순서가 뒤죽박죽이라
따로 배열을 만들어서 순서대로 다시 배열하는 부분을 넣어야 했다.
html2canvas 관련 내용을 찾다 보면 onrendered가 들어간 코드들이 많이 보이는데,
개발자가 이 부분을 수정해서 더이상 사용이 안 된다.
html2canvas().then() 으로 해야 함.