個人サイト制作:サイトマップへ戻る

PDFをWebサイトに掲載する際の工夫

ウェブサイトでPDFを掲載する際、ユーザーエクスペリエンスを向上させ、PDFの利用がスムーズになるようにしたいものです。
サイトの目的やユーザーのニーズに合わせて微調整できるとさらにいいですね。

フェードアウト効果の草花写真
明確なリンクテキスト
PDFへのリンクをわかりやすくするために、リンクテキストを明確にしましょう。
例えば、「PDFダウンロード」ではなく、「製品マニュアル(PDF)」や「会議議事録(PDF)」など、リンク先の内容を具体的に示すと良いです。
プレビュー機能
これは当サイトで力を入れている部分です。
いちいちPDFビューワーに飛ばされてたらたまらないからね。
PDFのプレビュー機能を提供することで、ユーザーが内容を確認してからダウンロードするかどうかを判断できます。
プレビュー機能は、GoogleドライブやPDF.jsなどのライブラリを使用して実装することができます。
ファイルサイズの表示
PDFのファイルサイズを表示することで、ユーザーがダウンロードに必要な時間を把握できるようにします。
これは特に大きなファイルで重要なんですが、当サイトの場合はプレビュー機能を充実させることで、細かい記載を避けています。
モバイル対応
PDFのリンクや表示がモバイルデバイスでも快適に利用できるようにします。
レスポンシブデザインを採用し、モバイルユーザーにとって使いやすい配置やサイズに調整します。

このページに関する注意事項

当Webサイト作成者は、例示を目的としてマークアップ及びプログラミング例を提供しており、明示または黙示にかかわらず、いかなる責任も負わないものとします。
このページは、説明されているマークアップ及びプログラミング言語、手順を作成およびデバッグするために使用される各種ツールに読者が精通していることを前提にしています。
このページは、特定の機能を説明するのに役立つ可能性がありますが、当Webサイト作成者がこれらの例を変更した上で、特定の要件を満たすために追加の機能を提供したり、システムを構築したりすることはできません。
加えて、この例の手順に従う場合は、読者の各種ファイルを事前にバックアップすることを推奨いたします。

PDFのプレビュー表示

ここは手強いですよ。
まずはhtmlから行きます。
全体を通して、このHTMLはPDFを表示し、ページを操作するための基本的な構造を持っています。

デフォルトでPDFをプレビュー表示するhtml


<!--head内部のCSS-->
    <link rel="stylesheet" type="text/css" href="css/pdf.css">
<!--head内部のJavaScript-->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.6.347/pdf.min.js"></script>
    <script src="script/pdf.js" defer></script>

<!--body内部のhtml-->
 <div class="feinpdf-container">
  <div id="feinpdf-viewer"></div>
   <div class="feinpdfcontrols">
    <button id="prev-page">前のページへ</button>
    <span>Page: <span id="page-num"></span> / <span id="page-count"></span></span>
    <button id="next-page">次のページへ</button>
   </div>
 </div>

<div class="feinpdf-container">
全体を囲むコンテナで、PDFビューアの外枠にあたる部分です。
デザインやレイアウトのために使用されます。

<div id="feinpdf-viewer"></div>
ここにPDFが表示されます。
この部分は空ですが、JavaScriptを使ってPDFを表示します。

<div class="feinpdfcontrols">
PDFを操作するためのボタンとページ情報を囲むコンテナです。
ボタンの配置やデザインを整えます。

<button id="prev-page">前のページへ</button>
前のページに戻るためのボタンです。
クリックすると、JavaScriptが前のページを表示するように指示します。

<span>Page: <span id="page-num"></span> / <span id="page-count"></span></span>
現在のページ番号と総ページ数を表示します。
JavaScriptがページ番号と総ページ数を更新します。

<button id="next-page">次のページへ</button>
次のページに進むためのボタンです。
クリックすると、JavaScriptが次のページを表示するように指示します。

mozillaのPDF.js

フェードアウト効果の草花写真

