はじめに (対象読者・この記事でわかること)
この記事は、WebサイトでPDF資料を表示し、ユーザーが特定のページに直接アクセスできるようにしたいと考えているWeb開発者を対象としています。特に、長いドキュメントやマニュアルを提供する際に、ユーザビリティを向上させるための技術的な実装方法に興味がある方に最適です。
本記事を読むことで、HTML内でPDFを表示する基本的な方法と、JavaScriptを用いてPDF内の特定のページにリンクで直接遷移する実装方法を習得できます。具体的なコード例とその解説を通じて、すぐに実践できるテクニックを学べます。これにより、ユーザーがPDF全体をダウンロードせずに必要な情報に素早くアクセスできるWebサイトを構築できるようになります。
前提知識
この記事を読み進める上で、以下の知識があるとスムーズです。 - HTML/CSSの基本的な知識 - JavaScriptの基本的な知識 - PDFファイルの基本的な理解
PDF表示の基本とページ遷移の必要性
ウェブサイトで資料やマニュアルをPDF形式で提供するケースは非常に多いですが、ユーザーがPDF全体をダウンロードせずに、ウェブページ上で直接閲覧したいというニーズも増えています。特に、長いドキュメントの場合、特定のページに直接アクセスできるとユーザビリティが大幅に向上します。
しかし、PDFをHTML内で表示し、リンクで特定のページに遷移するには、いくつかの技術的な課題があります。一般的なPDFビューアーでは、ページ間の移動に専用のインターフェースが必要ですが、これをHTMLのリンクから直接制御するにはJavaScriptを活用する必要があります。
本記事では、iframeタグとPDF.jsを活用した2つのPDF表示方法と、それぞれの方法でページ遷移を実現する具体的な実装方法について解説します。これにより、ユーザーはより直感的にPDF内の必要な情報にアクセスできるようになります。
具体的な実装方法
方法1:iframeタグを利用したシンプルな実装
最もシンプルな方法として、HTMLのiframeタグを利用してPDFを表示する方法があります。この方法では、PDF.jsのような外部ライブラリを必要とせず、基本的なHTMLだけで実装できます。
まず、HTMLにiframeタグを追加します:
Html<div class="pdf-container"> <iframe id="pdf-frame" src="path/to/your/document.pdf" width="100%" height="600px"></iframe> </div>
次に、特定のページにリンクするためのHTMLを追加します:
Html<div class="navigation-links"> <a href="#" data-target="3" data-pdf="path/to/your/document.pdf">第3章へ移動</a> <a href="#" data-target="7" data-pdf="path/to/your/document.pdf">第7章へ移動</a> </div>
最後に、JavaScriptでリンクのクリックイベントを処理し、PDFの特定のページに遷移するようにします:
Javascriptdocument.querySelectorAll('.navigation-links a').forEach(link => { link.addEventListener('click', function(e) { e.preventDefault(); const targetPage = this.getAttribute('data-target'); const pdfPath = this.getAttribute('data-pdf'); const pdfFrame = document.getElementById('pdf-frame'); // PDFのURLにページフラグメントを追加 const newSrc = `${pdfPath}#page=${targetPage}`; pdfFrame.src = newSrc; // フレームがロードされるまで少し待つ setTimeout(() => { pdfFrame.contentWindow.location.reload(); }, 100); }); });
この方法の利点は実装が非常に簡単であることですが、ブラウザやPDFビューアーによってはページフラグメント(#page=N)が正しく機能しない場合があります。その場合は、次に紹介するPDF.jsを利用した方法がより確実です。
方法2:PDF.jsを利用した高度な実装
PDF.jsはMozillaが開発したJavaScriptライブラリで、PDFをHTML5 Canvas上でレンダリングできます。これにより、より高度な制御が可能になり、ページ指定の機能も確実に実装できます。
まず、PDF.jsをプロジェクトに追加します。CDNを利用する場合は、以下のように記述します:
Html<script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.min.js"></script> <script> // PDF.jsのワーカーを設定 pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.worker.min.js'; </script>
次に、PDFを表示するためのHTMLとJavaScriptを記述します:
Html<div class="pdf-viewer"> <canvas id="pdf-canvas"></canvas> <div class="pdf-controls"> <button id="prev-page">前のページ</button> <span id="page-num">ページ 1 / 1</span> <button id="next-page">次のページ</button> </div> <div class="navigation-links"> <a href="#" data-page="3">第3章へ移動</a> <a href="#" data-page="7">第7章へ移動</a> </div> </div>
Javascript// PDFファイルのパス const url = 'path/to/your/document.pdf'; // PDF.jsを使ってPDFを表示 let pdfDoc = null; let pageNum = 1; let pageRendering = false; let pageNumPending = null; const scale = 1.5; const canvas = document.getElementById('pdf-canvas'); const ctx = canvas.getContext('2d'); // PDFをロード pdfjsLib.getDocument(url).promise.then(function(pdf) { pdfDoc = pdf; document.getElementById('page-num').textContent = `ページ ${pageNum} / ${pdf.numPages}`; // 最初のページを表示 renderPage(pageNum); }); // ページをレンダリングする関数 function renderPage(num) { pageRendering = true; pdfDoc.getPage(num).then(function(page) { const viewport = page.getViewport({scale: scale}); canvas.height = viewport.height; canvas.width = viewport.width; const renderContext = { canvasContext: ctx, viewport: viewport }; const renderTask = page.render(renderContext); // レンダリングが完了したら renderTask.promise.then(function() { pageRendering = false; if (pageNumPending !== null) { // ページが保留されていたら、それをレンダリング renderPage(pageNumPending); pageNumPending = null; } }); }); // ページ番号を更新 document.getElementById('page-num').textContent = `ページ ${num} / ${pdfDoc.numPages}`; } // 次のページを表示 function queueRenderPage(num) { if (pageRendering) { pageNumPending = num; } else { renderPage(num); } } // 前のページボタンのイベントリスナー document.getElementById('prev-page').addEventListener('click', function() { if (pageNum <= 1) { return; } pageNum--; queueRenderPage(pageNum); }); // 次のページボタンのイベントリスナー document.getElementById('next-page').addEventListener('click', function() { if (pageNum >= pdfDoc.numPages) { return; } pageNum++; queueRenderPage(pageNum); }); // ページ移動リンクのイベントリスナー document.querySelectorAll('.navigation-links a').forEach(function(link) { link.addEventListener('click', function(e) { e.preventDefault(); const targetPage = parseInt(this.getAttribute('data-page')); if (targetPage >= 1 && targetPage <= pdfDoc.numPages) { pageNum = targetPage; queueRenderPage(pageNum); } }); });
さらに、URLパラメータを使ってページを指定する方法も実装できます。これにより、ブックマークや共有が容易になります:
Javascript// URLパラメータからページ番号を取得 function getQueryParam(param) { const urlParams = new URLSearchParams(window.location.search); return urlParams.get(param); } // ページ番号のパラメータがあれば、そのページを表示 const pageParam = getQueryParam('page'); if (pageParam && pdfDoc) { pageNum = parseInt(pageParam); if (pageNum >= 1 && pageNum <= pdfDoc.numPages) { queueRenderPage(pageNum); } }
この方法では、URLに?page=3のようなパラメータを追加することで、特定のページを直接表示できます。これにより、ユーザーはドキュメントの特定のセクションへのリンクを簡単に共有できます。
ハマった点やエラー解決
問題1:PDF.jsが正しく読み込まれない
PDF.jsを正しく読み込む際に、ワーカーファイルのパスが正しく設定されていないと、以下のようなエラーが発生します:
Uncaught (in promise) Error: Worker failed to construct. Check the console for detailed information.
解決策: ワーカーファイルのパスが正しいことを確認します。PDF.jsのバージョンが一致しているかも確認してください:
Javascript// PDF.jsのバージョンに合わせてワーカーファイルのパスを設定 pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.worker.min.js';
問題2:PDFのページ番号が0から始まるのに1から始まっていると思っている
JavaScriptでは配列のインデックスが0から始まりますが、PDFのページ番号は1から始まります。この違いにより、ページ指定の際に混乱することがあります。
解決策: PDFのページ番号は1から始まることを念頭に置き、コードを記述します:
Javascript// ページ番号は1から始まる const targetPage = parseInt(this.getAttribute('data-page')); if (targetPage >= 1 && targetPage <= pdfDoc.numPages) { pageNum = targetPage; queueRenderPage(pageNum); }
問題3:モバイルデバイスでのPDF表示がうまくいかない
モバイルデバイスでは、PDFの表示がうまくいかない場合があります。特に、ピンチイン・アウトによる拡大縮小が機能しないことがあります。
解決策: viewportの設定を調整し、CSSで適切なスタイルを適用します:
Html<meta name="viewport" content="width=device-width, initial-scale=1.0"> <style> .pdf-viewer { max-width: 100%; overflow-x: auto; } #pdf-canvas { max-width: 100%; height: auto; } .pdf-controls { display: flex; justify-content: center; align-items: center; margin: 10px 0; } .navigation-links { margin-top: 10px; } .navigation-links a { margin-right: 10px; text-decoration: none; color: #0066cc; } </style>
まとめ
本記事では、HTML内でPDFを表示し、リンクを使って特定のページに直接遷移する方法について解説しました。具体的には、iframeタグとPDF.jsを利用した2つの表示方法と、JavaScriptを使ったページ制御の実装方法を紹介しました。
- iframeタグを利用した方法は実装が簡単ですが、ブラウザやPDFビューアーによってはページフラグメントが正しく機能しない場合があります。
- PDF.jsを利用した方法はより高度な制御が可能で、ページ指定の機能も確実に実装できます。また、URLパラメータを使ったページ指定も実装できます。
この記事で紹介した技術を活用することで、ユーザーがより直感的にPDF内の必要な情報にアクセスできるWebサイトを構築できるようになります。特に、長いドキュメントやマニュアルを提供する際に、ユーザビリティを大幅に向上させることができます。
今後は、PDFの検索機能の実装や、アノテーション機能の追加など、さらに高度な機能についても記事にする予定です。
参考資料