uniapp开发epub阅读器保姆级教程

前言

阅读器的基本功能:翻页、字体大小设置、切换背景主题色、进度条功能、目录与跳转、添加书签、获取电子书信息、获取当前章节总页码和页数等

功能的实现

 1.引入epubjs

使用命令安装0.3.71版本epubjs:

npm i [email protected]

注:这里之前踩过坑,其他版本进行切换主题时,每一个背景颜色只能切换一次,再次选择其他主题不生效。

解决方法:将版本更换到 0.3.71

2.为电子书准备容器

添加一个id为read的view标签。

3.渲染电子书

在onLoad生命周期中对电子书进行渲染。

通过new一个Epub对电子书进行初始化解析,生成book。

onLoad() {
    this.showEpub();
},

methods:{
    showEpub(){
        // 对电子书进行初始化解析,路径可以是相对路径或者绝对路径
        this.book = new Epub("https://mp-9281e2b4-5558-4603-841a-433fcefa275b.cdn.bspapp.com/cloudstorage/108ca182-d460-4f65-be1b-5819d82d4dfd.epub"
       );
    }
}

有了电子书的路径后,对电子书进行渲染。

1.book通过renderTo方法对电子书进行渲染,生成rendition对象。

2.renderTo有两个参数:第一个参数是view标签的id,将生成的dom挂在该id的容器上;第二个参数是用来指定电子书的样式和属性,包括宽高,翻页方式等。

3.rendition再通过display方法渲染完成,display支持两种参数:①章节目录中的href链接,可以跳转至指定章节;②cfi值,为epubcfi规范的一个值,不用细究他的构成,能获取到就行。display后面不传参数时默认为0,渲染到首页。

showEpub(){
    // 通过new一个Epub对电子书进行初始化解析,生成book,路径可以是相对路径或者绝对路径
    this.book = new Epub("https://mp-9281e2b4-5558-4603-841a-433fcefa275b.cdn.bspapp.com/cloudstorage/108ca182-d460-4f65-be1b-5819d82d4dfd.epub");

    // book通过renderTo方法对电子书进行渲染,生成rendition对象
    this.rendition = this.book.renderTo("read",{
        allowScriptedContent: true,
        snap: true,
        restore: false,
        width: "100vw",
        height: "100vh",
        manager: "continuous",
        spread: "none",
        flow:
          this.flowIndex === 0
            ? "scrolled-doc"
            : this.flowIndex === 1
            ? "paginated"
            : "", //scrolled-doc滚动 paginated分页
    })   

    // 通过display方法进行渲染
    this.rendition.display()
}

4.翻页功能

此处为点击翻页功能,可以为点击屏幕左侧25%,或者点击屏幕右侧25%进行翻上一页和下一页操作。

翻页方法会返回一个promise,进行后续的操作。

// 上一页
prevPage() {
    if (this.rendition) {
        this.rendition.prev().then(() => {
          // 其他逻辑代码
        });
    }
},

// 下一页
nextPage() {
    if (this.rendition) {
        this.rendition.next().then(() => {
          // 其他逻辑代码
        });
    }
},

5.字体大小设置

定义一个theme,通过rendition中的Theme对象属性进行字号主题等功能设置。

在这里可以用一个进度条控件,动态设置fontsize大小,并且保存到缓存中,以便下次进入电子书时获取字体大小。字体大小单位为"px"。

this.themes = this.rendition.themes
this.themes.fontSize(this.fontsize + "px")

 6.切换背景主题色

与字体大小设置一样,切换主题时用的也是theme对象属性。

通过theme.register()为电子书添加主题,通过theme.select(name)选择已经添加好的主题。

// data中定义好主题数组
themeList:[
    {
        name: "default", // 主题名字
        style: { // 主题样式
            body: {
              color: "#494948", // 文字颜色
              background: "#F4F3EF", // 背景颜色
              lineColor: "#E4E3DF", // 主题中并无该属性,该属性为自定义目录下划线颜色
            },
        },
    },
    {
        name: "twoTheme",
        style: {
            body: {
              color: "#39342B",
              background: "#D5C6A9",
              lineColor: "#C6B89B",
            },
        },
    },
    {
        name: "threeTheme",
        style: {
            body: {
              color: "#94938F",
              background: "#3A3031",
              lineColor: "#3F3939",
            },
        },
    },
    {
        name: "fourTheme",
        style: {
            body: {
              color: "#313635",
              background: "#CCE8D1",
              lineColor: "#BCD8C1",
            },
        },
    },
    {
        name: "fiveTheme",
        style: {
            body: {
              color: "rgb(100,110,119)",
              background: "#051827",
              lineColor: "#0C1E2D",
            },
        },
    },
]


methods:{
    // 渲染电子书后调用
    registerTheme() {
      this.themeList.forEach((item) => {
        this.themes.register(item.name, item.style);
      });
    },
    // 触发改变电子书背景主题时调用
    setTheme(index) {
      this.themes.select(this.themeList[index].name);
    },
}

7.进度条功能

