react-native-fast-shadow:基于 React Native 鸿蒙生态的高性能阴影组件库

高性能阴影视图组件

Branch3Tags2
FilesLast commitLast update
3 years ago
18 days ago
18 days ago
19 days ago
1 month ago
1 month ago
1 month ago
28 days ago
19 days ago
18 days ago
18 days ago
1 month ago
18 days ago
1 month ago

本项目基于 react-native-fast-shadow 开发。如果在使用过程中有任何问题,可以在 GitCode 提交 Issue,会及时跟进。

项目介绍

react-native-fast-shadow 是 React Native 生态的高性能阴影组件库。本项目为其 HarmonyOS(RNOH / Fabric 架构)适配版本,npm 包名为 @hxa-rn/react-native-fast-shadow,业务别名为 react-native-fast-shadow(鸿蒙侧 HAR 的 ohpm 包名为 @oh-rn/react-native-fast-shadow),适配基线为上游 v0.1.1。

对外提供两个能力:

  • ShadowedView —— 阴影包裹容器组件,是 <View> 的直接替代品。读取标准 shadowColor / shadowOpacity / shadowRadius / shadowOffset 样式,在原生侧经 ArkUI shadow() 绘制盒外投影,并自动从自身或直接子节点的样式推断投影圆角。
  • shadowStyle() —— 跨端阴影样式工具函数,用于统一各平台的阴影观感;鸿蒙平台模糊半径按原值输出,不做 iOS 式减半。

投影绘制在容器盒外,不占用内容区域。

集成指南

本节用于接入已有 RN 鸿蒙应用;运行本仓库示例请参见「快速验证(运行 Example)」。

1. 安装适配包

当前 npm 适配包为 @hxa-rn/react-native-fast-shadow@0.1.2(与上游基线同号;版本号低于此前发布的 1.0.0,请按精确版本安装),业务别名为 react-native-fast-shadow。在 RN 应用根目录执行:

npm install @hxa-rn/react-native-fast-shadow@0.1.2 --legacy-peer-deps

该 npm 包包含 JS / 类型产物及已构建的 harmony/fast_shadow.har;安装 npm 包不会重新编译原生 HAR。

