@hxa-rn/react-native-photo-editor
v1.0.0
Published
React Native: Native Photo Editor
Readme
react-native-photo-editor
react-native-photo-editor 基于上游 react-native-photo-editor 开发。如果在使用过程中有任何问题,欢迎在GitCode提交Issue,会及时跟进。
项目介绍
react-native-photo-editor 为 React Native 应用提供全屏图片编辑能力:JS 侧一次调用 PhotoEditor.Edit(props) 即可拉起原生全屏编辑界面,支持涂鸦(画笔/橡皮擦/撤销)、文本、贴纸/Emoji、裁剪旋转、保存(覆盖写回源图或另存系统相册)与系统分享,编辑完成后按结果回吐 onDone/onCancel 回调。
react-native-photo-editor 是 OpenHarmony 适配版,JS 侧仍使用上游包名 react-native-photo-editor,鸿蒙侧 ohpm 包名为 @oh-rn/react-native-photo-editor。适配面包括:
- 1 个 TurboModule:
RNPhotoEditor - 1 个 TurboModule 方法:
Edit - 2 个回调:
onDone/onCancel - 4 个 props 字段:
path/colors/hiddenControls/stickers - 1 套 HAR 导出的 ArkUI 编辑页组件(需宿主声明 Ability 装载)
集成指南
本节用于接入已有 RN 鸿蒙应用;运行本仓库示例请参见「快速验证(运行 Example)」。
1. 安装适配包
当前 npm 适配包为 @hxa-rn/[email protected],业务别名为 react-native-photo-editor。在 RN 应用根目录执行:
npm install @hxa-rn/[email protected] --save-exact --legacy-peer-depspeerDependencies:{"react-native":">=0.72"}。还需已有可运行的 RNOH 宿主工程。
2. 配置 Metro 并导入
适配包已声明 harmony.alias。宿主 metro.config.js 合并以下配置,并保留原有的自定义设置:
const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');
const {createHarmonyMetroConfig} = require('@react-native-oh/react-native-harmony/metro.config');
module.exports = mergeConfig(
getDefaultConfig(__dirname),
createHarmonyMetroConfig({
reactNativeHarmonyPackageName: '@react-native-oh/react-native-harmony',
}),
);业务代码:
import PhotoEditor from 'react-native-photo-editor';3. 注册鸿蒙原生模块
本包声明了 Autolinking 元数据:CMake 目标 photo_editor,ohpm 包 @oh-rn/react-native-photo-editor,C++ / ETS 类 PhotoEditorPackage。宿主启用 RNOH Autolinking 后,应检查生成的 HAR 依赖、CMake 链接及 C++ / ETS Package 注册是否齐全;已自动注册时不要重复手动注册。
Autolinking 不可用时,保留宿主已有配置,补齐以下四处:
- 在
harmony/entry/oh-package.json5的dependencies追加下项,然后在harmony/entry执行ohpm install并同步工程:
"@oh-rn/react-native-photo-editor": "file:../../node_modules/@hxa-rn/react-native-photo-editor/harmony/photo_editor.har"- 在
harmony/entry/src/main/cpp/CMakeLists.txt添加子目录,并在已有add_library(rnoh_app ...)之后链接:
set(OH_MODULE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../oh_modules")
add_subdirectory("${OH_MODULE_DIR}/@oh-rn/react-native-photo-editor/src/main/cpp" ./photo_editor)
# 放在 rnoh_app 目标创建之后:
target_link_libraries(rnoh_app PUBLIC photo_editor)- 在
PackageProvider.cpp添加头文件,并把实例加入已有getPackages返回集合(本仓库模板可加入ManualLinkingPackage列表):
#include "PhotoEditorPackage.h"
// 加入已有 Package 集合:
std::make_shared<rnoh::PhotoEditorPackage>(ctx)- 在
harmony/entry/src/main/ets/RNPackagesFactory.ets添加默认导入,并把实例加入已有createRNPackages返回数组:
import PhotoEditorPackage from '@oh-rn/react-native-photo-editor';
// 加入 createRNPackages(ctx) 返回数组:
new PhotoEditorPackage(ctx)确保宿主 RNApp 使用上述 createRNPackages,并启用 enableCAPIArchitecture: true。完成后重新生成宿主 Bundle、构建并安装 HAP;只刷新 JS 不会加载新增的原生模块。若 HAR 内 RNOH 相对依赖无法解析,在宿主鸿蒙根 oh-package.json5 的 overrides 中将 @rnoh/react-native-openharmony 指向宿主正在使用的同一 RNOH HAR,勿混用 debug/release 或不同版本。
4. 声明宿主 Ability(HAR 不能声明 Ability,本库唯一需要手动接线的一步)
HAR 不能自行声明 Ability,宿主必须自行声明并提供实现:
module.json5中新增一个exported: false的 Ability 条目(如PhotoEditorAbility),srcEntry指向宿主自己实现的入口文件;- 该入口文件里创建一个
@Entry页壳装载本 HAR 导出的PhotoEditorPage组件,并把页面的onBackPress()转发给 HAR 导出的PhotoEditorController.onBackPress()(否则系统返回键无法正确触发onCancel); - 如需使用资源名方式的
stickers(与上游 Android/iOS 写法一致,如stickers: ['sticker1']),需在 Ability 的onCreate中调用本库导出的registerStickerResolver(createRawfileStickerResolver(this.context.resourceManager)),并把对应贴纸图放入宿主resources/rawfile/;未接线时资源名会回退为「按完整路径」语义处理,不会静默失败。
未完成本步接线时,Edit 调用会因拉不起编辑页而回 onCancel。
可参照当前仓库的 PhotoEditorAbility 及 example 的页面与 main_pages.json 配置迁移宿主接线。
使用说明
最小调用
import PhotoEditor from 'react-native-photo-editor';
PhotoEditor.Edit({
path: '/data/storage/el2/base/haps/entry/files/photo.jpg',
onDone: (imagePath: string) => console.log('saved ->', imagePath),
onCancel: (resultCode: number) => console.log('cancelled, code =', resultCode),
});完整调用
PhotoEditor.Edit({
path: 'file:///data/storage/el2/base/haps/entry/files/photo.png', // file:// 前缀会被内部剥离
colors: ['#000000', '#f00', '#80FF0000'], // 支持 #RRGGBB / #RGB / #AARRGGBB 及 Android 颜色名;非法串被剔除、其余正常显示
hiddenControls: ['crop', 'share'], // 取值域:text/clear/draw/save/share/sticker/crop,大小写不敏感
stickers: ['sticker1', '/data/storage/el2/base/haps/entry/files/star.png'], // 资源名(需宿主注册 resolver)或完整路径均可
onDone: (imagePath) => { /* 【完成】回吐剥离前缀后的源路径;【保存】回吐相册 URI */ },
onCancel: (resultCode) => { /* 取消/失败统一回 0 */ },
});接口文档
PhotoEditor.Edit(props, onDone, onCancel) props:
| props 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| path | string | 无(必填) | 源图路径或 URI |
| colors | string[] | 内置 13 色 | 十六进制(#RGB/#ARGB/#RRGGBB/#AARRGGBB)或 Android 颜色名调色板 |
| hiddenControls | string[] | [] | 要隐藏的工具,取值域 7 键:text/clear/draw/save/share/sticker/crop,大小写不敏感 |
| stickers | string[] | [](内置 26 张) | 贴纸列表,资源名(需宿主注册 resolver)或完整路径均可 |
回调:
| 回调 | 类型 | 说明 |
|---|---|---|
| onDone | (imagePath: string) => void | 【完成】回吐归一化后的源路径;【保存】回吐系统相册 URI(file://media/Photo/…),源图不变 |
| onCancel | (resultCode: number) => void | 用户取消、保存失败、path 非法、拉起失败均回 0(四因同码),返回码不可单独作为成因判据 |
返回值:void。异常:不抛出,结果异步经 onDone/onCancel 二选一回吐。
贴纸解析集成函数(HAR 导出):
| 函数 | 说明 |
|---|---|
| registerStickerResolver(fn) | 注册"贴纸资源名 → 图片资源"的解析函数 |
| createRawfileStickerResolver(rm) | 开箱即用的 rawfile 映射实现 |
| hasStickerResolver() | 查询是否已注册 resolver |
HAR 导出组件:
PhotoEditorPage / PhotoEditorController,供宿主自建的 @Entry 页壳装载与转发系统返回事件,配合上方「集成指南」第 5 步使用。
快速验证(运行 Example)
前置条件
- Node.js >= 20(以示例 engines 为准),npm,以及 DevEco Studio 配套的 ohpm / SDK。
- 示例版本:React Native
0.72.5、RNOH0.72.143。 - 鸿蒙工程配置:targetSdkVersion=6.1.1(24),compatibleSdkVersion=5.1.0(18)。设备应满足最低版本及本库系统能力要求。
- 在 DevEco Studio 中配置与当前应用包名匹配的签名,不能直接使用其他电脑上的证书路径。
运行步骤
1. 克隆仓库
git clone https://gitcode.com/hxa-rn/react-native-photo-editor.git
cd react-native-photo-editor
git checkout br_rnoh0.72以下步骤使用 example 展示工程;example_auto 的依赖与构建输出独立,不要混用。Windows 建议使用较短目录,避免 RNOH 原生构建中间路径过长。
2. 安装示例依赖
进入示例目录,从 npmjs 安装依赖:
cd example
npm install --legacy-peer-deps3. 生成 JS Bundle
npm run dev确认生成 example/harmony/entry/src/main/resources/rawfile/bundle.harmony.js。先解决命令报错,再进入原生构建。
4. 同步与运行鸿蒙工程
用 DevEco Studio 打开 example/harmony,完成依赖同步。缺少 ohpm 依赖时,在该目录使用 DevEco 配套工具执行 ohpm install --all,再同步。保留示例已有的 RNOH HAR 路径和版本。
示例已配置本库运行所需的依赖与接线,无需重复添加 Package。选择设备、配置签名并点击运行,生成并安装 HAP。修改 JS 后重新生成 Bundle;修改原生依赖后重新构建安装 HAP。
常见问题
- 找不到 JS 模块:检查适配包安装、Metro 别名及对应入口,修改 Metro 后重启打包进程。
- 找不到本地包或 HAR:核对当前目录、文件名及准备步骤;不要将
example_auto的 node_modules 当成example的依赖。 - 原生模块或组件未注册:检查 HAR、CMake、C++ 和 ETS 注册,排除重复注册并重建 HAP。
- SDK / 签名报错:按当前工程配置安装对应 SDK,并重新配置本机签名。
- Ninja
.rsp创建失败:查看完整日志;确认是路径长度问题后,缩短工程目录、清理旧路径构建缓存再构建。
约束与限制
兼容性:
| 项 | 值 |
|---|---|
| 上游基线 | [email protected] |
| npm 适配版本 | @hxa-rn/[email protected] |
| RN / RNOH | RN 0.72.5 + @react-native-oh/[email protected] |
| 鸿蒙最低兼容 API | API 18(compatibleSdkVersion 5.1.0(18)) |
| 目标 API | API 24(targetSdkVersion 6.1.1(24)) |
| 运行系统 | HarmonyOS |
| 已验证通过的设备与档位 | API22 / API23 / API24 / API26 真机,共四档 |
权限:
本库 HAR module.json5 的 requestPermissions 为空数组。【保存】经系统相册确认框完成,无需申请存储权限;【分享】走系统分享面板,无需权限。
使用约束:
- HAR 不能声明 Ability,也不能被宿主直接加载页面,需按「集成指南」第 5 步手动接线,否则拉不起编辑页 / 系统返回键无法正确取消。
- 保存像素尺寸按源图真实像素尺寸导出(裁剪后为选区像素),与上游 Android「视图渲染尺寸」不同——这是有意优于上游的改进,非缺陷。
- 取消返回码「四因同码」:用户取消 / 保存失败 /
path非法 / 拉起失败统一回onCancel(0),四种成因不可仅凭返回码区分。 - 贴纸资源名(如
sticker1)需宿主注册 resolver 才能命中应用内资源,未接线时回退为按完整路径处理,不会崩溃或静默失败。
开源 License
本项目基于 Apache-2.0 License 开源,与上游协议一致。
问题反馈渠道
使用过程中发现任何问题,欢迎在GitCode 提交 Issue,也欢迎提交 PR 参与共建。