link relのところにあるURLは、PDF.jsというJavaScriptライブラリの最小化されたバージョンを指しています。
PDF.jsはブラウザ上でPDFファイルを表示・解析するためのライブラリで、Mozillaが開発したプロジェクトです。
これを使うと、PDFファイルをウェブページ上で直接表示できるようになるのです。
Google Sitesでも似たようなことはできるけど、より高度なコントロールができます。
これも導入しようと思ってたんですよねー。
Mozillaは、主にFirefoxブラウザを開発していますが、PDF.jsもその一環として公開されているものです。

mozillaとはどういう団体か

Mozillaは、オープンウェブの推進とインターネットの利益を最大化することを目指す非営利団体です。
ていうか、Webを体系的に学んだ人なら誰でも知ってる団体ですよ。

Mozilla Foundation

Mozilla Foundationは、カリフォルニア州に本拠を置く非営利団体で、Mozillaのコミュニティを支援し、インターネットの利益を最大化することを目指しています。
Mozilla Foundationは、Mozillaの原則を支えるためのさまざまな組織の一部です。

Mozilla Corporation

Mozilla Corporationは、2005年に設立されたMozilla Foundationの完全子会社で、インターネット関連のアプリケーションの開発を統合・調整します。
代表的な製品には、Firefoxブラウザがあります。

Mozillaのミッション

Mozillaのミッションは、インターネットをオープンでアクセスしやすいものに保つことです。
Mozillaは、利益を最優先するのではなく、人々を優先することを目指しています。

Mozillaのビジョン

Mozillaのビジョンは、インターネットを健康で興味深く、すべての人に歓迎する場所にすることです。Mozillaは、オープンウェブの先駆者であり、インターネットの健康を守るために活動しています。
Mozillaは、オープンソースの開発者コミュニティと協力して、Firefoxをはじめとするさまざまな製品を開発しています。
Mozillaの活動は、インターネットが共有された公共資源であり続けることを目指しています。

参考サイト

PDFのプレビュー表示(CSS)

このCSSはPDFビューアのデザインとレイアウトを設定しています。
.feinpdf-containerはコンテナの幅を80%に設定し、中央に配置、ボーダーやシャドウを追加。
#feinpdf-viewerは幅を100%に設定し、高さを自動調整してスクロールバーを表示。
.feincanvasはキャンバスの幅を100%にし、高さを自動調整。
.feinpdfcontrolsはテキストを中央に配置し、余白を追加しています。
ボタンにはパディングやマージン、背景色、ボーダー、カーソル、ホバー時の色変更が設定。
@mediaクエリは画面幅が600ピクセル以下の場合のスタイルを調整しているという流れです。

これがhtml・JavaScriptと関連付いて動作しているんですよね。
やたらと「fein」という名称にしているのは、「pdf-container」といった一般名称を乱用すると、Webサイトが大規模になってきたときにCSS同士が干渉してしまう可能性があるからです。
自分で分からなくなってくるまえに、固有名詞というか、スペルを追加しています。

デフォルトでPDFをプレビュー表示するpdf.css


@charset "UTF-8";

.feinpdf-container {
    width: 80%;
    margin: auto;
    border: 1px solid #ddd;
    padding: 10px;
    border-radius: 10px;
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
    background-color: #fff;
}

#feinpdf-viewer {
    width: 100%;
    height: auto;
    overflow: auto;
    position: relative;
}

.feincanvas {
    width: 100% !important;
    height: auto !important;
    position: relative;
}

.feinpdfcontrols {
    text-align: center;
    margin-top: 10px;
}

.feinpdfcontrols button {
    padding: 5px 10px;
    margin: 0 5px;
    background-color: #007bff;
    color: white;
    border: none;
    border-radius: 5px;
    cursor: pointer;
    transition: background-color 0.3s ease;
}

.feinpdfcontrols button:hover {
    background-color: #0056b3;
}

.feinpdfcontrols span {
    font-weight: bold;
}