peerDependencies:{"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 {ShadowedView, shadowStyle} from 'react-native-fast-shadow';

3. 注册鸿蒙原生模块

本包声明了 Autolinking 元数据:CMake 目标 fast_shadow,ohpm 包 @oh-rn/react-native-fast-shadow,C++ / ETS 类 FastShadowPackage。宿主启用 RNOH Autolinking 后,应检查生成的 HAR 依赖、CMake 链接及 C++ / ETS Package 注册是否齐全;已自动注册时不要重复手动注册。

Autolinking 不可用时,保留宿主已有配置,补齐以下四处:

  1. 在 harmony/entry/oh-package.json5 的 dependencies 追加下项,然后在 harmony/entry 执行 ohpm install 并同步工程:
"@oh-rn/react-native-fast-shadow": "file:../../node_modules/@hxa-rn/react-native-fast-shadow/harmony/fast_shadow.har"
  1. 在 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-fast-shadow/src/main/cpp" ./fast_shadow)
# 放在 rnoh_app 目标创建之后:
target_link_libraries(rnoh_app PUBLIC fast_shadow)
  1. 在 harmony/entry/src/main/cpp/PackageProvider.cpp 添加头文件,并把实例加入已有 getPackages 返回集合(本仓库模板可加入 ManualLinkingPackage 列表):
#include "FastShadowPackage.h"

// 加入已有 Package 集合:
std::make_shared<rnoh::FastShadowPackage>(ctx)
  1. 在 harmony/entry/src/main/ets/RNPackagesFactory.ets 添加默认导入,并把实例加入已有 createRNPackages 返回数组:
import FastShadowPackage from '@oh-rn/react-native-fast-shadow';

// 加入 createRNPackages(ctx) 返回数组:
new FastShadowPackage(ctx)

确保宿主 RNApp 使用上述 createRNPackages,并启用 enableCAPIArchitecture: true。完成后重新生成宿主 Bundle、构建并安装 HAP;只刷新 JS 不会加载新增的原生模块。若 HAR 内 RNOH 相对依赖无法解析,在宿主鸿蒙根 oh-package.json5 的 overrides 中将 @rnoh/react-native-openharmony 指向宿主正在使用的同一 RNOH HAR,勿混用 debug/release 或不同版本。

宿主页面接线(Autolinking 与手动接入都需要):ShadowedView 在鸿蒙侧由本库的 ArkTS 组件 FastShadowView 渲染,Autolinking 不会修改宿主页面。请在宿主创建 RNApp 的页面(RNOH 工程模板为 harmony/entry/src/main/ets/pages/Index.ets)补齐以下三处,否则阴影不显示(与本仓示例相同):

import { FastShadowView, FAST_SHADOW_VIEW_TYPE } from '@oh-rn/react-native-fast-shadow';

const ARK_TS_COMPONENT_NAMES: string[] = [FAST_SHADOW_VIEW_TYPE];

@Builder
export function buildCustomRNComponent(ctx: ComponentBuilderContext) {
  // 保留宿主已有的分支,追加:
  if (ctx.componentName === FAST_SHADOW_VIEW_TYPE) {
    FastShadowView({ ctx: ctx.rnComponentContext, tag: ctx.tag });
  }
}

const wrappedCustomRNComponentBuilder = wrapBuilder(buildCustomRNComponent)

// RNApp 参数中:
RNApp({
  rnInstanceConfig: {
    createRNPackages,
    enableCAPIArchitecture: true,
    arkTsComponentNames: ARK_TS_COMPONENT_NAMES,
    // ...保留宿主原有配置
  },
  wrappedCustomRNComponentBuilder: wrappedCustomRNComponentBuilder,
  // ...保留宿主原有参数
})

本库本体不要求额外系统权限。

使用说明

基础用法

import { ShadowedView } from 'react-native-fast-shadow';

<ShadowedView
  style={{
    shadowColor: '#1e88e5',
    shadowOpacity: 0.6,
    shadowRadius: 12,
    shadowOffset: { width: 0, height: 4 },
    borderRadius: 16,
    backgroundColor: '#ffffff',
  }}
>
  <View style={{ width: 160, height: 100 }} />
</ShadowedView>

配合 shadowStyle() 保持跨端一致

import { ShadowedView, shadowStyle } from 'react-native-fast-shadow';

<ShadowedView
  style={shadowStyle({
    color: '#1e88e5',
    opacity: 0.6,
    radius: 12,
    offset: [0, 4],
  })}
>
  <View style={{ width: 160, height: 100, borderRadius: 16, backgroundColor: '#fff' }} />
</ShadowedView>

圆角推断规则

投影轮廓的圆角按以下顺序推断,命中即止:

  1. 自身 style —— 当自身样式含 backgroundColor 或任一圆角属性时命中,取自身圆角;
  2. 唯一合法直接子元素的 style —— 自身未命中时,取子元素圆角;
  3. 两者皆无 —— 四角回落为 0,投影呈直角矩形。

四角取值支持 borderRadius 统一值、borderTopLeftRadius 等四角单角值,以及 borderTopStartRadius / borderTopEndRadius 等方向属性;单角值优先于统一值。

接口文档

ShadowedView

阴影包裹容器组件,继承全部标准 ViewProps。

样式属性 类型 默认值 说明
shadowColor ColorValue 黑色 投影颜色。颜色自带的 alpha 通道被剥离,浓淡仅由 shadowOpacity 决定;不可解析的颜色回落默认黑
shadowOpacity number 0 投影不透明度。≤ 0(含负值)完全不绘制;> 1 按全不透明处理
shadowRadius number 3 模糊半径(vp)。有效范围 [0, 25],越界按边界钳制;取整到最近 0.5
shadowOffset { width: number; height: number } { width: 0, height: -3 } 投影偏移(vp)。正值分别向右、向下
圆角属性 number 0 参与圆角推断,规则见「使用说明」

返回值:React 组件。 异常:不抛出任何异常,无错误码。非法或缺省的样式值一律按上表默认值回落,不中断渲染。 标准容器属性:testID、onLayout、pointerEvents 等全量透传给底层组件。

shadowStyle(params)

生成标准阴影样式对象的工具函数。

参数 params: ShadowParams

字段 类型 必填 说明
color ColorValue 否 原样赋给 shadowColor
opacity number 否 原样赋给 shadowOpacity
radius number 否 赋给 shadowRadius。鸿蒙平台输出原值;iOS 平台输出输入值的一半
offset [number, number] 否 转为 { width: offset[0], height: offset[1] }

返回值 ViewStyle —— 含 shadowColor / shadowOpacity / shadowRadius / shadowOffset 四个键的样式对象。入参字段缺省时对应输出为 undefined;radius: 0 时字段值为 0(与「未提供」不同,后者字段不存在)。

异常:不抛出。

ShadowParams

shadowStyle() 的入参类型,字段定义见上表。

与其他平台的行为差异

项 鸿蒙 上游 Android / iOS
shadowStyle() 的 radius 原值输出 iOS 输出一半(上游认为 iOS 视觉半径偏大一倍)
半径与圆角取整 四舍五入到最近 0.5 上游 Android 实为向下取整到整数(其代码与注释不符),鸿蒙按上游注释的设计意图实现
投影形状 仅圆角矩形 Android 同;iOS 支持任意形状

快速验证(运行 Example)

前置条件

依赖 版本要求
Node.js >= 20(示例工程 engines 要求);DevEco Sync 时 ohpm preInstall 钩子也要用 PATH 中的 Node.js 与 npm
DevEco Studio 6.1.1 及以上(示例 targetSdkVersion 为 6.1.1(24))
HarmonyOS SDK API 18+(example/harmony 的 compatibleSdkVersion 为 5.1.0(18))
路径 Windows 下仓库根目录的完整路径不超过 40 个字符,否则原生构建的中间文件路径会超过系统上限

运行步骤

1. 克隆仓库

git clone -b br_rnoh0.72 https://gitcode.com/hxa-rn/react-native-fast-shadow.git
cd react-native-fast-shadow

Windows 下可在克隆时指定短目录名,例如 git clone -b br_rnoh0.72 https://gitcode.com/hxa-rn/react-native-fast-shadow.git C:\rfs。

2. 进入 example 目录,安装依赖

cd example
npm install --legacy-peer-deps

Example 从 npm 公仓安装 @hxa-rn/react-native-fast-shadow@0.1.2,不需要在仓根执行 npm pack。

3. 生成 JS Bundle

npm run dev

产物:harmony/entry/src/main/resources/rawfile/bundle.harmony.js

4. 用 DevEco Studio 打开鸿蒙工程

  • 打开 DevEco Studio,选择 example/harmony 目录
  • 首次构建请在 File → Project Structure → Signing Configs 勾选 Automatically generate signature,Apply 后 Sync
  • 等待 Sync 完成

5. 编译并运行 HAP

在 DevEco Studio 中点击运行按钮,将 HAP 安装到设备。

example_auto(自动化用例工程)步骤相同,把 example 换成 example_auto 即可,两者的依赖与构建输出相互独立。

注意:Example 已预置 Package 注册、Metro alias 与 HAR 依赖,无需手动 Link。编 HAP 前必须先执行 npm run dev;改过 JS 后重新执行再运行。首次 Sync 时 ohpm preInstall 钩子会在仓根补跑一次准备脚本(需联网,已完成的部分自动跳过)。

常见问题

  • 找不到 JS 模块:检查适配包安装、Metro 别名及对应入口,修改 Metro 后重启打包进程。
  • 找不到 npm 包或 HAR:核对 example/node_modules/@hxa-rn/react-native-fast-shadow/harmony/fast_shadow.har 是否存在,必要时在 example 目录重新执行 npm install --legacy-peer-deps;不要将 example_auto 的 node_modules 当成 example 的依赖。
  • 原生模块或组件未注册:检查 HAR、CMake、C++ 和 ETS 注册,排除重复注册并重建 HAP。
  • SDK / 签名报错:按当前工程配置安装对应 SDK,并重新配置本机签名。
  • Ninja .rsp 创建失败:查看完整日志;确认是路径长度问题后,缩短工程目录、清理旧路径构建缓存再构建。

约束与限制

项 说明
支持形状 仅支持圆角矩形投影,不支持任意形状。文字投影请使用 textShadowRadius
子节点尺寸 应填满容器:ShadowedView 与其子节点尺寸不一致时,投影会大于内容
圆角推断 视图层级较深时推断链可能落空,此时请直接给 ShadowedView 的 style 传 borderRadius
模糊半径范围 [0, 25]:负值按 0 渲染,超过 25 按 25 渲染。取整到最近 0.5
颜色 alpha shadowColor 的 alpha 通道不参与,投影浓淡仅由 shadowOpacity 决定
默认偏移 未提供 shadowOffset 时按 (0, -3) 呈现(向上偏移),而非 (0, 0)
RTL 布局镜像即时生效;圆角起始/结束方向映射取决于 JS 侧 I18nManager.isRTL,运行时 forceRTL 不刷新该常量且重启不持久,需系统级 RTL 环境才生效
权限 不申请任何系统权限
兼容性 鸿蒙 SDK minAPIVersion 5.0.1(13);已验证环境 RN 0.72.5 / RNOH 0.72.139
设备类型 HAR module.json 声明 default / tablet / 2in1
自动链接 当前根 package.json 已声明 harmony.autolinking;宿主启用自动链接后检查生成结果,不可用时按集成指南手动注册

开源 License

本项目基于 MIT License 开源,与上游 react-native-fast-shadow 协议一致。请自由地享受和参与开源。

问题反馈渠道

使用过程中发现任何问题,欢迎在GitCode 提交 Issue,也欢迎提交 PR 参与共建。