1.进度条功能需要获取locations对象,由于locations对象的生成比较消耗性能,所以默认是不会生成locations对象的。

2.通过epubjs的钩子函数来实现。借助book解析完成之后回调的ready方法来生成。

3.通过book的locations.cfiFromPercentage()方法获取当前百分比所对应的epubcfi,通过this.rendition.display(epubcfi)渲染即可跳到相应位置。

注:在进度条可操作之前,必须是分页执行完之后得到location对象才可对进度条进行操作。(可添加一标识,判断locations对象是否得到,未得到时提示进度条加载中,完成后显示在操作)。

showEpub(){
    // 通过new一个Epub对电子书进行初始化解析,生成book,路径可以是相对路径或者绝对路径
    this.book = new Epub("https://mp-9281e2b4-5558-4603-841a-433fcefa275b.cdn.bspapp.com/cloudstorage/108ca182-d460-4f65-be1b-5819d82d4dfd.epub");

    // book通过renderTo方法对电子书进行渲染,生成rendition对象
    this.rendition = this.book.renderTo("read",{
        allowScriptedContent: true,
        snap: true,
        restore: false,
        width: "100vw",
        height: "100vh",
        manager: "continuous",
        spread: "none",
        flow:
          this.flowIndex === 0
            ? "scrolled-doc"
            : this.flowIndex === 1
            ? "paginated"
            : "", //scrolled-doc滚动 paginated分页
    })   

    // 通过display方法进行渲染
    this.rendition.display()

    this.book.ready
        .then(() => {
          return this.book.locations.generate();
        })
        .then((result) => {
          // result为book生成电子书的cfi的一个数组。与下面this.locations中的_locations属性一致
          this.locations = this.book.locations;
          console.log("locations", this.locations);
          // bookAvailable标识,默认为false,为true时代表进度条可操作
          this.bookAvailable = true;
        })
}

调整进度条跳转至对应页面。

onProgressChange(e) {
    // e为进度条保留两位小数点的数字
    const percentage = e / 100;
    // location为根据进度生成的cfi值
    const location =
        percentage > 0 ? this.locations.cfiFromPercentage(percentage) : 0;
    console.log("location", location);
    this.rendition.display(location);
},

8.目录与跳转

1.通过book的navigation对象,可以获取到电子书的目录。

2.通过epubjs的钩子函数来实现。借助book解析完成之后回调的ready方法来生成。

3.由于目录为一个tree类型,所以页面上需用tree组件来渲染。

this.book.ready
    .then(() => {
        this.navigation = this.book.navigation;
        // toc为总目录,目录可分级
        this.toc = this.book.navigation.toc;
        return this.book.locations.generate();
     })
     .then((result) => {
          // result为book生成电子书的cfi的一个数组。与下面this.locations中的_locations属性一致
          this.locations = this.book.locations;
          console.log("locations", this.locations);
          // bookAvailable标识,默认为false,为true时代表进度条可操作
          this.bookAvailable = true;
      })

Navigation.toc表示电子书的目录结构,是一个数组,toc下的每一个元素对应一个目录,toc[n].href表示目录路径(链接),toc[n].label是当前目录的名字,toc[n].subitems里面包含的是该目录下还有其他的二级(三级)目录,可根据需要使用几级目录。

获取到目录后,可以通过点击树组件中的章节获取到该章节对应的数据(toc数组中某一项),再根据该项中的href属性进行跳转。

jumpTo(item){
    this.rendition.display(item.href)
}

9.添加书签

添加书签功能需要使用到rendition对象中的currentLocation方法。

currentLocation.start.cfi为当前页的cfi值,可根据该cfi值进行跳转。

// 获取当前页cfi值并保存到数组中
handleMark() {
    const currentLocation = this.book.rendition.currentLocation();
    this.bookmarks.push(currentLocation.start.cfi);
},
// 点击,根据cfi值跳转
toMark(cfi) {
    this.rendition.display(cfi)
},

 10.获取电子书信息

通过book中的package对象获取电子书信息:

1.manifest用来获取电子书的所有用到的文件信息;

2.metadata用来获取电子书的出版信息,其中titile为电子书的名字;

3.ncxPath为目录的路径;

4.spine为阅读顺序。

this.book.loaded.metadata.then((meta) => {
    console.log("meta", meta);
    this.meta= meta;
});

11.获取当前章节页码和总页数

获取当前章节页码和总页数与添加书签功能一样需要用到rendition对象中的currentLocation方法。

total:当前章节总页数;

page:当前页在当前章节页码。

showPage(page) {
    const currentLocation = this.book.rendition.currentLocation();
    console.log("当前位置", {
        ...currentLocation.start.displayed,
    });
    this.bookInfo.pageInfo = {
        total: page?.total || currentLocation.start.displayed.total,
        page: page?.page || currentLocation.start.displayed.page,
    };
},

总结

以上就完成了基于epubjs开发的基本的阅读器功能,样式和点击事件部分可以由各位根据需求来添加,如有问题和错误之处欢迎指出~

 

你可能感兴趣的:(uni-app)