@bingtang-rn/react-native-pdf-light
v3.2.1
Published
适配鸿蒙版本,提供react_native_pdf_viewer组件。
Maintainers
Readme
@bingtang-rn/react-native-pdf-light for HarmonyOS
本项目基于 react-native-pdf-light 开发,为 React Native 鸿蒙(OpenHarmony)适配版本。如果在使用过程中有任何问题,可以在GitCode提Issue,会及时跟进。issue地址:issues。
版本对应关系
| 鸿蒙适配包版本 | 原始库版本 | 支持 RN 版本 | Autolink | 编译 API 版本 | | ------------ | ---------- | ------------ | -------- | ------------- | | 见发布记录 | 3.2.1 | 0.72+ | 是 | API17+ |
安装
npm install @bingtang-rn/react-native-pdf-light使用
import { Pdf, PdfView, PdfUtil, type PdfViewRef } from 'react-native-pdf-light';
// 整文档浏览(source 须为应用沙箱绝对路径)
<Pdf
source={path}
onError={(e: Error) => console.warn(e.message)}
onLoadComplete={(n: number) => console.log(`${n} pages`)}
/>;
// 单页渲染 + contain/fitWidth 切换
<PdfView
source={path}
page={0}
resizeMode="contain"
onError={(e) => console.warn(e.message)}
onLoadComplete={(e) => console.log(`${e.width}x${e.height}pt`)}
/>;
// 运行时更新标注(imperativeApplyAnnotation 命令)
const ref = useRef<PdfViewRef>(null);
ref.current?.setAnnotation(JSON.stringify([{ strokes: [...], text: [...] }]));
// 元信息
const count = await PdfUtil.getPageCount(path);
const sizes = await PdfUtil.getPageSizes(path);
// HarmonyOS-only:把 rawfile 资源拷到沙箱,PDF Kit 只认沙箱路径
const sandboxPath = await PdfUtil.copyAssetToFilesDir('sample.pdf');import 时使用原库名
'react-native-pdf-light',而非鸿蒙包名(由 RNOH alias 映射为@bingtang-rn/react-native-pdf-light)。
平台差异:
- HarmonyOS 上
source必须为应用沙箱绝对路径(filesDir/tempDir);rawfile资源需先拷到沙箱,可用 HarmonyOS-only 的PdfUtil.copyAssetToFilesDir(assetName)完成。 getPageSizes/onPdfLoadComplete返回的宽高单位为 PDF Points(1 英寸 = 72 点),与 iOS 一致;JS 层仅用宽高比做布局,单位差异不影响。- PDF Kit(
@kit.PDFKit)仅在 PhonePC/2in1Tablet 设备形态、API17+ 可用;不支持时<PdfView>会通过onError上报并显示提示,PdfUtil.*在调用时会 reject。
权限要求:
- 无需额外权限。PDF Kit 与应用沙箱文件读写均无
ohos.permission.*要求。
Link
| 版本 | 是否支持 Autolink | |------|------------------| | 当前版本 | 是 |
如使用版本支持 Autolink 且工程已接入,可跳过手动配置。
说明:本模块需要同时在 C++ 侧和 ETS 侧注册 Package。
1. Overrides RN SDK
在工程根目录 oh-package.json5 添加:
{
"overrides": {
"@rnoh/react-native-openharmony": "./react_native_openharmony"
}
}2. 引入原生端依赖
打开 entry/oh-package.json5,添加:
"dependencies": {
"@bingtang-rn/react-native-pdf-light": "file:../../node_modules/@bingtang-rn/react-native-pdf-light/harmony/pdf_light.har"
}执行 ohpm install。
3. 配置 CMakeLists
打开 entry/src/main/cpp/CMakeLists.txt,添加:
set(OH_MODULES "${CMAKE_CURRENT_SOURCE_DIR}/../../../oh_modules")
add_subdirectory("${OH_MODULES}/@bingtang-rn/react-native-pdf-light/src/main/cpp" ./pdf_light)
target_link_libraries(rnoh_app PUBLIC pdf_light)4. 注册 Package(C++ 侧)
打开 entry/src/main/cpp/PackageProvider.cpp,添加:
#include "PdfLightPackage.h"
std::vector<std::shared_ptr<Package>> PackageProvider::getPackages(Package::Context ctx) {
return {
std::make_shared<PdfLightPackage>(ctx),
};
}5. 注册 Package(ETS 侧)
打开 entry/src/main/ets/RNPackagesFactory.ets,添加:
import { PdfLightPackage } from '@bingtang-rn/react-native-pdf-light/ts';
export function createRNPackages(ctx: RNPackageContext): RNPackage[] {
return [
new PdfLightPackage(ctx),
];
}属性 / API
| API | 描述 | 参数 | 返回值 | HarmonyOS 支持 | |-----|------|------|--------|----------------| | PdfUtil.getPageCount | 获取 PDF 总页数 | source: string | Promise | ✅ 完全支持 | | PdfUtil.getPageSizes | 获取每页尺寸(宽高,Points) | source: string | Promise<{width,height}[]> | ✅ 完全支持 | | PdfUtil.copyAssetToFilesDir | 拷贝 rawfile 到沙箱并返回绝对路径(HarmonyOS-only) | assetName: string | Promise | ✅ 完全支持 | | source | PDF 沙箱路径 | string | — | ✅ 完全支持 | | page | 页码(0-indexed) | number | — | ✅ 完全支持 | | resizeMode | 缩放模式 | 'contain' | 'fitWidth' | — | ✅ 完全支持 | | annotation | PAS v1 标注文件路径 | string | — | ✅ 完全支持 | | annotationStr | PAS v1 标注 JSON 字符串 | string | — | ✅ 完全支持 | | onError | 加载/渲染失败回调 | (e: {message}) => void | — | ✅ 完全支持 | | onLoadComplete | 加载完成回调(页面 pt 尺寸) | (e: {width,height}) => void | — | ✅ 完全支持 | | setAnnotation | 运行时更新标注(imperativeApplyAnnotation 命令) | annotation: string | void | ✅ 完全支持 | | source | PDF 沙箱路径 | string | — | ✅ 完全支持 | | annotation / annotationStr | PAS v1 标注 | string | — | ✅ 完全支持 | | onError / onLoadComplete | 错误 / 加载完成(页数)回调 | (e?) => void | — | ✅ 完全支持 | | onMeasurePages | 每页显示高度与偏移回调 | (m: PageMeasurement[]) => void | — | ✅ 完全支持 | | shrinkToFit | 单页最大高度限制方向 | 'never'|'portrait'|'landscape'|'always' | — | ✅ 完全支持 | | ref.scrollToIndex / scrollToOffset | 滚动到页 / 偏移 | index | offset: number | void | ✅ 完全支持 | | | 可捏合缩放单页(深导入 /Zoom) | PdfViewProps + maximumZoom? 等 | — | ⚠️ 部分支持 |
平台差异
- HarmonyOS 上
source必须为应用沙箱绝对路径(filesDir/tempDir);rawfile 须先用PdfUtil.copyAssetToFilesDir拷出。 getPageSizes/onPdfLoadComplete的宽高单位为 PDF Points(与 iOS 一致;JS 层仅用宽高比做布局)。- PDF Kit(
@kit.PDFKit)仅在 PhonePC/2in1Tablet 设备形态、API17+ 可用;不支持时<PdfView>通过onError上报并显示提示,PdfUtil.*在调用时会 reject。
未实现 / 受限功能
| API | 原因 |
|-----|------|
| pinch 缩放 | JS 源码完整保留,但 example 未演示:依赖 react-native-gesture-handler(已有鸿蒙适配版)未装到 example,pinch focalPoint/Scale、Animated 多节点运算、双向 ScrollView 协调、useNativeDriver:false 需真机验证后再定。底层 <PdfView> 已可用,可作为其渲染容器。 |
| C++ ShadowNode 自定义 measure + State 推回 | RNOH Fabric 用 ArkUI 布局 + ETS 实现,不重写 C++ ShadowNode;由 JS 层 getPageSizes 驱动 getItemLayout + 原生 onAreaChange 等价实现,视觉/行为无差异。 |
| 单页渲染 SLICES 切片防 OOM | 鸿蒙 getAreaPixelMap 一次性返回完整 PixelMap,无切片 API;bitmap 尺寸由视图尺寸驱动并按 vp2px 渲染到屏幕物理像素、上限 4096 防超大页 OOM。常规 A4 页 + 屏幕尺寸足够。 |
使用限制
PdfDocument.loadDocument不支持重复调用,二次加载前必须releaseDocument(库内已 try/finally 保证)。- 需 HarmonyOS SDK API17+ 且设备形态为 PhonePC/2in1Tablet。
快速验证(运行 Example)
前置条件
| 依赖 | 版本要求 | |------|----------| | Node.js | >= 18 | | DevEco Studio | 5.0+ / 6.0+ | | HarmonyOS SDK | API 17+ |
运行步骤
1. 克隆仓库
git clone <仓库地址>
cd <仓库目录>2. 安装依赖并构建
npm install --legacy-peer-deps
npm pack # 生成 tgz 包(会自动触发 prepare 构建 JS 产物)3. 进入 example 目录,安装依赖
cd example
npm install --legacy-peer-deps4. 生成 JS Bundle
npm run dev产物:harmony/entry/src/main/resources/rawfile/bundle.harmony.js
5. 用 DevEco Studio 打开鸿蒙工程
- 打开 DevEco Studio
- 选择
example/harmony目录 - 等待 Sync 完成
6. 编译并运行 HAP
在 DevEco Studio 中点击运行按钮,将 HAP 安装到设备/模拟器。
注意:Example 中已预置插件依赖和 Package 注册,无需手动配置 Link。
约束与限制
兼容性
- RNOH: 0.72+
- HarmonyOS SDK: API 17+
- DevEco Studio: 5.0+
遗留问题
无(或列出已知问题)
开源协议
本项目基于 [原始库协议](原始库 LICENSE 链接),详见 LICENSE 文件。
