电子书阅读器(StPageFlip)

195 阅读4分钟

主要介绍了 StPageFlip 库,介绍了一些基本特性和参数,实现了两个 demo:图片仿真翻页和文本仿真翻页效果

其他系列文章:

StPageFlip

强大、简单且灵活的 JS 库,用于创建逼真而精美的页面翻页效果。

可以用来作为电子书阅读器的基础,在其基础上进行功能扩展。

最主要的功能是有仿真翻页效果,turn.js也可以,都可以尝试一下。

官网地址:nodlik.github.io/StPageFlip/

Github 地址:github.com/Nodlik/StPa…

  1. 特征
    • 可处理 Canvas 上的简单图像及复杂的 HTML 块
    • 提供简洁的 API 与灵活的配置
    • 兼容移动设备
    • 支持横屏与竖屏显示模式
    • 支持软页和硬页类型(仅限 HTML 模式)
      • 软页面:模拟真实纸张的柔软翻页效果,过渡自然。例如:小说、杂志等连续阅读
      • 硬页面:呈现更挺括的翻页质感,适合结构化内容。例如:教科书、操作手册等
    • 零依赖
  2. 渲染模式
    • Canvas 模式:适合静态图片展示,性能优化好
    • HTML 模式:支持复杂交互内容,可嵌套 DOM 元素
    • 混合模式:关键内容使用 HTML,背景使用 Canvas

react-pageflip

该插件支持 react,可以在 react 中使用,官方文档为:nodlik.github.io/react-pagef…

# npm安装
npm install react-pageflip
# pnpm安装
pnpm add react-pageflip

参数说明:

属性名 类型 默认值 说明
width number -(必填) 页面基础宽度
height number -(必填) 页面基础高度
size ("fixed", "stretch") "fixed" 书籍是否在父元素下拉伸
minWidth, maxWidth, minHeight, maxHeight number - size 为 "stretch" 时需设置的阈值
drawShadow bool true 翻页时是否绘制阴影
flippingTime number(毫秒) 1000 翻页动画时间
usePortrait bool true 是否启用切换到竖屏模式
startZIndex number 0 z 轴索引初始值
autoSize bool true 若为 true,父元素大小将与书籍大小一致
maxShadowOpacity number [0..1] 1 阴影强度(1 为最大强度,0 为隐藏阴影)
showCover boolean false 若为 true,第一页和最后一页将标记为封面封底,并以单页模式显示
mobileScrollSupport boolean true 在移动设备上触摸书籍时是否禁用内容滚动

方法说明:

方法名 参数 返回值 说明
getPageCount number 获取总页数
getCurrentPageIndex number 获取当前页码(从 0 开始)
turnToPage pageNum: number void 跳转到指定页码(无动画)
turnToNextPage void 跳转到下一页(无动画)
turnToPrevPage void 跳转到上一页(无动画)
flip pageNum: number, corner: 'top' | 'bottom' void 以动画形式跳转到指定页码
flipNext corner: 'top' | 'bottom' void 以动画形式跳转到下一页
flipPrev corner: 'top' | 'bottom' void 以动画形式跳转到上一页
loadFromImages images: ['path-to-image'...] void 从图片加载页面
loadFromHtml items: NodeListOf | HTMLElement[] void 从 HTML 元素加载页面
updateFromHtml items: NodeListOf | HTMLElement[] void 从 HTML 元素更新页面(0.4.0 新增)
updateFromImages images: ['path-to-image1.jpg', ...] void 从图片更新页面(0.4.0 新增)
destroyvoid 移除父 HTML 元素及所有事件处理程序

图片仿真预览

实现 pdf 图片仿真预览:首先将 pdf 全部拆分为图片,然后使用 react-pageflip 实现仿真翻页效果。

如下为基础 demo 示例:模拟数据来源为 ebookImg.json

import { EBOOK_IMG_LIST } from "@/_mock/book";
import HTMLFlipBook from "react-pageflip";
import { styled } from "styled-components";

export default function PageFlip() {
  return (
    <Container>
      <HTMLFlipBook
        width={298}
        height={420} // 按照图片原宽高比例
        showCover={true} // 启用封面封底单页模式
        size="fixed" // 必须指定尺寸模式
        startPage={0} // 设置初始页码
        className="flip-book"
        onFlip={(e) => console.log(`翻页至第 ${e.data + 1} 页`)}
      >
        {EBOOK_IMG_LIST.map((o: any) => (
          <div className="demoPage" key={o.pageId}>
            <img src={o.imgUrl} alt="图片" />
          </div>
        ))}
      </HTMLFlipBook>
    </Container>
  );
}

const Container = styled.div`
  .demoPage {
    > img {
      // 图片比例为298/420
      // aspect-ratio: 298 / 420;
      width: 100%;
      height: 100%;
    }
  }
`;

渲染效果,如图 ebook-1.png 所示:

ebook-1.png

文本仿真预览

实现文本仿真预览:将章节文本内容拆分为页,然后使用 react-pageflip 实现仿真翻页效果。

如下为基础 demo 示例:模拟数据来源为 ebookTxt.json

import { EBOOK_TEXT_LIST } from "@/_mock/book";
import HTMLFlipBook from "react-pageflip";
import { styled } from "styled-components";

export default function PageFlip() {
  return (
    <Container>
      <HTMLFlipBook
        width={298}
        height={419} // 按照图片原宽高比例
        showCover={false} // 封面特效
        size="fixed" // 必须指定尺寸模式
        startPage={0} // 设置初始页码
        className="flip-book"
        onFlip={(e) => console.log(`翻页至第 ${e.data + 1} 页`)}
      >
        {EBOOK_TEXT_LIST.map((o: any, idx) => (
          <div className="demoPage" key={o.id}>
            <p>第{idx + 1}页</p>
            <p>{o.text}</p>
          </div>
        ))}
      </HTMLFlipBook>
    </Container>
  );
}

const Container = styled.div`
  .demoPage {
    border: 1px solid #ccc;
    background-color: rgb(224, 236, 224);
    padding: 24px;
  }
`;

渲染效果,如图 ebook-2.png 所示:

ebook-2.png