この記事について
この記事は、生成AIを活用した自動生成フローで作成しています。papanda925 Character Sheet v1をキャラクターの正本として統一した4枚のマンガ画像を使い、JSONから1ページずつ切り替える「横向きページ切り替え版」と、同じ画像を上から順に並べる「スマホ縦読み版」を Daily-Code-Samples に実装して、表示方式の違いを比べています。検証ステータス:🧪 GitHub実装済み・JavaScript/JSON/公開安全性チェック成功・GitHub Pages build完了・スマホ実機表示は未確認
マンガをWebで見せるなら、1枚の長い画像をそのまま縦に置くのが一番簡単です。
でも今回は、あえてもう一歩だけ進めます。
「前へ」「次へ」で1ページずつ切り替える横向きビューアと、スマホでそのまま下へスクロールして読む縦読みビューアを、同じ4枚の画像データから作ってみました。
専用のマンガライブラリは使いません。
必要なのは、HTML、CSS、JavaScript、JSON、そしてマンガ画像だけです。
- まず試してみる
- 今回使っている4枚のマンガ画像
- Papandaの正本は Character Sheet v1
- 全体像
- 横向き版のファイル構成
- 画像と付帯データはJSONで持つ
- JSONを fetch() で読む
- currentIndex で「今のページ」を持つ
- renderPage() で画像と付帯データをまとめて変える
- 「前へ」「次へ」は同じ関数を使う
- PCでは左右キーでも読める
- スマホ縦読み版は何が違う?
- 縦読み版は forEach() で全ページを作る
- 縦読みでは遅延読み込みも使う
- 横向き版と縦読み版を比べる
- GitHubでコードと画像を全部見る
- GitHub Pagesで公開する
- 今回あえて入れなかった機能
- まとめ
- 参考リンク
まず試してみる
今回のサンプルは GitHub Pages で公開しています。
横向き版では「次のページ」を押すと、1 / 4 → 2 / 4 → 3 / 4 → 4 / 4 と表示が切り替わります。
画像だけではありません。タイトル、説明、タグも、そのページのデータとして一緒に切り替わります。
縦読み版では同じ4枚を上から順に並べます。「次へ」ボタンは使わず、スマホではそのまま下へスクロールして読みます。
今回使っている4枚のマンガ画像
現在は papanda925 Character Sheet v1 を基準にしたPapanda へ統一しています。
1 / 4 — ブラウザでページを切り替える
2 / 4 — 画像と付帯データを分けて持つ
3 / 4 — 前へ・次へでページを切り替える
4 / 4 — GitHub Pagesで公開する
スマホ縦読み版の説明用画像も用意しました。
Papandaの正本は Character Sheet v1
今回から、Papandaの見た目を記事ごとにその場で決めるのではなく、Character Sheet v1 を正本として扱うことにしました。
基準にしているのは、たとえば次のような特徴です。
顔は真円ではなく、少し横長でやわらかい輪郭
顔とおなかはクリーム寄りの白
耳・目の周り・手足は真っ黒ではなく濃いブラウン
大きめでツヤのある目
薄いピンクのほっぺ
小さな口
2〜3頭身程度の、かわいらしいアニメ・ちびキャラ調
「考える」「驚く」「説明する・うれしい」を基本表情にする
この基準を文章でも再利用できるよう、GitHubに CHARACTER_SOURCE.md を置きました。
今後マンガ画像を増やすときも、ここを参照元にすることで、記事ごとに別のパンダのようになるブレを減らせます。
全体像
今回のポイントは、マンガ画像そのものと、どう見せるかを分けたことです。
flowchart TD
A[4枚のSVG画像] --> B[manga.json / manga-vertical.json]
B --> C{表示方法}
C --> D[横向き版]
C --> E[スマホ縦読み版]
D --> F[currentIndexで1枚を選ぶ]
F --> G[前へ / 次へで差し替える]
E --> H[全ページを順番にDOMへ追加]
H --> I[下へスクロールして読む]
同じ画像を使っていても、JavaScript側の表示方法を変えれば読み方を変えられます。
これが今回の実験で一番面白かったところです。
横向き版のファイル構成
docs/demos/papanda-manga-viewer/
├── index.html
├── style.css
├── app.js
├── manga.json
└── pages/
├── page-01.svg
├── page-02.svg
├── page-03.svg
└── page-04.svg
HTMLを4ページ分作っているわけではありません。HTMLは1画面だけです。
その中にある <img> の参照先を JavaScript で差し替えています。
画像と付帯データはJSONで持つ
manga.json では、画像パスだけでなく、そのページに付随する情報も一緒に持たせています。
{
"image": "./pages/page-02.svg",
"alt": "2ページ目。Papandaが画像と付帯データを分けて管理する考え方を紹介するイラスト",
"title": "2ページ目:画像と付帯データを分けて持つ",
"caption": "画像パスだけでなく、タイトル・説明・タグもJSONから取得します。",
"tags": ["JSON", "メタデータ", "付帯データ"]
}
ページ切り替えだけなら、JavaScriptへ画像名を4つ直接書いても動きます。
それでもJSONを分けたのは、画像と表示用の情報を1ページ分のデータとして扱いたかったからです。
JSONを fetch() で読む
ページ情報は fetch() で読み込みます。
fetch('./manga.json')
.then((response) => {
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
return response.json();
})
.then((data) => {
if (!Array.isArray(data.pages) || data.pages.length === 0) {
throw new Error('pages が空、または配列ではありません');
}
pages = data.pages;
renderPage();
})
.catch((error) => {
status.textContent =
`マンガデータを読み込めませんでした: ${error.message}`;
});
response.ok を確認し、さらに pages が配列として存在するかもチェックしています。
currentIndex で「今のページ」を持つ
横向き版の中心はこれです。
let pages = []; let currentIndex = 0;
配列は0から始まるため、4ページならこう対応します。
currentIndex = 0 → 1ページ目 currentIndex = 1 → 2ページ目 currentIndex = 2 → 3ページ目 currentIndex = 3 → 4ページ目
画面では、
`${currentIndex + 1} / ${pages.length}`
として、人間が読みやすい 1 / 4 に変えています。
renderPage() で画像と付帯データをまとめて変える
function renderPage() {
const page = pages[currentIndex];
if (!page) return;
image.src = page.image;
image.alt = page.alt ?? '';
counter.textContent = `${currentIndex + 1} / ${pages.length}`;
title.textContent = page.title ?? '';
caption.textContent = page.caption ?? '';
}
中心になるのは次の1行です。
image.src = page.image;
同じ <img> 要素の src を変えるだけで、別のマンガ画像へ切り替えられます。
「前へ」「次へ」は同じ関数を使う
function movePage(step) {
const nextIndex = currentIndex + step;
if (nextIndex < 0 || nextIndex >= pages.length) {
return;
}
currentIndex = nextIndex;
renderPage();
}
次へなら movePage(1)、前へなら movePage(-1) です。
画面の端では、範囲外へ進まないようボタンも無効にします。
prevButton.disabled = currentIndex === 0; nextButton.disabled = currentIndex === pages.length - 1;
PCでは左右キーでも読める
document.addEventListener('keydown', (event) => {
if (event.key === 'ArrowLeft') movePage(-1);
if (event.key === 'ArrowRight') movePage(1);
});
ボタン用とは別の移動処理を作らず、同じ movePage() を再利用しています。
スマホ縦読み版は何が違う?
縦読み版でもマンガ画像は同じです。
違うのは、JavaScript側で1枚だけ選ばず、全部を順番に画面へ追加することです。
docs/demos/papanda-manga-viewer-vertical/ ├── index.html ├── style.css ├── app.js ├── manga-vertical.json └── vertical-sample.svg
実際の4ページ画像は複製せず、横向き版の pages/ を参照しています。
同じ4枚のSVG
├─ 横向き版 → 1枚ずつ切り替える
└─ 縦読み版 → 4枚を上から順に並べる
縦読み版は forEach() で全ページを作る
const fragment = document.createDocumentFragment();
data.pages.forEach((page, index) => {
fragment.append(
createPage(page, index, data.pages.length)
);
});
root.replaceChildren(fragment);
横向き版は currentIndex で今の1ページだけを表示し、縦読み版は forEach() ですべてのページを順番に表示します。
同じページデータでも、表示ロジックを変えるだけで別の読み方になることが分かります。
縦読みでは遅延読み込みも使う
image.loading = index === 0 ? 'eager' : 'lazy'; image.decoding = 'async';
1ページ目はすぐ読み込み、2ページ目以降はブラウザの遅延読み込みを使います。
今回の4ページ程度では差は小さいですが、ページ数を増やしたときに効いてくる考え方です。
横向き版と縦読み版を比べる
| 項目 | 横向きページ切り替え版 | スマホ縦読み版 |
|---|---|---|
| 読み方 | 前へ / 次へ | 下へスクロール |
| 中心ロジック | currentIndex | forEach() |
| 同時表示 | 原則1ページ | 全ページ |
| PC | 見やすい | 閲覧可能 |
| スマホ | 閲覧可能 | 特に読みやすい |
| 画像データ | 4枚を参照 | 同じ4枚を再利用 |
| 付帯データ | JSON | JSON |
コンテンツと表示方法を分けておけば、同じマンガ画像から別のUIを作れます。
GitHubでコードと画像を全部見る
READMEからライブデモだけでなく、実装ファイルとサンプル画像へ直接たどれるようにしています。
横向き版
スマホ縦読み版
GitHub Pagesで公開する
今回のビューアは、HTML、CSS、JavaScript、JSON、SVGだけで構成されています。PHPやPythonなどのサーバー側プログラムは不要です。
Daily-Code-Samples は main ブランチの /docs を公開元にしています。今回の更新後、GitHub Pages側の状態が built になっていることを確認しました。
ただし、ここで確認しているのはGitHub Pagesのビルド状態です。スマートフォン実機でのレイアウト・操作感は、この記事の公開時点ではまだ追加確認対象としています。
今回あえて入れなかった機能
今回は「画像をどう見せ分けるか」に集中するため、スワイプ操作、ページめくりアニメーション、URLへの現在ページ保存、拡大表示、全画面表示、吹き出し位置の外部データ化、AIによるマンガ自動生成パイプライン、WordPress専用埋め込みなどはまだ入れていません。
まずは、
画像 + JSON
↓
横なら1枚ずつ切り替える
縦なら全部並べる
という最小構成を動かすところまでにしました。
まとめ
Papanda Manga Viewer v0.1 では、専用のマンガライブラリを使っていません。
横向き版の中心は currentIndex と image.src = page.image;。縦読み版では同じ4枚を forEach() で上から順に追加しています。
さらに、画像だけでなくタイトル・説明・タグをJSONへ分けておくことで、同じコンテンツを別のUIから再利用できるようになります。
そして今回から、Papanda自体も Character Sheet v1 を正本にしました。
同じキャラクター、同じ画像データ、違う表示方法。
マンガを題材にすると、JSON、配列、DOM操作、レスポンシブ表示といったWebの基本が、かなり目で見て分かりやすくなります。
参考リンク
最終更新: 2026年9月10日