/* レスポンシブデザイン対応 */
@media (max-width: 600px) {
    .feinpdf-container {
        width: 100%;
        padding: 5px;
        box-sizing: border-box;
    }

    #feinpdf-viewer {
        width: 100%;
        height: auto;
        overflow: auto;
        position: relative;
    }

    .feincanvas {
        width: 100% !important;
        height: auto !important;
    }

    .feinpdfcontrols button {
        padding: 3px 6px;
        font-size: 12px;
    }
}
   

.feinpdf-container:

width: 80%;
親要素の幅に対して80%の幅を持つように設定。

margin: auto;
要素を中央に配置。

border: 1px solid #ddd;
要素の周りに薄い灰色の1ピクセルの枠線を追加。

padding: 10px;
要素の内部に10ピクセルの余白を追加。

border-radius: 10px;
要素の角を10ピクセルの半径で丸める。

box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
要素に影を追加。

background-color: #fff;
要素の背景色を白に設定。

フェードアウト効果の草花写真

#feinpdf-viewer:

width: 100%;
親要素の幅に対して100%の幅を持つように設定。

height: auto;
要素の高さを内容に応じて自動調整。

overflow: auto;
要素の内容が多い場合にスクロールバーを表示。

position: relative;
要素の位置を相対的に設定。

.feincanvas:

width: 100% !important;
幅を100%に設定し、他のスタイルを上書き。

height: auto !important;
高さを内容に応じて自動調整し、他のスタイルを上書き。

position: relative;
要素の位置を相対的に設定。

.feinpdfcontrols:

text-align: center;
要素内のテキストを中央に配置。

margin-top: 10px;
上部に10ピクセルの余白を追加。

.feinpdfcontrols button:

padding: 5px 10px;
ボタン内のテキストに対して5ピクセルの上下余白と10ピクセルの左右余白を追加。

margin: 0 5px;
左右に5ピクセルの余白を追加。

background-color: #007bff;
背景色を青に設定。

color: white;
テキストの色を白に設定。

border: none;
ボーダーを削除。

border-radius: 5px;
ボタンの角を5ピクセルの半径で丸める。

cursor: pointer;
ボタン上にカーソルが来たときにポインターを表示。

transition: background-color 0.3s ease;
背景色の変化を0.3秒かけて滑らかにする。

.feinpdfcontrols button:hover:

background-color: #0056b3;
ボタンにマウスオーバーしたときに背景色を濃い青に変更。

.feinpdfcontrols span:

font-weight: bold;
テキストを太字に設定。

@media (max-width: 600px);
画面の幅が600ピクセル以下の場合に適用するスタイル。

.feinpdf-container:

width: 100%;
親要素の幅に対して100%の幅を持つように設定。

padding: 5px;
要素の内部に5ピクセルの余白を追加。

box-sizing: border-box;
ボーダーとパディングを含めて要素のサイズを計算。

#feinpdf-viewer:

width: 100%;
親要素の幅に対して100%の幅を持つように設定。

height: auto;
要素の高さを内容に応じて自動調整。

overflow: auto;
要素の内容が多い場合にスクロールバーを表示。

position: relative;
要素の位置を相対的に設定。

.feincanvas:

width: 100% !important;
幅を100%に設定し、他のスタイルを上書き。

height: auto !important;
高さを内容に応じて自動調整し、他のスタイルを上書き。

.feinpdfcontrols button:

padding: 3px 6px;
ボタン内のテキストに対して3ピクセルの上下余白と6ピクセルの左右余白を追加。

font-size: 12px;
フォントサイズを12ピクセルに設定。

PDFのプレビュー表示(JavaScript)

これどうしようかな…
思い切ってコメントアウトのみにしてみましょうか!

デフォルトでPDFをプレビュー表示するpdf.js


// PDF.jsの設定
const url = '../another-eden/fein_report/grasta.pdf'; // PDFファイルのURLを設定
const pdfjsLib = window['pdfjs-dist/build/pdf']; // PDF.jsライブラリを読み込む
pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.6.347/pdf.worker.min.js'; // ワーカーのURLを設定

