Flutter-电子书EPub解析Iridium

Iridium

Iridium 是一个功能强大的 Flutter 电子书阅读器组件集合,旨在提供高质量的电子书阅读体验。

📚 功能特点

  • 支持 EPUB 格式电子书的显示和阅读
  • 提供完整的阅读器 UI 组件
  • 可自定义的主题设置
  • 字体大小、行距等排版设置
  • 页面导航和进度显示
  • 可嵌入任何 Flutter 应用中

📦 包结构

该项目包含多个核心组件:

  • reader_widget: 即插即用的阅读器 Widget 组件
  • components/commons: 通用工具和辅助类
  • components/navigator: 导航和页面控制
  • components/opds: OPDS 目录支持
  • components/server: 服务器相关功能
  • components/shared: 共享组件
  • components/streamer: 流媒体处理
  • components/webview: Web 视图组件

🚀 快速开始

  1. 添加依赖到 pubspec.yaml:
yaml 复制代码
dependencies:
  iridium_reader_widget:
    path: path/to/iridium/reader_widget

1 加载EPUB

1. 从文件路径加载

EpubScreen.fromPath( filePath: "path/to/book.epub", location: "书签位置", settings: "100", // 字体大小设置 theme: "主题设置JSON" );

2. 从 File 对象加载

EpubScreen.fromFile( file: File("path/to/book.epub") );

3. 从 URI 加载

EpubScreen.fromUri( rootHref: "example.com/book.epub" );

加载完成后是BookScreen

  1. 阅读进度保存
  • 自动记录上次阅读位置
  • 支持书签功能
  • 可在不同设备间同步进度(使用 Firestore 存储时)
  1. 阅读设置
  • 字体大小调节
  • 主题切换
  • 自定义样式
  1. 交互功能
  • 文本选择
  • 页面导航
  • 进度跳转

2 读取EPUB

状态管理
  • 支持实时更新和状态同步
  • 使用 BLoC 模式管理主题和阅读器设置
  • 支持实时更新和状态同步
less 复制代码
  Widget buildWidgetWrapper(BuildContext context, Widget child,
          List<Link> spineItems, ServerStarted state) =>
      Stack(
        children: <Widget>[
          buildBackground(),
          child,
          Align(
            alignment: Alignment.bottomCenter,
            child: MultiBlocProvider(
              providers: [
                BlocProvider<ReaderThemeBloc>(
                  create: (_) => BlocProvider.of<ReaderThemeBloc>(context),
                ),
                BlocProvider<ViewerSettingsBloc>(
                  create: (_) => BlocProvider.of<ViewerSettingsBloc>(context),
                ),
              ],
              child: ReaderToolbar(
                readerContext: readerContext,
                onSkipLeft: publicationController.onSkipLeft,
                onSkipRight: publicationController.onSkipRight,
              ),
            ),
          ),
          // SafeArea(
          //   top: false,
          //   child: Align(
          //     alignment: Alignment.topCenter,
          //     child: ReaderAppBar(
          //       readerContext: readerContext,
          //       publicationController: publicationController,
          //     ),
          //   ),
          // ),
     
        ],
      );

1. 组件概述

这是一个用于 EPUB 电子书阅读的导航组件,文件名为 epub_navigator.dart 。它包含两个主要类:

  • EpubNavigator :继承自 PublicationNavigator 的 Widget 类
  • EpubNavigatorState :对应的 State 类,处理具体的导航逻辑
less 复制代码
@override
  Widget buildReaderView(List<Link> spine, ServerStarted serverState) =>
      PreloadPageView.builder(
        controller: epubController.pageController,
        scrollDirection: Axis.horizontal,
        // TODO Currently, with Hybrid Composition activated, preloadPagesCount > 1 provides erratic behavior.
        // To investigate!
        // preloadPagesCount: min(spine.length, 2),
        preloadPagesCount: 1,
        onPageChanged: epubController.onPageChanged,
        physics: const AlwaysScrollableScrollPhysics(),
        reverse: readerContext?.readingProgression?.isReverseOrder() ?? false,
        itemCount: spine.length,
        itemBuilder: (context, position) =>
            (Platform.isAndroid || Platform.isIOS)
                ? WebViewScreen(
                    address: serverState.address,
                    link: spine[position],
                    position: position,
                    readerContext: readerContext!,
                    publicationController: epubController,
                  )
                : const SizedBox.shrink(),
      );
}

