更新记录
1.0.0(2026-09-18)
平台兼容性
uni-app x(5.25)
| Chrome |
Safari |
Android |
iOS |
鸿蒙 |
微信小程序 |
| - |
- |
√ |
√ |
√ |
√ |
其他
st-page-flip-canvas
基于 StPageFlip 核心算法深度移植的 uni-app X 原生 Canvas 2D 3D 仿真翻书组件。
具备逼真的纸张弯曲物理效果、动态高光阴影以及顺滑的手势拖拽体验。
✨ 特性一览
- 📖 仿真 3D 纸张物理形变:精确的纸张翻卷几何与光影计算,逼真模拟真实书本翻阅手感。
- ⚡ 原生 Canvas 2D 高效渲染:基于 uni-app X / UTS 开发,深度适配多端,高帧率平滑过渡。
- 📐 确定性尺寸管线:支持外部容器显式尺寸传入与内部自动计算,彻底杜绝自适应导致的页面重排与闪烁。
- 📱 多端手势体系适配:
- 内置原生 Touch/Mouse 手势支持(点击翻页、滑动翻页、拖拽卷角)。
- 提供外部手势注入接口(
startTouch、moveTouch、endTouch),完美兼容微信小程序 Skyline 手势协商机制。
- 🔄 智能图片增量更新:内置 URL 差异对比机制,在图片逐步下载、画质升级或按需加载时仅重绘变化页,避免整书重建导致重置回第 0 页。
- 🖥️ 单双页自适应 (Spread Mode):支持移动端单页竖屏、桌面/平板双页并排横屏显示,支持封面 (Cover) 特殊渲染。
平台兼容性
| App-Android |
App-iOS |
Web / H5 |
微信小程序 |
其他小程序 |
| ✅ 支持 |
✅ 支持 |
✅ 支持 |
✅ 支持 (Canvas 2D) |
需支持 Canvas 2D |
提示:本组件专为 uni-app X 打造,编写语言为 .uvue 和 .uts。
快速上手
由于基于 uni_modules 规范开发,符合 easycom 自动导入机制,安装后在页面中直接使用 <st-page-flip-canvas> 标签即可。
基础示例
<template>
<view class="container">
<st-page-flip-canvas
ref="flipRef"
canvas-id="myBookCanvas"
:images="imageList"
:canvas-width="700"
:canvas-height="500"
:flipping-time="800"
:show-cover="true"
@flip="onPageFlip"
@init="onBookInit"
/>
<view class="controls">
<button @click="prev">上一页</button>
<button @click="next">下一页</button>
</view>
</view>
</template>
<script setup lang="uts">
import { ref } from 'vue'
const flipRef = ref<any | null>(null)
// 准备展示的图片列表(支持本地路径与网络路径)
const imageList = ref<string[]>([
'/static/pages/cover.jpg',
'/static/pages/page1.jpg',
'/static/pages/page2.jpg',
'/static/pages/page3.jpg',
'/static/pages/back.jpg'
])
function onBookInit(data: any) {
console.log('书本初始化完成:', data)
}
function onPageFlip(pageIndex: number) {
console.log('当前页码变更:', pageIndex)
}
function prev() {
flipRef.value?.flipPrev()
}
function next() {
flipRef.value?.flipNext()
}
</script>
<style>
.container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 20px;
}
.controls {
display: flex;
flex-direction: row;
margin-top: 20px;
gap: 16px;
}
</style>
属性说明 (Props)
| 属性名 |
类型 |
默认值 |
必填 |
说明 |
images |
Array<string> |
[] |
是 |
书本页面图片列表(网络 URL 或本地绝对路径) |
canvasWidth |
Number |
0 |
建议 |
画布展示区域的 CSS 逻辑宽度 (px)。设置后启用确定性尺寸管线 |
canvasHeight |
Number |
0 |
建议 |
画布展示区域的 CSS 逻辑高度 (px)。设置后启用确定性尺寸管线 |
width |
Number |
400 |
否 |
单页基准逻辑宽度(比例参考) |
height |
Number |
600 |
否 |
单页基准逻辑高度(比例参考) |
spreadMode |
Number |
0 |
否 |
每屏显示页数:0 自动判定,1 单页模式 (Portrait),2 双页展开模式 (Landscape) |
startPage |
Number |
0 |
否 |
起始页码(从 0 开始) |
showCover |
Boolean |
false |
否 |
是否启用硬皮封面模式(首尾两页单页显示且质感为硬壳) |
flippingTime |
Number |
1000 |
否 |
翻页平滑动画时长 (ms) |
drawShadow |
Boolean |
true |
否 |
是否绘制纸张翻转时的逼真阴影和背脊阴影 |
maxShadowOpacity |
Number |
1 |
否 |
阴影最大透明度(范围 0 ~ 1,建议 0.3 ~ 0.5 观感更自然) |
swipeDistance |
Number |
30 |
否 |
触发滑动手势翻页的最小像素滑动阈值 |
showPageCorners |
Boolean |
true |
否 |
鼠标/手势靠近书角时是否自动轻微翘起书角 |
disableFlipByClick |
Boolean |
false |
否 |
是否禁用点击书本任意处直接翻页(设为 true 则仅能通过拖拽/滑动翻页) |
autoSize |
Boolean |
true |
否 |
是否自动缩放适配父容器尺寸 |
usePortrait |
Boolean |
true |
否 |
是否允许自动切换到单页纵向显示 |
canvasId |
String |
'stPageFlipCanvas' |
否 |
Canvas 组件 ID,页面中存在多个实例时请保持唯一 |
事件说明 (Events)
| 事件名 |
回调参数 |
说明 |
@init |
{ page: number, mode: string } |
画布及书本初始化完成时触发,返回当前页码和当前单双页模式 |
@flip |
pageIndex: number |
页码发生翻页切换时触发,返回翻转后的当前页索引(从 0 开始) |
@changeState |
state: string |
翻页状态变更时触发。可选值:'read' (静止阅读), 'user_fold' (手动拖拽), 'fold_corner' (折角), 'flipping' (动画翻页中) |
@changeOrientation |
orientation: string |
书本排版方向变化时触发:'portrait' (单页), 'landscape' (双页) |
实例方法 (Methods)
通过在组件上绑定 ref="flipRef" 即可调用内部提供的实例方法:
| 方法名 |
参数 |
说明 |
flipNext() |
(corner?: FlipCorner) |
播放动画翻到下一页(可选触发角 FlipCorner.TOP / FlipCorner.BOTTOM) |
flipPrev() |
(corner?: FlipCorner) |
播放动画翻到上一页 |
turnToPage(page) |
page: number |
立即跳转到指定页(无翻页过渡动画) |
startTouch(x, y) |
x: number, y: number |
外部注入手势开始事件(用于对接微信小程序 Worklet 等手势组件) |
moveTouch(x, y) |
x: number, y: number |
外部注入手势移动事件 |
endTouch(x, y, isSwipe) |
x: number, y: number, isSwipe: boolean |
外部注入手势抬起/结束事件 |
进阶:高级手势对接(微信小程序 Skyline)
在微信小程序中,如需配合 <horizontal-drag-gesture-handler> 进行手势冲突管理,可结合组件暴露的方法使用:
<horizontal-drag-gesture-handler
tag="flipGesture"
worklet:ongesture="onFlipGesture"
>
<st-page-flip-canvas
ref="flipRef"
canvas-id="flipCanvas"
:images="images"
:canvas-width="canvasWidth"
:canvas-height="canvasHeight"
:disable-flip-by-click="true"
@flip="onFlip"
/>
</horizontal-drag-gesture-handler>
注意事项
- 网络图片跨域:在 Web / 小程序端加载网络图片时,需确保图片 CDN 开启了 CORS 跨域头,小程序端需配置合法域名。
- 尺寸测量:推荐使用
:canvas-width 与 :canvas-height 传入确切的像素尺寸(可根据屏幕宽高在页面 onReady 时计算出保持书本宽高比的尺寸),避免异步测量导致的视觉抖动。