let pdfDoc = null,    // PDFドキュメントのオブジェクト
    pageNum = 1,     // 現在のページ番号
    pageRendering = false, // ページがレンダリング中かどうかのフラグ
    pageNumPending = null, // 保留中のページ番号
    feincanvas = document.createElement('canvas'), // キャンバス要素を作成
    ctx = feincanvas.getContext('2d'); // キャンバスの2Dコンテキストを取得

// キャンバスをPDFビューアのコンテナに追加
document.getElementById('feinpdf-viewer').appendChild(feincanvas);

// PDFをレンダリングする関数
function renderPage(num) {
    pageRendering = true;
    pdfDoc.getPage(num).then(page => {
        const containerWidth = document.getElementById('feinpdf-viewer').clientWidth; // ビューアの幅を取得
        const viewport = page.getViewport({ scale: 1 }); // ページのビューポートを取得
        const scale = containerWidth / viewport.width; // スケールを計算
        const scaledViewport = page.getViewport({ scale: scale }); // スケールを適用したビューポートを取得

        feincanvas.height = scaledViewport.height; // キャンバスの高さを設定
        feincanvas.width = scaledViewport.width; // キャンバスの幅を設定

        const renderContext = {
            canvasContext: ctx,
            viewport: scaledViewport
        }; // レンダリングコンテキストを設定

        const renderTask = page.render(renderContext); // ページをレンダリング

        renderTask.promise.then(() => {
            pageRendering = false; // レンダリングが終了
            if (pageNumPending !== null) {
                renderPage(pageNumPending); // 保留中のページをレンダリング
                pageNumPending = null;
            }
        });
    });

    document.getElementById('page-num').textContent = num; // 現在のページ番号を表示
}

// 次のページをレンダリングする関数
function queueRenderPage(num) {
    if (pageRendering) {
        pageNumPending = num; // ページレンダリングが保留中の場合、次のページ番号を設定
    } else {
        renderPage(num); // 直ちにページをレンダリング
    }
}

// PDFのドキュメントを取得してレンダリングを開始
pdfjsLib.getDocument(url).promise.then(pdfDoc_ => {
    pdfDoc = pdfDoc_;
    document.getElementById('page-count').textContent = pdfDoc.numPages; // 総ページ数を表示
    renderPage(pageNum); // 最初のページをレンダリング
});

// 前のページボタンのイベントリスナー
document.getElementById('prev-page').addEventListener('click', () => {
    if (pageNum <= 1) {
        return; // 最初のページの場合、動作なし
    }
    pageNum--;
    queueRenderPage(pageNum); // 前のページをレンダリング
});

// 次のページボタンのイベントリスナー
document.getElementById('next-page').addEventListener('click', () => {
    if (pageNum >= pdfDoc.numPages) {
        return; // 最後のページの場合、動作なし
    }
    pageNum++;
    queueRenderPage(pageNum); // 次のページをレンダリング
});
    

このJavaScriptは、PDF.jsを使ってPDFをブラウザで表示し、ページを切り替えるためのものです。

フェードアウト効果の草花写真
  • 最初にPDFファイルのURLを設定し、PDF.jsライブラリを読み込みます。
  • pdfDocpageNumpageRenderingpageNumPendingなどの変数を定義し、PDFドキュメントやレンダリング状態を管理します。
  • 新しいキャンバス要素を作成し、それをPDFビューアのコンテナに追加します。
  • renderPage関数は、指定されたページ番号のPDFページをレンダリングし、キャンバスに描画します。ページの幅に合わせてスケールを調整し、適切な大きさにレンダリングします。
  • queueRenderPage関数は、レンダリング中に次のページを指定された場合に、保留中のページ番号を設定します。レンダリングが完了したら保留中のページをレンダリングします。
  • PDFドキュメントの読み込みが完了すると、最初のページをレンダリングし、総ページ数を表示します。
  • 前のページと次のページへの移動は、それぞれボタンのイベントリスナーで処理されます。ボタンをクリックすると、現在のページ番号を変更し、対応するページをレンダリングします。