主要特性:

  • 使用 PreloadPageView.builder 实现页面预加载
  • 水平滚动方向
  • 当前仅预加载 1 页(由于混合渲染模式下多页预加载存在问题)
  • 支持根据阅读方向反转页面顺序
  • 使用WebView来加载EPUB

3 功能解析

1. 整体架构
  • 采用了 Flutter 框架实现跨平台电子书阅读器
  • 主要支持 EPUB 和 CBZ 两种电子书格式
  • 使用 WebView 来渲染 EPUB 内容
  • 采用 BLoC 模式进行状态管理
2. 核心功能模块

阅读器导航

  • EpubNavigator 和 CbzNavigator 分别处理不同格式电子书的导航

  • 支持页面跳转、目录导航和书签功能

  • 通过 ReaderContext 管理阅读状态和上下文 EPUB 渲染

  • 使用 WebViewScreen 渲染 EPUB 内容

  • 支持自定义主题和排版设置

  • 实现了手势控制和页面切换 注释和高亮

  • 支持文本选择和高亮标注

  • 提供书签和注释功能

  • 可以保存和管理用户的标注 主题和设置

  • ReaderThemeBloc 管理阅读主题

  • ViewerSettingsBloc 处理阅读器设置

  • 支持自定义字体、颜色和排版

3. 关键类说明

EpubController

  • 控制 EPUB 阅读器的核心类

  • 管理页面控制器和阅读状态

  • 处理用户交互和导航 WebViewScreenState

  • 负责 EPUB 内容的渲染和显示

  • 处理 WebView 相关的事件和回调

  • 管理注释和高亮功能 ReaderContext

  • 维护阅读器的全局状态

  • 管理书签和注释

  • 处理阅读进度和位置信息

4. 特色功能
  • 支持多种电子书格式 (EPUB, CBZ)
  • 提供完整的注释和标注系统
  • 支持主题自定义和排版设置
  • 实现了跨平台兼容性
  • 提供流畅的阅读体验和手势控制
5. 数据持久化
  • 支持多种注释存储方式:
    • 内存存储 (InMemoryReaderAnnotationRepository)
    • SQLite 存储 (SqliteReaderAnnotationRepository)
    • Firestore 存储 (FirestoreReaderAnnotationRepository)

###页面跳转解析书签功能

webview_screen_state.dart

使用js的方式进行跳转 _jsApi?.openPage

scss 复制代码
   void _onPageFinished(InAppWebViewController controller, Uri? url) async {
    try {
      if (_jsApi == null || !mounted) {
        return;
      }
      // // 获取页面请求数据
      OpenPageRequest? openPageRequestData =
          _getOpenPageRequestFromCommand(readerContext.readerCommand);
      List<String> elementIds =
          readerContext.getElementIdsFromSpineItem(position);
      _jsApi?.setElementIds(elementIds);
      
      if (openPageRequestData != null) {
        _jsApi?.openPage(openPageRequestData);
      }

    // 如果存在跳转请求,执行页面跳转
      try {
        _jsApi?.setStyles(_readerThemeBloc.state.readerTheme,
            _viewerSettingsBloc.viewerSettings);
      } catch (e) {
        Fimber.d("Error setting styles", ex: e);
      }

      _updateSpineItemPosition(_currentSpineItemBloc.state);
      await _loadDecorations();
      await _loadBookmarks();
    } catch (e, stacktrace) {
      Fimber.d("Error in _onPageFinished", ex: e, stacktrace: stacktrace);
    }
  }


