Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kenmori/efa54f261e090bf36a89b6feeeb6d4a1 to your computer and use it in GitHub Desktop.
Save kenmori/efa54f261e090bf36a89b6feeeb6d4a1 to your computer and use it in GitHub Desktop.
Function to generate and download PDF as it is by converting components into images once with react

Function to generate and download PDF as it is by converting components into images once with react

Overview

  • reactでコンポーネントを一回画像にしてそのままPDF生成してダウンロードする機能
  • react-pdfは使わない
  • コンポーネントを画像にしてその画像をpdfとして出力する方法

author Twitter

いろいろ検索してようやく実装した機能。 誰かのためになるのではと思い共有

コンテンツをラップするコンポーネントを作成

import * as React from 'react'
import Button from '@atoms/Button'

function WithPDFAbleContent({ children, elementId, onClick }){
  return (
    <>
      <Button onClick={() => onClick()}>PDFをダウンロードする</Button>
      <div id={elementId}>
        { children }
      </div>
    </>
  )
}

export default WithPDFAbleContent;

ラップしたいコンポーネントがあるpage層で実装

import html2canvas from 'html2canvas'
(window as any).html2canvas = html2canvas;
// https://github.com/MrRio/jsPDF/issues/1225
import * as jsPDF from 'jspdf'
import WithPDFAbleContent from '@molecules/WithPDFAbleContent'


function SomeComponent () { // 適当
/// 実装
 onClickDownloadForPDF = (elementId: string, id: string) => () => {
    const input = document.getElementById(elementId); // idを走査する
    html2canvas(input, { scale: 2.5 }).then(canvas => {
      const imgData = canvas.toDataURL('image/svg', 1.0); // 一度svgにする。pngでもjpegでもok
      let pdf = new jsPDF(); // pdfを生成
      pdf.addImage(imgData, 'SVG', 5, 10, canvas.width / 18, canvas.height / 18); // ここが大変だった
      pdf.save(`${id}.pdf`); // ダウンロードが開始される // 実際はuserを受け取り名前.pdfにしてあげている
    })
  }
}

使いたいところで

<WithPDFAbleContent elementId="sheet" onClick={this.onClickDownloadForPDF("sheet", "1")} >
  <SomeComponent />
</WithPDFAbleContent>

PDFに描画したくないcomponentがある場合

childrenの中のどこかでこれは出力したくないなと思うところがあるかもしれない。 例えばボタンとか、ナビゲーションとか。 そのような無視したいコンポーネントに data-html2canvas-ignore="trueを付与してあげればいい

<IgnoreComponent data-html2canvas-ignore="true">

TODO

  • ページをまたがる高さがあるコンポーネントの場合未実装

author Twitter

ref

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment