[React] 스크린샷 + pdf w/typescript

Darcy Daeseok YU ·2023년 5월 29일
0

특정 영역 스크린샷해서 pdf 파일로 다운로드

플로우

areaTobeCaptured:HTMLElement 를
canvas = html2canvas(areaToBeCaptured)를 통해서 이미지 캔버스 컴포넌트를 생성
imgDataURL = canvas.toDataURL("image/png) canvas에서 dataURL을 생성

생성된 image dataURL을 string타입을

const pdfDoc = new jsPDF("p", "mm", "a4");

const pdfA4SizeW = pdfDoc.internal.pageSize.getWidth();
const pdfA4SizeH = pdfDoc.interanl.pageSize.getHeight();

pdfDoc.addImage(imgDataURL, "JPEG", 0,0,pdfA4SizeW, pdfA4SizeH)

// 로컬 드라이브에 세이브
pdfDoc.save("파일명.pdf")

// 새로운 파일만들지만 세이브는 아직
const pdfFile = new File(
pdfDoc.output("blob"),
"파일명.pdf",
{type: "application/pdf"}
)

window.open(pdfDoc.output("bloburl") // 새로운 브라우저 탭에서 표시



/**
 * 이미지 파일 데이터를 pdf에 담고 저장
 * @param fieName : 파일명
 * @param imageData : 이미지파일 데이터
 */
export async function makePDFWithImage(fieName: string, htmlTag: HTMLElement) {
  // convert html to canvas then get dataUrl of image
  const imageData = await getImgDataUrlFromHTML2Canvas(htmlTag);

  const imgOriginWidthmm = htmlTag.clientWidth * 0.2646; // px to mm
  const imgOriginHeightmm = htmlTag.clientHeight * 0.2646; // px to mm

  // pdf 생성 ('landscape' || 'portrait')
  const pdfDoc = new jsPDF(imgOriginWidthmm > imgOriginHeightmm ? 'landscape' : 'portrait', 'mm', 'a4');
  const pdfDocA4Widthmm = pdfDoc.internal.pageSize.getWidth();
  const pdfDocA4Heightmm = pdfDoc.internal.pageSize.getHeight();

  let imgSizeWidth = 0;
  let imgSizeHeight = 0;
  imgSizeWidth = pdfDocA4Widthmm - 10 * 2;
  imgSizeHeight = imgSizeWidth * (imgOriginHeightmm / imgOriginWidthmm);
  imgSizeHeight = imgSizeHeight > pdfDocA4Heightmm ? pdfDocA4Heightmm - 20 * 2 : imgSizeHeight;
  pdfDoc.addImage(imageData, 'PNG', 10, 20, imgSizeWidth, imgSizeHeight);
  pdfDoc.save(`${fieName}.pdf`);
}

/**
 * html 태그 영역을 이미지파일로 생성 후 해당 dataUrl 스트링 반환
 * @param htmlTag 캡쳐 영역의 html tag
 * @returns
 */
export async function getImgDataUrlFromHTML2Canvas(htmlTag: HTMLElement) {
  const canvas = await html2canvas(htmlTag);
  const imgDataUrl = canvas.toDataURL('image/png', 1);
  return imgDataUrl;
}

이 로직에서 px to mm 는 큰 영향 없어 보임

profile
React, React-Native https://darcyu83.netlify.app/

0개의 댓글