void _onPaginationInfo(PaginationInfo? paginationInfo) {
    if (currentSelectedSpineItem && paginationInfo != null) {
        // 更新书签
        _updateBookmarks(paginationInfo);
        // 通知当前位置变化
        readerContext.notifyCurrentLocation(paginationInfo, spineItem);
    }
}
  1. 直接跳转
  • 通过目录跳转到指定章节
  • 通过书签跳转到保存的位置
  • 通过进度条跳转到指定位置

文本选择和高亮标注

1 文本选择监听器在 simple_selection_listener.dart 中实现了基本的选择监听功能:

scss 复制代码
  @override
 void showHighlightPopup(Selection selection, HighlightStyle style, Color tint,
     {String? highlightId}) {
   _hideSelectionPopup();
   _highlightPopup = HighlightPopup(this);
   _highlightPopup!
       .showHighlightPopup(context, selection, style, tint, highlightId);
 }

Selection是选种的文本 HighlightStyle选择的样式 Color文本选种的颜色

  1. 文本选择:
  • 用户在WebView中选择文本时触发选择事件
  • SelectionListener监听选择事件并显示操作弹窗
  • 用户可以选择进行高亮标注或其他操作
  1. 高亮标注:
  • 用户选择高亮操作后,创建ReaderAnnotation对象保存标注信息
  • 使用annotationMarkTemplate生成高亮样式
  • 将高亮效果应用到WebView中的选中文本
  1. 标注管理:
  • 标注数据通过ReaderAnnotationRepository进行持久化存储
  • 支持查看、编辑和删除已有标注
  • 可以通过ReaderNavigationScreen查看所有标注列表

书签和注释功能实现 webview_screen_state.dart

加载书签功能使用**_jsApi?.initPagination()**

scss 复制代码
// 加载书签
Future<void> _loadBookmarks() async {
   _spineItemContext.bookmarks.addAll(
       await readerContext.readerAnnotationRepository.allWhere(
           predicate: AnnotationTypeAndDocumentPredicate(
               spineItem.href, AnnotationType.bookmark)));
   _jsApi?.initPagination();
}

注释功能在simple_selection_listener.dart

scss 复制代码
  @override
 void showAnnotationPopup(Selection selection,
     {HighlightStyle? style, Color? tint, String? highlightId}) async {
      // 隐藏其他弹窗
   hidePopup();
       // 清除文本选择
   jsApi?.clearSelection();
       
   // 设置默认样式和颜色
   style ??= HighlightStyle.highlight;
   tint ??= HighlightPopup.highlightTints[0];
       
   // 获取已有注释(如果是编辑模式)
   ReaderAnnotation? highlight;
   if (highlightId != null) {
     highlight = await readerAnnotationRepository.get(highlightId);
     style = highlight?.style ?? style;
     tint = highlight?.tint?.let((it) => Color(it)) ?? tint;
   }
       // 显示注释弹窗
   if (state.mounted) {
     AnnotationPopup.showAnnotationPopup(context, this, selection, style, tint,
         highlight?.annotation, highlightId);
   }
 }
}
相关推荐
DC...8 分钟前
vue滑块组件设计与实现
前端·javascript·vue.js
Mars狐狸16 分钟前
AI项目改用服务端组件实现对话?包体积减小50%!
前端·react.js
H5开发新纪元25 分钟前
Vite 项目打包分析完整指南:从配置到优化
前端·vue.js
嘻嘻嘻嘻嘻嘻ys26 分钟前
《Vue 3.3响应式革新与TypeScript高效开发实战指南》
前端·后端
恋猫de小郭41 分钟前
腾讯 Kuikly 正式开源,了解一下这个基于 Kotlin 的全平台框架
android·前端·ios
2301_7994049143 分钟前
如何修改npm的全局安装路径?
前端·npm·node.js
(❁´◡双辞`❁)*✲゚*1 小时前
node入门和npm
前端·npm·node.js
韩明君1 小时前
前端学习笔记(四)自定义组件控制自己的css
前端·笔记·学习
tianchang1 小时前
TS入门教程
前端·typescript
吃瓜群众i1 小时前
初识javascript
前端