Comimi 是开源 TypeScript/JavaScript 漫画阅读器库,单 API 即可嵌入完整阅读体验。支持 RTL/LTR 切换、单页双页、键盘快捷键和 IndexedDB 进度记忆,6 种语言界面免依赖 React 等 UI 框架。MIT 协议开源,npm 一行安装即用,白标嵌入解锁。
🎤 引言
有没有试过这种情况:自己博客里塞一组漫画图,想让读者能像专业漫画站那样翻页、放大、记忆阅读位置……结果折腾半天,要么引入了一个 React 套件(项目本来就没用框架),要么拿现成插件发现锁了功能、改不动。
日本开发者 yui540 开源的 comimi 就是冲这个场景来的 —— 单 API 调用、不依赖任何 UI 框架、原生 TypeScript、MIT 协议。0.15.0 版本(2026 年 6 月 20 日更新)已经收录 RTL/LTR 阅读方向、单页 / 双页见开启、键盘快捷键、IndexedDB 阅读进度记忆等一套完整特性。
最近在 GitHub Trendshift 出现频率挺高,379 stars、105 commits,定位「Open-source comic reader library for JS/TS」。下面具体看看它到底能干啥、能不能解决你的痛点。
🌟 核心亮点
1. 单 API + 零框架依赖
整个库对外暴露的就一个函数 —— createMangaViewer(container, options)。传入一个 DOM 元素和漫画数据,返回一个 MangaViewerInstance 实例,剩下的 DOM 全部由库自己生成。最简例子直接拷贝就能跑:
import { createMangaViewer } from "@yui540/comimi";
createMangaViewer(document.querySelector("#viewer")!, {
manga: {
id: "sample",
title: "サンプル漫画",
author: "yui540",
pages: [
{ id: "p0", type: "image", src: "/pages/0.webp" },
{ id: "p1", type: "image", src: "/pages/1.webp" },
{ id: "p2", type: "image", src: "/pages/2.webp" },
],
},
});没 React、没 Vue、没 Svelte,连 jQuery 都不需要。package.json 里 type: "module" 直接走 ESM,TypeScript 类型定义挂在 dist/index.d.ts,IDE 自动补全体验拉满。
2. 阅读方向 + 见开启模式
日漫是 RTL(从右往左)、条漫(webtoon)大多是 LTR(从左往右),comimi 在 settings.readingDirection 一个字段里切:默认 "rtl",传 "ltr" 立刻翻过来。同样 pageTurnMode: "single" | "spread" 控制单页 / 双页见开启,再加 hasCover: true 让双页模式下第一页单独显示(模拟真实翻书)。
这套默认参数其实已经覆盖了 90% 的阅读场景,不用去读一堆配置。
3. 布局模式 4 选 1 + 键盘快捷键
layoutMode 提供 4 种:
| 模式 | 行为 |
|---|---|
inline | 默认嵌入父元素(桌面 max 900px / 移动 max 500px),圆角 + 薄阴影 |
wide | 100% 宽,下方拖拽手柄调高度 |
browserFullscreen | position: fixed 铺满视口,不走 Fullscreen API |
nativeFullscreen | 调 Fullscreen API,失败回退到上面那种 |
键盘党狂喜:←/→ 翻页、Space 翻页、A 自动播放、N/W/F 切布局、P 单页/见开启切换、M 菜单、O 覆盖层、S 设置面板、Esc 标准布局。这些快捷键只在 viewer 根元素聚焦时生效,不会污染页面其他输入。
4. IndexedDB 阅读进度记忆
默认开启 IndexedDB 持久化(可通过 storage.enabled: false 关掉),自动保存:
- 全局设置(locale、theme、autoPageTurnIntervalMs、backgroundColor、zoom)
- 单作品设置(pageTurnMode、hasCover、readingDirection),用
manga.id作 key - 当前布局模式和 wide 高度
- 每部作品的阅读位置(manga.id 作 key)
下次读者打开直接 initialPageIndex 不传就自动从上次位置续读。传了就强制跳到指定页(保存的进度不会被破坏,下次不传再继续)。需要多作品切换的场景特别合适,比如把整站漫画全用 comimi 渲染,每部独立记忆。
5. 内置 i18n + 自定义翻译
开箱就有 6 种语言:ja / en / zh-CN / ko / th / id。中文读者直接设 locale: "zh-CN" 即可。要局部覆盖某个 key:
createMangaViewer(container, {
manga,
locale: "zh-CN",
translations: {
"overlay.settings": "设置面板",
"settings.cover": "封面模式",
},
});未定义的 key 自动按 ja → 原文 fallback,不会乱码也不会空白。
6. 键盘 / 触摸 / 鼠标三端交互
桌面端鼠标支持:
- 中央 40% 点击切换覆盖层
- 左 30% / 右 30% 点击瞬切前 / 后页(无动画)
- Ctrl/⌘ + 滚轮缩放(围绕光标点)
- 缩放后拖拽平移
移动端:左右滑动(40px 阈值)、双指捏合缩放。整体响应时延感很顺,不会有「卡一下才反应」的廉价感。
📥 安装与使用
方式一:npm 包(推荐)
npm install @yui540/comimi需要现代浏览器(IndexedDB + ES2020 即可),打包器任意(Vite / Webpack / Rollup 都行)。
方式二:CDN(无构建)
不想走打包?读 dist/manga-viewer.global.js 直接 <script> 引入,挂到 window.MangaViewer.createMangaViewer(...):
<div id="viewer"></div>
<script src="https://unpkg.com/@yui540/comimi/dist/manga-viewer.global.js"></script>
<script>
window.MangaViewer.createMangaViewer(document.querySelector("#viewer"), {
manga: { id: "demo", title: "Demo", pages: [...] },
});
</script>进阶用法:受保护资源(resolvePageSrc)
如果你的漫画页需要鉴权或者加密存储,用 resolvePageSrc:
createMangaViewer(container, {
manga,
resolvePageSrc: async ({ page }) => {
const res = await fetch(page.src, {
headers: { Authorization: `Bearer ${getToken()}` }
});
const blob = await res.blob();
return URL.createObjectURL(blob);
},
});库在每页图片渲染前调用你的函数,返回 Data URL / Blob URL / 普通 URL 都行。结果会按 page.id 缓存,反复来回翻同一页不会重新请求。
白标嵌入(锁布局 / 隐藏设置)
做付费阅读 / DRM 风格嵌入时,用 lockLayoutMode + hiddenSettings 锁死交互:
createMangaViewer(container, {
manga,
settings: { layoutMode: "browserFullscreen" },
lockLayoutMode: true, // 锁死布局切换
hiddenSettings: ["pageMode", "autoplay", "viewMode"], // 隐藏工具栏按钮
});hiddenSettings 比 lockLayoutMode 更细:可以单独隐藏工具栏的「自动播放」按钮同时保留快捷键 P。覆盖层菜单、设置面板的每个项目都能精准控。
🛠 适用场景
✅ 个人漫画博客 / 独立漫画作者站 —— 单 API 嵌入,无须改现有技术栈
✅ 日漫 / 条漫平台原型 —— RTL/LTR + 单页/双页开箱即用
✅ 付费阅读 / DRM 嵌入 —— resolvePageSrc + lockLayoutMode 组合
✅ 多作品连续阅读 —— IndexedDB 按 manga.id 独立记忆位置
✅ 教育 / 培训站点 —— 嵌入 HTMLPage 类型,把讲义排版当「页」渲染
❌ PDF / EPUB 直接渲染 —— 不支持,得先转图片
❌ 视频 / 音频 —— 当前只有 image / html 两种 page type
❌ 超大图(万级像素) —— 单页加载慢,得自己切片
🔍 与同类工具对比
| 维度 | Comimi | Tachiyomi 源 | 自研 React 组件 | PDF.js |
|---|---|---|---|---|
| 集成方式 | npm 包 / CDN | Android 客户端 | 自建 | npm 包 |
| 框架依赖 | 零 | 原生 Android | 必须 React | 零 |
| 阅读方向切换 | ✅ 一键切 RTL/LTR | ❌ 看源 | 自实现 | ❌ |
| 见开启模式 | ✅ 单/双页 | ✅ | 自实现 | ❌ |
| 阅读进度记忆 | ✅ IndexedDB 自动 | ✅ 本地库 | 自实现 | ✅ |
| 多语言界面 | ✅ 6 种 + 自定义 | 取决于源 | 自实现 | 较少 |
| 白标锁定 | ✅ lockLayoutMode | ❌ | 自实现 | ❌ |
| 包体积 | ~150KB(gzip) | N/A | 看实现 | ~300KB+ |
| 协议 | MIT | GPL-3.0 | 看实现 | Apache-2.0 |
Tachiyomi 是 Android 客户端方案、Web 端用不上;自研 React 组件灵活但工作量大;PDF.js 是为 PDF 设计的,漫画翻页体验得自己二次开发。comimi 在「Web 端零框架集成 + 漫画场景」这一格几乎没有对位选手。
⚠️ 注意事项
- 仅支持 image / html 两种 page。想做视频或者 PDF 得自己预处理。建议优先 webp 格式(库默认示例就是 webp),体积小 + 加载快。
- IndexedDB 默认开启。GDPR 合规场景下记得显式
storage.enabled: false,或者在隐私政策里说明。IndexedDB 用的是库默认数据库名manga-viewer,可通过storage.databaseName改名方便多实例隔离。 - 快捷键只在 viewer 聚焦时生效,但
<input>等表单元素不在范围内。如果你页面里塞了搜索框,激活搜索时不会误触发翻页。放心。 - CDN 用法目前只发布 global.js,没有 ESM 兼容 CDN(如 esm.sh)自动同步,跨域引入得自己 polyfill 或自建。如有需要可用 esm.sh 二次封装:
<script type="module">
import { createMangaViewer } from "https://esm.sh/@yui540/comimi";
// ...
</script>- 仅作者 yui540 一人维护(截至 2026-06)。Stars 379、Issue 1、PR 1 算很早期,遇到问题反馈修复周期不定。如果你的项目强依赖,最好 fork 一份留底。
- i18n 没欧洲语言。法语 / 德语 / 西班牙语这些得自己用
translations全量覆盖。不过键名很规整(overlay.settings这种),全量覆盖 50 行 JSON 就完事。 - 缩放上限 4x(默认)。需要更大缩放自定义
settings.zoom.max,但要在移动端测过 —— 超过 4x 容易卡 GPU。
🎯 总结
Comimi 给「想在 Web 里嵌漫画阅读器、又不想引 UI 框架」这个场景提供了一个真正即插即用的方案。单 API 调起来、配置项都在一个 settings 对象里、IndexedDB 自动记忆阅读进度 —— 这些都是用过一次就回不去的细节。
推荐指数:⭐⭐⭐⭐(4/5)—— 漫画 / 条漫 / 教学站点场景强推,少一颗星是「作者单点维护 + 早期阶段」的潜在风险。
适合人群:
- 独立漫画作者想搭一个干净的个人站
- 博客主想给文章附一组漫画图并提供专业翻页体验
- 团队 / 教育产品需要在不引入 React 的页面里嵌漫画
- DRM 风格嵌入(
resolvePageSrc+lockLayoutMode)
不适合:需要 PDF 直接渲染、视频页、超大图(万级像素)的项目。
如果你是前端开发,正好在找一个轻量的漫画 / 条漫阅读器库,comimi 值得放进你的工具箱。下次有人问你「博客里嵌入漫画用什么好」,直接把这篇转过去。