方案一: webview 加载 epub.js解析
具体思路
- 编写小程序
webview 加载页 - 编写
webview H5页面,使用 epub.js 进行解析和渲染
1. 编写webview 加载页
import { WebView } from "@tarojs/components";
export default function Epub() {
const url = `${process.env.TARO_APP_WEB_URL}/#/pages/epubwebview/epubwebview`
return (
<WebView src={url}></WebView>
);
}
2. 编写 webview H5 页面
本示例只简单加载所有章节内容进行展示,需要复杂的目录展示、翻页加载、滚动加载,请查看 epub.js 官方 Examples 和 Doc
-
由于小程序真机环境
webview不允许加载iframe,所以无法通过epub.js的renderTo方法进行渲染,我们需要自己实现渲染 -
Epub必须从epubjs/dist/epub目录import,否则在webpack中无法打包 -
epubUrl,必须使用.opf格式,否则无法加载 -
.opf文件,用压缩工具解压 epub 文件,即可在目录中找到.opf文件 -
将
epub文件 解压后的目录,直接放在远程服务器上或对象存储上(即cos、oss等)
import { useDidShow } from "@tarojs/taro";
import { useRef, useState } from "react";
import { RichText, View } from "@tarojs/components";
import styles from "./epubweb.module.scss";
// 注意:这里的必须从 dist 目录加载,否在 webpack 中会无法打包
import Epub from "epubjs/dist/epub";
export default function Epubwebview() {
const toc = useRef([]);
const [section, setSection] = useState([]);
const [metadata, setMetadata] = useState({
title: "",
creator: "",
});
useDidShow(async () => {
// epuburl 文件地址,必须使用 opf 格式,下面的链接只是示例
const epubUrl = "https://xxx.cos.xxx/book/EPUB/content.opf";
const book = new Epub(epubUrl);
// 加载目录
const _toc = await book.loaded.navigation;
toc.current = _toc;
// 加载元数据
const _metadata = await book.loaded.metadata;
setMetadata(_metadata);
// 加载章节
await book.opened;
for (let i = 0; i < toc.current.length; i++) {
const tocItem = toc.current.toc[i];
await display(tocItem, i);
}
async function display(tocItem, i) {
let _section = book.spine.get(i);
if (_section) {
const html = await _section.render();
setSection((prev) => [...prev, { nodes: html, tocItem }]);
}
return section;
}
});
return (
<>
<View className={styles.epub}>
{/* 渲染元数据 */}
<View className={styles.metadata}>
<View className={styles.title}>{metadata.title}</View>
<View className={styles.cteator}>{metadata.creator}</View>
</View>
{/* 渲染章节 */}
{section.map((item, index) => (
<View key={index} className={styles.section}>
{/* 章节标题 */}
<View className={styles.title}>{item.tocItem?.label}</View>
{/* 章节内容 */}
<RichText nodes={item.nodes}></RichText>
</View>
))}
</View>
</>
);
}
3. 效果展示
方案二. Node 解析 Epub
采用node 解析 epub,小程序调用 node 解析 epub 接口加载html富文本渲染
- 此方案未进行实践,不确定效果如何
- 欢迎交流一下此方案