reactで埋め込みPDFのonScrollを実装している中躓いたためまとめます。
新しいプロジェクトを作成し、実際に作りながら振り返ります。
<環境>
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-pdf": "^6.0.0-beta.3",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
PDFを埋め込む
react-pdfライブラリを下記コマンドでインストールする。
npm install react-pdf --save
表示するための記述を書く
import {Document, Page,pdfjs} from 'react-pdf'
import {useState} from 'react'
import samplePDF from './pdf/sample.pdf'
pdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.js`;
function App() {
const [numPages, setNumPages] = useState(null);
function onDocumentLoadSuccess({ numPages }) {
setNumPages(numPages);
}
return (
<div className='react-pdf'>
<h1 style={{textAlign:"center"}}>pdf表示</h1>
<p style={{textAlign:"center"}}>PDFを最後までスクロールすることによりチェックボックスが活性化されます・</p>
<div className='pdf' style={{width:"80%",margin:"0 auto", height:400,overflow:"scroll"}}>
<Document
file={samplePDF}
onLoadSuccess={onDocumentLoadSuccess}>
{Array.from(
new Array(numPages),
(el, index) => (
<Page
key={`page_${index + 1}`}
pageNumber={index + 1}
/>
),
)}
</Document>
</div>
</div>
);
}
export default App;
※以下の記述を書かないと、表示する際に「Failed to load PDF file.」というエラーが発生してしまうと思います。
pdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.js`;
<Document>のfileプロパティには表示したいPDFのパスを書きます。base64にエンコードされたPDFも以下のように記述することで表示できるはずです。
<Document
file="data:application/pdf;base64, 'base64エンコードデータ'"
onLoadSuccess={onDocumentLoadSuccess}>
<Document>のonLoadSuccessプロパティは、PDF ファイルの読み込みに成功した時に実行されページ数を取ってくることが可能になります。
その他react-pdfの使い方に関しては以下を参考になります。
https://github.com/wojtekmaj/react-pdf/wiki
react-pdf gitHubページ
これでPDFが表示されます。
※PDFの埋め込みは他にもhtml5のiframe,object,embedタグで行うことができますが、これらを用いる場合だと高さの取得ができませんでした。
最後までスクロールされた場合、チェックボックスを活性化
全体のコード
import {Document, Page,pdfjs} from 'react-pdf'
import {useState} from 'react'
import samplePDF from './pdf/sample.pdf'
pdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.js`;
function App() {
const [numPages, setNumPages] = useState(null);
const [checkFlg, setCheckFlg] = useState(false)
function onDocumentLoadSuccess({ numPages }) {
setNumPages(numPages);
}
const handleScroll = (event) =>{
if (event.target.scrollTop > event.currentTarget.children[0].clientHeight -400){
//event.target.scrollTop→どのくらいスクロールされたか
//event.currentTarget.children[0].clientHeight→react-pdfで生成される要素の高さ。 400→元々の高さ。
setCheckFlg(true)
}
}
return (
<>
<div className='react-pdf'>
<h1 style={{textAlign:"center"}}>pdf表示</h1>
<p style={{textAlign:"center"}}>PDFを最後までスクロールすることによりチェックボックスが活性化されます・</p>
<div className='pdf' style={{width:"80%",margin:"0 auto", height:400,overflow:"scroll"}} onScroll={handleScroll}>
<Document
file={samplePDF}
onLoadSuccess={onDocumentLoadSuccess}>
{Array.from(
new Array(numPages),
(el, index) => (
<Page
key={`page_${index + 1}`}
pageNumber={index + 1}
/>
),
)}
</Document>
</div>
</div>
<div style={{textAlign:"center"}}>
<span>ボタン</span>
{checkFlg? <input id='check' type="checkbox"/>: <input id='check' type="checkbox" disabled/>}
</div>
</>
);
}
export default App;
スクロールされたときにonScrollイベントを発生させ、最後までスクロールされた場合にcheckFlgをtrueにしてその値をstateで保持することによって、チェックボックスを活性しました。
チェックボックスの活性・非活性が分かりづらいと思いますが、できたものの画像を載せます。
この記事が見ていただいた方の役に立てれば幸いです。
コメント