关于本文
本文采用利用生成式 AI 的自动化生成流程制作。papanda925 Character Sheet v1在 Daily-Code-Samples 中实现了以统一的角色标准为基础的4张漫画图片,通过 JSON 实现逐页切换的“横屏页面切换版”,以及将相同图片从上到下依次排列的“手机竖屏阅读版”,以此比较不同显示方式的区别。验证状态:🧪 GitHub 已实现・JavaScript/JSON/公开安全性检查成功・GitHub Pages 构建完成・手机实机显示未确认
如果要在网页上展示漫画,最简单的方法是将一张长图直接纵向放置。
但这一次,我们决定再向前迈出一步。
通过“上一页”和“下一页”逐页切换的横屏查看器,以及在手机上直接向下滚动阅读的竖屏查看器,我们使用相同的4张图片数据分别制作了这两个版本。
我们不使用任何专用的漫画库。
需要的只有 HTML、CSS、JavaScript、JSON 以及漫画图片。
首先进行尝试
本次的示例已在 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 头身左右,可爱的小头Q版动画风格
基本表情设定为“思考”、“惊讶”、“说明・高兴”
为了能够在文章中重复利用这些标准,我们在 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
并不是为4页分别制作了4个 HTML 文件。HTML 只有一个界面。
通过 JavaScript 动态替换其中 <img> 的引用目标。
使用 JSON 保存图片与附加数据
manga.json 在 中,不仅保存了图片路径,还一同保存了该页面附带的相关信息。
{
"image": "./pages/page-02.svg",
"alt": "2ページ目。Papandaが画像と付帯データを分けて管理する考え方を紹介するイラスト",
"title": "2ページ目:画像と付帯データを分けて持つ",
"caption": "画像パスだけでなく、タイトル・説明・タグもJSONから取得します。",
"tags": ["JSON", "メタデータ", "付帯データ"]
}
如果只是切换页面,直接在 JavaScript 中写死4个图片名称也能运行。
即便如此,我们还是将 JSON 独立出来,因为我们希望将图片和显示用的信息作为一个单页的数据来处理。
通过 fetch() 读取 JSON
页面信息通过 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 ?? '';
}
核心是下面这一行代码。
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';
第一页会立即加载,而第二页及之后的页面则使用浏览器的延迟加载功能。
虽然对于本次大约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日