同じページに複数のPDFがある場合(CSS)

CSSのほうはさほど大きな違いはないですね。
デフォルトではPDFを閉じてあるというだけです。

複数のPDFがある場合のaddpdf.css


@charset "UTF-8";

.addpdfhidden {
    display: none; /* 要素を非表示にします。 */
}

.pdf-link-add {
    padding: 8px 15px; /* 内側の余白を上下8ピクセル、左右15ピクセルに設定します。 */
    margin: 10px 0; /* 上下に10ピクセルの余白を追加します。 */
    background-color: #28a745; /* 背景色を緑色に設定します。 */
    color: white; /* 文字色を白に設定します。 */
    border: none; /* 境界線をなしに設定します。 */
    border-radius: 50px; /* 角を丸くします。 */
    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); /* 要素に影を追加します。影の位置は下に4ピクセル、広がりは6ピクセル、色は黒の10%透明です。 */
    font-size: 14px; /* フォントサイズを14ピクセルに設定します。 */
    font-weight: bold; /* フォントを太字に設定します。 */
    cursor: pointer; /* カーソルをポインターに変更します。 */
    transition: background-color 0.3s ease, box-shadow 0.3s ease; /* 背景色と影の変化にアニメーションを追加します。 */
    display: inline-block; /* 要素をインラインブロックに設定します。 */
    letter-spacing: 1px; /* 文字間隔を1ピクセルに設定します。 */
}

.pdf-link-add:hover {
    background-color: #218838; /* ホバー時の背景色を濃い緑色に設定します。 */
    box-shadow: 0 6px 8px rgba(0, 0, 0, 0.2); /* ホバー時の影を追加します。影の位置は下に6ピクセル、広がりは8ピクセル、色は黒の20%透明です。 */
}

.pdf-link-add:active {
    background-color: #1e7e34; /* クリック時の背景色をさらに濃い緑色に設定します。 */
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); /* クリック時の影を追加します。影の位置は下に2ピクセル、広がりは4ピクセル、色は黒の20%透明です。 */
}

.TESTpdf-container-add {
    width: 80%; /* 要素の幅を80%に設定します。 */
    margin: auto; /* 要素を中央揃えにします。 */
    border: 1px solid #ddd; /* 要素の周りに薄い灰色の境界線を追加します。 */
    padding: 10px; /* 内側の余白を10ピクセルに設定します。 */
    border-radius: 10px; /* 角を丸くします。 */
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); /* 要素に影を追加します。影の位置は下に4ピクセル、広がりは8ピクセル、色は黒の10%透明です。 */
    background-color: #fff; /* 背景色を白に設定します。 */
}

.TESTpdf-viewer-add {
    width: 100%; /* 要素の幅を100%に設定します。 */
    height: auto; /* 要素の高さを自動調整します。 */
    overflow: auto; /* 要素の内容が溢れた場合にスクロールバーを表示します。 */
    position: relative; /* 要素の位置を相対的に設定します。 */
}

.TESTcanvas {
    width: 100% !important; /* 要素の幅を100%に設定します。 */
    height: auto !important; /* 要素の高さを自動調整します。 */
    position: relative; /* 要素の位置を相対的に設定します。 */
}

.TESTpdfcontrols-add {
    text-align: center; /* テキストを中央揃えにします。 */
    margin-top: 10px; /* 上部に10ピクセルの余白を追加します。 */
}

.TESTpdfcontrols-add button {
    padding: 8px 15px; /* 内側の余白を上下8ピクセル、左右15ピクセルに設定します。 */
    margin: 0 5px; /* 左右に5ピクセルの余白を追加します。 */
    background-color: #007bff; /* 背景色を青色に設定します。 */
    color: white; /* 文字色を白に設定します。 */
    border: none; /* 境界線をなしに設定します。 */
    border-radius: 50px; /* 角を丸くします。 */
    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); /* 要素に影を追加します。影の位置は下に4ピクセル、広がりは6ピクセル、色は黒の10%透明です。 */
    font-size: 14px; /* フォントサイズを14ピクセルに設定します。 */
    font-weight: bold; /* フォントを太字に設定します。 */
    cursor: pointer; /* カーソルをポインターに変更します。 */
    transition: background-color 0.3s ease, box-shadow 0.3s ease; /* 背景色と影の変化にアニメーションを追加します。 */
}

