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.jsontype: "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),圆角 + 薄阴影
wide100% 宽,下方拖拽手柄调高度
browserFullscreenposition: 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"],  // 隐藏工具栏按钮
});

hiddenSettingslockLayoutMode 更细:可以单独隐藏工具栏的「自动播放」按钮同时保留快捷键 P。覆盖层菜单、设置面板的每个项目都能精准控。


🛠 适用场景

个人漫画博客 / 独立漫画作者站 —— 单 API 嵌入,无须改现有技术栈
日漫 / 条漫平台原型 —— RTL/LTR + 单页/双页开箱即用
付费阅读 / DRM 嵌入 —— resolvePageSrc + lockLayoutMode 组合
多作品连续阅读 —— IndexedDB 按 manga.id 独立记忆位置
教育 / 培训站点 —— 嵌入 HTMLPage 类型,把讲义排版当「页」渲染

PDF / EPUB 直接渲染 —— 不支持,得先转图片
视频 / 音频 —— 当前只有 image / html 两种 page type
超大图(万级像素) —— 单页加载慢,得自己切片


🔍 与同类工具对比

维度ComimiTachiyomi 源自研 React 组件PDF.js
集成方式npm 包 / CDNAndroid 客户端自建npm 包
框架依赖原生 Android必须 React
阅读方向切换✅ 一键切 RTL/LTR❌ 看源自实现
见开启模式✅ 单/双页自实现
阅读进度记忆✅ IndexedDB 自动✅ 本地库自实现
多语言界面✅ 6 种 + 自定义取决于源自实现较少
白标锁定✅ lockLayoutMode自实现
包体积~150KB(gzip)N/A看实现~300KB+
协议MITGPL-3.0看实现Apache-2.0

Tachiyomi 是 Android 客户端方案、Web 端用不上;自研 React 组件灵活但工作量大;PDF.js 是为 PDF 设计的,漫画翻页体验得自己二次开发。comimi 在「Web 端零框架集成 + 漫画场景」这一格几乎没有对位选手。


⚠️ 注意事项

  1. 仅支持 image / html 两种 page。想做视频或者 PDF 得自己预处理。建议优先 webp 格式(库默认示例就是 webp),体积小 + 加载快。
  2. IndexedDB 默认开启。GDPR 合规场景下记得显式 storage.enabled: false,或者在隐私政策里说明。IndexedDB 用的是库默认数据库名 manga-viewer,可通过 storage.databaseName 改名方便多实例隔离。
  3. 快捷键只在 viewer 聚焦时生效,但 <input> 等表单元素不在范围内。如果你页面里塞了搜索框,激活搜索时不会误触发翻页。放心。
  4. CDN 用法目前只发布 global.js,没有 ESM 兼容 CDN(如 esm.sh)自动同步,跨域引入得自己 polyfill 或自建。如有需要可用 esm.sh 二次封装:
<script type="module">
  import { createMangaViewer } from "https://esm.sh/@yui540/comimi";
  // ...
</script>
  1. 仅作者 yui540 一人维护(截至 2026-06)。Stars 379、Issue 1、PR 1 算很早期,遇到问题反馈修复周期不定。如果你的项目强依赖,最好 fork 一份留底。
  2. i18n 没欧洲语言。法语 / 德语 / 西班牙语这些得自己用 translations 全量覆盖。不过键名很规整(overlay.settings 这种),全量覆盖 50 行 JSON 就完事。
  3. 缩放上限 4x(默认)。需要更大缩放自定义 settings.zoom.max,但要在移动端测过 —— 超过 4x 容易卡 GPU。

🎯 总结

Comimi 给「想在 Web 里嵌漫画阅读器、又不想引 UI 框架」这个场景提供了一个真正即插即用的方案。单 API 调起来、配置项都在一个 settings 对象里、IndexedDB 自动记忆阅读进度 —— 这些都是用过一次就回不去的细节。

推荐指数:⭐⭐⭐⭐(4/5)—— 漫画 / 条漫 / 教学站点场景强推,少一颗星是「作者单点维护 + 早期阶段」的潜在风险。

适合人群

  • 独立漫画作者想搭一个干净的个人站
  • 博客主想给文章附一组漫画图并提供专业翻页体验
  • 团队 / 教育产品需要在不引入 React 的页面里嵌漫画
  • DRM 风格嵌入(resolvePageSrc + lockLayoutMode

不适合:需要 PDF 直接渲染、视频页、超大图(万级像素)的项目。

如果你是前端开发,正好在找一个轻量的漫画 / 条漫阅读器库,comimi 值得放进你的工具箱。下次有人问你「博客里嵌入漫画用什么好」,直接把这篇转过去。