こんにちは。エンジニアの砂町です。
本日はreactで、PDFを埋め込んで表示する方法についてです。
今回は以下の2種類の方法と挙動の違いについてお話しします。
- Google Docs Viewer
- react-pdf
※今回ブラウザの環境は、前回までご紹介していたLIFFブラウザ(iOSとAndroid)でのお話になります。今からお話しする問題点は、Chromeなどのブラウザ環境では起きない場合もあります。
▶LaravelでLINE Message API使ってみた
▶ReactでLIFF(LINE Login)使ってみた
実装したい機能概要
今回実装したいPDFの表示方法は、
- LIFFアプリなのでiOS、Androidへの使用が可能
- 複数ページに跨るのPDFを縦長のスクロールで表示
- ピッチイン・ピッチアウトでの拡大・縮小が可能
といった要件です。
Google Docs Viewer
まずは下記の実装例をご覧ください。
export const testComponent = () => {
const encodeUrl = '表示したいPDFのURLをエンコードしたもの';
const url = `https://docs.google.com/viewer?url=${encodeUrl}&embedded=true`;
return(
<iframe width="100%" height="100%" src={url} ></iframe>
)
}
まず表示したいPDFのURLをエンコードして、Google Docs Viewerのurlのパラメータに渡してあげます。
高さと横幅を指定した「iframe」でにこのURLを指定したら表示可能です。
Google Docs ViewerではPDFのURLを指定すると、Google Docs Viewer側でPDFを自動で縦長表示してくれます。
またピッチイン・ピッチアウトによる拡大・縮小の制御も自動で行ってくれます。
問題点としては画面が白くなったまま、うまく表示できない時があるということです。
react-pdf
下記の実装例をご覧ください。
export const testComponent = () => {
const [totalPages, setTotalPages] = useState(0);
const onLoadSuccess = ({numPages})=>{
setTotalPages(numPages);
}
/**
* 1ページずつ表示する
*/
const pdfContents = [];
for(let i=0; i<totalPages; i++){
const d = (
<Page key={i}
pageNumber={i+1}
width={300}
/>
);
pdfContents.push(d);
}
return (
<div style={{
width: "100%",
height: "100%",
overflow: 'scroll',
paddingTop: '32px'
}}>
<Document
file='PDFのURL'
onLoadSuccess={onLoadSuccess}
>
{pdfContents}
</Document>
</div>
);
}
react-pdf はURLを指定しただけでは、Google Docs Viewerのように縦長スクロール表示はできません。
そのため全体のページを取得して、ループさせて縦に並べています。
またピッチイン・ピッチアウトでの拡大・縮小はこの実装ではできません。
react-zoom-pan-pinchというライブラリを用いることで可能ですが、その場合縦長のスクロールと併用させることはうまく動作しませんでした。
ページネーションなどを用いて1枚ずつPDFを表示すればピッチイン・ピッチアウトでの拡大・縮小を行うことが可能です。
まとめ
PDF周りを色々調べてみたのですが、なかなか思ったような動きをするのが難しいなと思いました。
今回はスマホでの使用が前提だったので、最初の想定より考慮する点が多くなりました。
もっとスマートな実装方法がありましたらぜひ教えてください!