.TESTpdfcontrols-add button:hover {
    background-color: #0056b3; /* ホバー時の背景色を濃い青色に設定します。 */
    box-shadow: 0 6px 8px rgba(0, 0, 0, 0.2); /* ホバー時の影を追加します。影の位置は下に6ピクセル、広がりは8ピクセル、色は黒の20%透明です。 */
}

.TESTpdfcontrols-add button:active {
    background-color: #004494; /* クリック時の背景色をさらに濃い青色に設定します。 */
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); /* クリック時の影を追加します。影の位置は下に2ピクセル、広がりは4ピクセル、色は黒の20%透明です。 */
}

.TESTpdfcontrols-add span {
    font-weight: bold; /* フォントを太字に設定します。 */
}

/* レスポンシブデザイン */
@media (max-width: 600px) {
    .TESTpdf-container-add {
        width: 100%; /* 要素の幅を100%に設定します。 */
        padding: 5px; /* 内側の余白を5ピクセルに設定します。 */
        box-sizing: border-box; /* ボックスのサイズを境界線と内側の余白を含むように設定します。 */
    }

    .TESTpdf-viewer-add {
        width: 100%; /* 要素の幅を100%に設定します。 */
        height: auto; /* 要素の高さを自動調整します。 */
        overflow: auto; /* 要素の内容が溢れた場合にスクロールバーを表示します。 */
        position: relative; /* 要素の位置を相対的に設定します。 */
    }

    .TESTcanvas {
        width: 100% !important; /* 要素の幅を100%に設定します。 */
        height: auto !important; /* 要素の高さを自動調整します。 */
    }

    .TESTpdfcontrols-add button {
        padding: 5px 10px; /* 内側の余白を上下5ピクセル、左右10ピクセルに設定します。 */
        font-size: 12px; /* フォントサイズを12ピクセルに設定します。 */
    }
}

    

同じページに複数のPDFがある場合(JavaScript)

同じページに複数のPDFがある場合、その全てのPDFのプレビューを開いていたらWebページは重くなってしまいます。
ユーザーがボタンを押したときのみプレビューを表示するようにできれば、大量のPDF文書を並べてもレスポンスに大きな影響は与えません。
まず、コメントアウトを入れたコードを提示します。

複数のPDFがある場合のaddpdf.js


const pdfjsLib = window['pdfjs-dist/build/pdf'];
pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.6.347/pdf.worker.min.js'; /* PDF.jsのワーカーのURLを設定します。 */

document.querySelectorAll('.pdf-link-add').forEach((link, index) => {
    let isOpen = false; /* PDFビューアが開いているかどうかを追跡するフラグです。 */
    link.addEventListener('click', function () {
        const url = this.getAttribute('data-url'); /* クリックされたリンクのデータURL属性を取得します。 */
        const fileName = url.substring(url.lastIndexOf('/') + 1); /* URLからファイル名を抽出します。 */
        const container = document.querySelectorAll('.TESTpdf-container-add')[index]; /* 対応するPDFコンテナを取得します。 */
        const viewer = container.querySelector('.TESTpdf-viewer-add'); /* PDFビューア要素を取得します。 */
        const prevButton = container.querySelector('.prev-page-add'); /* 前のページボタンを取得します。 */
        const nextButton = container.querySelector('.next-page-add'); /* 次のページボタンを取得します。 */
        const pageNumElement = container.querySelector('.page-num-add'); /* 現在のページ番号を表示する要素を取得します。 */
        const pageCountElement = container.querySelector('.page-count-add'); /* 総ページ数を表示する要素を取得します。 */

        if (isOpen) {
            container.classList.add('addpdfhidden'); /* PDFコンテナを非表示にします。 */
            this.textContent = `${fileName} を開く`; /* リンクのテキストを「開く」に変更します。 */
            isOpen = false; /* フラグを更新してPDFビューアが閉じていることを示します。 */
        } else {
            container.classList.remove('addpdfhidden'); /* PDFコンテナを表示します。 */
            this.textContent = `${fileName} を閉じる`; /* リンクのテキストを「閉じる」に変更します。 */
            loadPDF(url, container, viewer, prevButton, nextButton, pageNumElement, pageCountElement); /* PDFを読み込みます。 */
            isOpen = true; /* フラグを更新してPDFビューアが開いていることを示します。 */
        }
    });
});

function loadPDF(url, container, viewer, prevButton, nextButton, pageNumElement, pageCountElement) {
    const canvas = document.createElement('canvas'); /* 新しいキャンバス要素を作成します。 */
    viewer.innerHTML = ''; /* ビューアの内容をクリアします。 */
    viewer.appendChild(canvas); /* キャンバスをビューアに追加します。 */

    let pdfDoc = null,
        pageNum = 1, /* 現在のページ番号を初期化します。 */
        pageRendering = false, /* ページがレンダリング中かどうかを追跡するフラグです。 */
        pageNumPending = null, /* レンダリング待ちのページ番号です。 */
        ctx = canvas.getContext('2d'); /* キャンバスの2Dコンテキストを取得します。 */

    function renderPage(num) {
        pageRendering = true; /* ページがレンダリング中であることを示します。 */
        pdfDoc.getPage(num).then(page => {
            const containerWidth = viewer.clientWidth; /* ビューアの幅を取得します。 */
            const scale = 3; /* ページのスケールを設定します。 */
            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(() => {
                canvas.style.width = `${containerWidth}px`; /* キャンバスの幅をビューアの幅に合わせます。 */
                canvas.style.height = "auto"; /* キャンバスの高さを自動調整します。 */

                pageRendering = false; /* ページのレンダリングが完了したことを示します。 */
                if (pageNumPending !== null) {
                    renderPage(pageNumPending); /* レンダリング待ちのページがあればレンダリングします。 */
                    pageNumPending = null; /* レンダリング待ちのページ番号をクリアします。 */
                }
            });
        });

        pageNumElement.textContent = num; /* 現在のページ番号を表示します。 */
    }

    function queueRenderPage(num) {
        if (pageRendering) {
            pageNumPending = num; /* ページがレンダリング中の場合、待ち行列に追加します。 */
        } else {
            renderPage(num); /* ページがレンダリング中でない場合、すぐにレンダリングします。 */
        }
    }

    pdfjsLib.getDocument(url).promise.then(pdfDoc_ => {
        pdfDoc = pdfDoc_; /* PDFドキュメントを取得します。 */
        pageCountElement.textContent = pdfDoc.numPages; /* 総ページ数を表示します。 */
        renderPage(pageNum); /* 最初のページをレンダリングします。 */
    });

    prevButton.addEventListener('click', () => {
        if (pageNum <= 1) {
            return; /* 現在のページが最初のページの場合、何もしません。 */
        }
        pageNum--; /* ページ番号を減少させます。 */
        queueRenderPage(pageNum); /* 前のページをレンダリングします。 */
    });

    nextButton.addEventListener('click', () => {
        if (pageNum >= pdfDoc.numPages) {
            return; /* 現在のページが最後のページの場合、何もしません。 */
        }
        pageNum++; /* ページ番号を増加させます。 */
        queueRenderPage(pageNum); /* 次のページをレンダリングします。 */
    });
}

このコードはPDF.jsライブラリを使用してウェブページ上でPDFファイルを表示し、ページ間を移動する機能を提供します。
今度はコメントアウトではなく、コードはそのまま掲載します。
そのうえで、このコードが何をしているのか、おおまかな流れを説明します。

PDF.jsの設定

ライブラリを読み込むJavaScript


const pdfjsLib = window['pdfjs-dist/build/pdf'];
pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.6.347/pdf.worker.min.js';
    

PDF.jsライブラリを読み込み、ワーカーのURLを設定します。

リンクのクリックイベント設定

クリックイベントを設定するJavaScript


document.querySelectorAll('.pdf-link-add').forEach((link, index) => {
    let isOpen = false;
    link.addEventListener('click', function () {
        const url = this.getAttribute('data-url');
        const fileName = url.substring(url.lastIndexOf('/') + 1);
        const container = document.querySelectorAll('.TESTpdf-container-add')[index];
        const viewer = container.querySelector('.TESTpdf-viewer-add');
        const prevButton = container.querySelector('.prev-page-add');
        const nextButton = container.querySelector('.next-page-add');
        const pageNumElement = container.querySelector('.page-num-add');
        const pageCountElement = container.querySelector('.page-count-add');

        if (isOpen) {
            container.classList.add('addpdfhidden');
            this.textContent = `${fileName} を開く`;
            isOpen = false;
        } else {
            container.classList.remove('addpdfhidden');
            this.textContent = `${fileName} を閉じる`;
            loadPDF(url, container, viewer, prevButton, nextButton, pageNumElement, pageCountElement);
            isOpen = true;
        }
    });
});
    
PDFの読み込みと表示

PDFを表示するJavaScript


function loadPDF(url, container, viewer, prevButton, nextButton, pageNumElement, pageCountElement) {
    const canvas = document.createElement('canvas');
    viewer.innerHTML = '';
    viewer.appendChild(canvas);

    let pdfDoc = null,
        pageNum = 1,
        pageRendering = false,
        pageNumPending = null,
        ctx = canvas.getContext('2d');

    function renderPage(num) {
        pageRendering = true;
        pdfDoc.getPage(num).then(page => {
            const containerWidth = viewer.clientWidth;
            const scale = 3;
            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(() => {
                canvas.style.width = `${containerWidth}px`;
                canvas.style.height = "auto";

                pageRendering = false;
                if (pageNumPending !== null) {
                    renderPage(pageNumPending);
                    pageNumPending = null;
                }
            });
        });

        pageNumElement.textContent = num;
    }

    function queueRenderPage(num) {
        if (pageRendering) {
            pageNumPending = num;
        } else {
            renderPage(num);
        }
    }

    pdfjsLib.getDocument(url).promise.then(pdfDoc_ => {
        pdfDoc = pdfDoc_;
        pageCountElement.textContent = pdfDoc.numPages;
        renderPage(pageNum);
    });

    prevButton.addEventListener('click', () => {
        if (pageNum <= 1) {
            return;
        }
        pageNum--;
        queueRenderPage(pageNum);
    });

    nextButton.addEventListener('click', () => {
        if (pageNum >= pdfDoc.numPages) {
            return;
        }
        pageNum++;
        queueRenderPage(pageNum);
    });
}
    

このようにして、PDFファイルをウェブページ上で表示し、ページ間を移動する機能を実現しています。


サイトマップ

アナザーエデン関連ページ・サイトマップ

アナザーエデンの強敵戦やストーリーコンテンツのリスト、お勧めバッジなどを掲載したコーナーです。
期間限定のない普通のRPGですので、初心者でも安心して続けていけるゲームとなっています。
もっとも重要なグラスタについては、場所別に網羅した表があります。

個人サイトのホスティングとコンテンツ作成

個人でウェブサイトを作るにはどうすればいいか。
HTML・CSS・JavaScriptの書き方はもちろん、無料かつ広告なしでホームページを作る方法を掲載したコーナーです。
Webデザインやレイアウトについても書いてあります。

魚釣りなどアウトドアのエリア

ゲームとパソコンだけじゃなく、アウトドアも趣味なんです。
このコーナーでは魚釣りの記録とか、魚料理のレシピ、はたまたサイクリングなどなど。
アウトドアに関連するコンテンツが詰め込まれています。