
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
📋 前言
react-native-svg(CAPI) 是一个强大的 SVG 矢量图形库,它为 React Native 应用提供了完整的 SVG 支持,可以绘制各种矢量图形、图标、图表等。该库基于 CAPI(C++ API)实现,提供了高性能的渲染能力,支持 Android、iOS 和 HarmonyOS 三端,特别适合需要绘制复杂图形、自定义粒子形状、图表数据可视化等场景,是 react-native-shadow-2 等库的底层依赖。
🎯 库简介
基本信息
-
库名称: react-native-svg
-
版本信息:
15.0.2: 支持 RN 0.72 版本(@react-native-ohos/react-native-svg)15.12.1: 支持 RN 0.77 版本(@react-native-ohos/react-native-svg)
-
主要功能:
- 矢量图形绘制:支持 Path、Rect、Circle、Ellipse、Line、Polygon、Polyline 等基本图形
- 渐变效果:支持 LinearGradient 和 RadialGradient 渐变
- 图形变换:支持 Translate、Rotate、Scale 等变换操作
- 文本渲染:支持 Text、TSpan、TextPath 等文本元素
- 高级功能:支持 Mask、ClipPath、Pattern、Marker 等高级特性
- 动态加载:支持 SvgFromUri、SvgFromXml、SvgAst 动态加载 SVG
- 图像支持:支持 Image 元素嵌入位图
-
技术特点: 基于 CAPI 实现,性能优异,是 react-native-shadow-2 等库的底层依赖
-
兼容性验证: 该第三方库支持直接从 npm 下载,完整支持 HarmonyOS 平台
为什么需要这个库?
- 矢量图形: 提供完整的 SVG 支持,可绘制任意矢量图形
- 高性能: 基于 CAPI 实现,渲染性能优异
- 跨平台: 支持 Android、iOS、HarmonyOS 三端,统一的 API
- 功能全面: 涵盖 SVG 2.0 的大部分特性
- 易于使用: API 设计简洁明了,易于集成和使用
- 底层依赖: 是 react-native-shadow-2 等库的底层依赖,必须配置
- 鸿蒙支持: 完整支持 HarmonyOS 平台,实现真正的跨平台
📦 安装步骤
1. 使用 npm 安装
根据您的 RN 版本选择对应的包名:
RN 0.72 版本(我用的这个版本):
bash
npm install react-native-svg@15.0.0
npm install @react-native-ohos/react-native-svg@15.0.2-rc.1
RN 0.77 版本(我没尝试):
bash
npm install react-native-svg@15.12.0
npm install @react-native-ohos/react-native-svg
2. 验证安装
安装完成后,检查 package.json 文件,应该能看到新增的依赖:
json
{
"dependencies": {
"react-native-svg": "^15.12.0",
"@react-native-ohos/react-native-svg": "^15.12.1",
// ... 其他依赖
}
}
🔧 HarmonyOS 平台配置 ⭐
1. 在工程根目录的 oh-package.json5 添加 overrides 字段
json
{
...
"overrides": {
"@rnoh/react-native-openharmony": "0.72.90"
}
}
2. 引入原生端代码
目前有两种方法:
方法一:通过 har 包引入(推荐,我用的这个)
!TIP\] har 包位于三方库安装路径的 `harmony` 文件夹下。
打开 harmony/entry/oh-package.json5,添加以下依赖:
json
"dependencies": {
"@react-native-ohos/react-native-svg": "file:../../node_modules/@react-native-ohos/react-native-svg/harmony/svg.har"
}
点击右上角的 sync 按钮
或者在终端执行:
bash
cd harmony/entry
ohpm install
方法二:直接链接源码(0.72的RN,安装15.0.2版本的我没找到)
!TIP\] 如需使用直接链接源码,请参考[直接链接源码说明](https://gitee.com/react-native-oh-library/usage-docs/blob/master/zh-cn/link-source-code.md)
步骤 1 : 把 <RN工程>/node_modules/@react-native-ohos/react-native-svg/harmony 目录下的源码 svg 复制到 harmony 工程根目录下。
步骤 2 : 在 harmony 工程根目录的 build-profile.json5 添加以下模块:
json
modules: [
...
{
name: 'svg',
srcPath: './svg',
}
]
步骤 3 : 打开 svg/oh-package.json5,修改 @rnoh/react-native-openharmony 和项目的版本一致。
步骤 4 : 打开 harmony/entry/oh-package.json5,添加以下依赖:
json
"dependencies": {
"@rnoh/react-native-openharmony": "0.72.90",
"@react-native-ohos/react-native-svg": "file:../svg"
}
步骤 5 : 点击 DevEco Studio 右上角的 sync 按钮
3. 配置 CMakeLists 和引入 SVGPackage
!WARNING\] 若使用的是 \<= 15.0.1 版本,请跳过本章。
打开 harmony/entry/src/main/cpp/CMakeLists.txt,添加:
diff
project(rnapp)
cmake_minimum_required(VERSION 3.4.1)
set(CMAKE_SKIP_BUILD_RPATH TRUE)
set(RNOH_APP_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
set(NODE_MODULES "${CMAKE_CURRENT_SOURCE_DIR}/../../../../../node_modules")
+ set(OH_MODULES "${CMAKE_CURRENT_SOURCE_DIR}/../../../oh_modules")
set(RNOH_CPP_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../react-native-harmony/harmony/cpp")
set(LOG_VERBOSITY_LEVEL 1)
set(CMAKE_ASM_FLAGS "-Wno-error=unused-command-line-argument -Qunused-arguments")
set(CMAKE_CXX_FLAGS "-fstack-protector-strong -Wl,-z,relro,-z,now,-z,noexecstack -s -fPIE -pie")
set(WITH_HITRACE_SYSTRACE 1) # for other CMakeLists.txt files to use
add_compile_definitions(WITH_HITRACE_SYSTRACE)
add_subdirectory("${RNOH_CPP_DIR}" ./rn)
# RNOH_BEGIN: manual_package_linking_1
add_subdirectory("../../../../sample_package/src/main/cpp" ./sample-package)
+ add_subdirectory("${OH_MODULES}/@react-native-ohos/react-native-svg/src/main/cpp" ./svg)
# RNOH_END: manual_package_linking_1
file(GLOB GENERATED_CPP_FILES "./generated/*.cpp")
add_library(rnoh_app SHARED
${GENERATED_CPP_FILES}
"./PackageProvider.cpp"
"${RNOH_CPP_DIR}/RNOHAppNapiBridge.cpp"
)
target_link_libraries(rnoh_app PUBLIC rnoh)
# RNOH_BEGIN: manual_package_linking_2
target_link_libraries(rnoh_app PUBLIC rnoh_sample_package)
+ target_link_libraries(rnoh_app PUBLIC rnoh_svg)
# RNOH_END: manual_package_linking_2
打开 harmony/entry/src/main/cpp/PackageProvider.cpp,添加:
diff
#include "RNOH/PackageProvider.h"
#include "generated/RNOHGeneratedPackage.h"
#include "SamplePackage.h"
+ #include "SVGPackage.h"
using namespace rnoh;
std::vector<std::shared_ptr<Package>> PackageProvider::getPackages(Package::Context ctx) {
return {
std::make_shared<RNOHGeneratedPackage>(ctx),
std::make_shared<SamplePackage>(ctx),
+ std::make_shared<SVGPackage>(ctx),
};
}
4. 在 ArkTs 侧引入 SvgPackage
打开 harmony/entry/src/main/ets/RNPackagesFactory.ts,添加:
diff
...
+ import { SvgPackage } from '@react-native-ohos/react-native-svg/ts';
export function createRNPackages(ctx: RNPackageContext): RNPackage[] {
return [
new SamplePackage(ctx),
+ new SvgPackage(ctx),
];
}
5. 配置字体文件(可选)
!TIP\] 本项非必配项,当使用 Text 组件的 fontFamily 属性指定字体时才需配置
步骤 1 : 复制字体文件到 entry/src/main/resources/rawfile/assets/fonts 目录下
步骤 2 : 打开 entry/src/main/ets/pages/Index.ets,添加以下代码:
typescript
const fonts: Record<string, Resource> = {
"Noto Sans Pau Cin Hau": $rawfile("assets/fonts/Noto Sans Pau Cin Hau.ttf"),
"NotoSansVai-Regular": $rawfile("assets/fonts/NotoSansVai-Regular.ttf"),
"HarmonyOS_Sans_Condensed_Regular_Italic": $rawfile("assets/fonts/HarmonyOS_Sans_Condensed_Regular_Italic.ttf"),
"HarmonyOS_Sans_Digit_Medium": $rawfile("assets/fonts/HarmonyOS_Sans_Digit_Medium.ttf")
}
@Entry
@Component
struct Index {
build() {
Column(){
RNApp({
rnInstanceConfig: {
fontResourceByFontFamily: fonts
},
//...
}
}
}
}
6. 运行
点击右上角的 sync 按钮
或者在终端执行:
bash
cd harmony/entry
ohpm install
然后编译、运行即可。
7.如果遇到编译命令太长,运行报错
在hvigor/hvigor-config.json5文件中添加配置
{
"properties": {
"ohos.nativeResolver": false
},
"module": {
// ... 其他配置
}
}
💻 完整代码示例
下面是一个完整的示例,展示了如何使用 react-native-svg 绘制粒子形状和图形:
javascript
import React, { useState } from 'react';
import {
View,
StyleSheet,
Text,
ScrollView,
TouchableOpacity,
SafeAreaView,
} from 'react-native';
import {
Svg,
Path,
Circle,
Rect,
Ellipse,
Line,
Polygon,
Polyline,
LinearGradient,
RadialGradient,
Stop,
Text as SvgText,
Defs,
Mask,
ClipPath,
G,
} from 'react-native-svg';
function SvgDemo() {
const [activeTab, setActiveTab] = useState<'particles' | 'shapes' | 'gradients'>('particles');
return (
<SafeAreaView style={styles.container}>
{/* 标题区域 */}
<View style={styles.header}>
<Text style={styles.headerTitle}>SVG 矢量图形</Text>
<Text style={styles.headerSubtitle}>react-native-svg(CAPI)</Text>
</View>
{/* 标签切换 */}
<View style={styles.tabContainer}>
<TouchableOpacity
style={[styles.tab, activeTab === 'particles' && styles.activeTab]}
onPress={() => setActiveTab('particles')}
>
<Text style={[styles.tabText, activeTab === 'particles' && styles.activeTabText]}>
粒子形状
</Text>
</TouchableOpacity>
<TouchableOpacity
style={[styles.tab, activeTab === 'shapes' && styles.activeTab]}
onPress={() => setActiveTab('shapes')}
>
<Text style={[styles.tabText, activeTab === 'shapes' && styles.activeTabText]}>
基本图形
</Text>
</TouchableOpacity>
<TouchableOpacity
style={[styles.tab, activeTab === 'gradients' && styles.activeTab]}
onPress={() => setActiveTab('gradients')}
>
<Text style={[styles.tabText, activeTab === 'gradients' && styles.activeTabText]}>
渐变效果
</Text>
</TouchableOpacity>
</View>
{/* 内容区域 */}
<ScrollView style={styles.content}>
{activeTab === 'particles' && <ParticleShapes />}
{activeTab === 'shapes' && <BasicShapes />}
{activeTab === 'gradients' && <GradientEffects />}
</ScrollView>
</SafeAreaView>
);
}
// 粒子形状
const ParticleShapes = () => {
return (
<View style={styles.section}>
<Text style={styles.sectionTitle}>粒子形状</Text>
{/* 圆形粒子 */}
<View style={styles.demoRow}>
<Text style={styles.label}>圆形粒子</Text>
<Svg width={60} height={60}>
<Circle
cx={30}
cy={30}
r={28}
fill="#409EFF"
/>
</Svg>
</View>
{/* 星形粒子 */}
<View style={styles.demoRow}>
<Text style={styles.label}>星形粒子</Text>
<Svg width={60} height={60}>
<Path
d="M30 5 L35 22 L53 22 L39 33 L44 50 L30 40 L16 50 L21 33 L7 22 L25 22 Z"
fill="#67C23A"
/>
</Svg>
</View>
{/* 心形粒子 */}
<View style={styles.demoRow}>
<Text style={styles.label}>心形粒子</Text>
<Svg width={60} height={60}>
<Path
d="M30 55 C10 35 0 25 0 15 C0 5 10 0 20 5 L30 15 L40 5 C50 0 60 5 60 15 C60 25 50 35 30 55 Z"
fill="#E6A23C"
/>
</Svg>
</View>
{/* 三角形粒子 */}
<View style={styles.demoRow}>
<Text style={styles.label}>三角形粒子</Text>
<Svg width={60} height={60}>
<Path
d="M30 5 L55 50 L5 50 Z"
fill="#F56C6C"
/>
</Svg>
</View>
{/* 六边形粒子 */}
<View style={styles.demoRow}>
<Text style={styles.label}>六边形粒子</Text>
<Svg width={60} height={60}>
<Polygon
points="30,5 53,17 53,43 30,55 7,43 7,17"
fill="#909399"
/>
</Svg>
</View>
{/* 菱形粒子 */}
<View style={styles.demoRow}>
<Text style={styles.label}>菱形粒子</Text>
<Svg width={60} height={60}>
<Polygon
points="30,5 55,30 30,55 5,30"
fill="#409EFF"
/>
</Svg>
</View>
</View>
);
};
// 基本图形
const BasicShapes = () => {
return (
<View style={styles.section}>
<Text style={styles.sectionTitle}>基本图形</Text>
{/* 矩形 */}
<View style={styles.demoRow}>
<Text style={styles.label}>矩形</Text>
<Svg width={80} height={50}>
<Rect
x={5}
y={5}
width={70}
height={40}
fill="#409EFF"
rx={5}
/>
</Svg>
</View>
{/* 椭圆 */}
<View style={styles.demoRow}>
<Text style={styles.label}>椭圆</Text>
<Svg width={80} height={50}>
<Ellipse
cx={40}
cy={25}
rx={35}
ry={20}
fill="#67C23A"
/>
</Svg>
</View>
{/* 线条 */}
<View style={styles.demoRow}>
<Text style={styles.label}>线条</Text>
<Svg width={80} height={50}>
<Line
x1={10}
y1={10}
x2={70}
y2={40}
stroke="#E6A23C"
strokeWidth={3}
/>
</Svg>
</View>
{/* 多段线 */}
<View style={styles.demoRow}>
<Text style={styles.label}>多段线</Text>
<Svg width={80} height={50}>
<Polyline
points="10,40 30,10 50,40 70,10"
stroke="#F56C6C"
strokeWidth={3}
fill="none"
/>
</Svg>
</View>
{/* 文本 */}
<View style={styles.demoRow}>
<Text style={styles.label}>文本</Text>
<Svg width={80} height={50}>
<SvgText
x={40}
y={30}
fontSize={16}
fill="#909399"
textAnchor="middle"
>
SVG
</SvgText>
</Svg>
</View>
{/* 组合图形 */}
<View style={styles.demoRow}>
<Text style={styles.label}>组合图形</Text>
<Svg width={80} height={50}>
<G>
<Rect x={10} y={10} width={20} height={20} fill="#409EFF" />
<Circle cx={50} cy={20} r={10} fill="#67C23A" />
<Line x1={10} y1={40} x2={70} y2={40} stroke="#E6A23C" strokeWidth={2} />
</G>
</Svg>
</View>
</View>
);
};
// 渐变效果
const GradientEffects = () => {
return (
<View style={styles.section}>
<Text style={styles.sectionTitle}>渐变效果</Text>
{/* 线性渐变 */}
<View style={styles.demoRow}>
<Text style={styles.label}>线性渐变</Text>
<Svg width={80} height={50}>
<Defs>
<LinearGradient id="linearGradient1" x1="0%" y1="0%" x2="100%" y2="0%">
<Stop offset="0%" stopColor="#409EFF" stopOpacity="1" />
<Stop offset="100%" stopColor="#67C23A" stopOpacity="1" />
</LinearGradient>
</Defs>
<Rect
x={5}
y={5}
width={70}
height={40}
fill="url(#linearGradient1)"
rx={5}
/>
</Svg>
</View>
{/* 径向渐变 */}
<View style={styles.demoRow}>
<Text style={styles.label}>径向渐变</Text>
<Svg width={80} height={50}>
<Defs>
<RadialGradient id="radialGradient1" cx="50%" cy="50%" r="50%">
<Stop offset="0%" stopColor="#E6A23C" stopOpacity="1" />
<Stop offset="100%" stopColor="#F56C6C" stopOpacity="1" />
</RadialGradient>
</Defs>
<Circle
cx={40}
cy={25}
r={20}
fill="url(#radialGradient1)"
/>
</Svg>
</View>
{/* 对角线渐变 */}
<View style={styles.demoRow}>
<Text style={styles.label}>对角线渐变</Text>
<Svg width={80} height={50}>
<Defs>
<LinearGradient id="linearGradient2" x1="0%" y1="0%" x2="100%" y2="100%">
<Stop offset="0%" stopColor="#909399" stopOpacity="1" />
<Stop offset="100%" stopColor="#409EFF" stopOpacity="1" />
</LinearGradient>
</Defs>
<Rect
x={5}
y={5}
width={70}
height={40}
fill="url(#linearGradient2)"
rx={5}
/>
</Svg>
</View>
{/* 多色渐变 */}
<View style={styles.demoRow}>
<Text style={styles.label}>多色渐变</Text>
<Svg width={80} height={50}>
<Defs>
<LinearGradient id="linearGradient3" x1="0%" y1="0%" x2="100%" y2="0%">
<Stop offset="0%" stopColor="#409EFF" stopOpacity="1" />
<Stop offset="50%" stopColor="#67C23A" stopOpacity="1" />
<Stop offset="100%" stopColor="#E6A23C" stopOpacity="1" />
</LinearGradient>
</Defs>
<Rect
x={5}
y={5}
width={70}
height={40}
fill="url(#linearGradient3)"
rx={5}
/>
</Svg>
</View>
{/* 透明度渐变 */}
<View style={styles.demoRow}>
<Text style={styles.label}>透明度渐变</Text>
<Svg width={80} height={50}>
<Defs>
<LinearGradient id="linearGradient4" x1="0%" y1="0%" x2="100%" y2="0%">
<Stop offset="0%" stopColor="#F56C6C" stopOpacity="1" />
<Stop offset="100%" stopColor="#F56C6C" stopOpacity="0" />
</LinearGradient>
</Defs>
<Rect
x={5}
y={5}
width={70}
height={40}
fill="url(#linearGradient4)"
rx={5}
/>
</Svg>
</View>
{/* 圆形径向渐变 */}
<View style={styles.demoRow}>
<Text style={styles.label}>圆形径向渐变</Text>
<Svg width={80} height={50}>
<Defs>
<RadialGradient id="radialGradient2" cx="30%" cy="30%" r="70%">
<Stop offset="0%" stopColor="#409EFF" stopOpacity="1" />
<Stop offset="100%" stopColor="#909399" stopOpacity="1" />
</RadialGradient>
</Defs>
<Circle
cx={40}
cy={25}
r={20}
fill="url(#radialGradient2)"
/>
</Svg>
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#F5F7FA',
},
header: {
padding: 20,
backgroundColor: '#FFFFFF',
borderBottomWidth: 1,
borderBottomColor: '#EBEEF5',
},
headerTitle: {
fontSize: 24,
fontWeight: '700',
color: '#303133',
textAlign: 'center',
marginBottom: 8,
},
headerSubtitle: {
fontSize: 16,
fontWeight: '500',
color: '#909399',
textAlign: 'center',
},
tabContainer: {
flexDirection: 'row',
backgroundColor: '#FFFFFF',
borderBottomWidth: 1,
borderBottomColor: '#EBEEF5',
},
tab: {
flex: 1,
paddingVertical: 16,
alignItems: 'center',
},
activeTab: {
borderBottomWidth: 2,
borderBottomColor: '#409EFF',
},
tabText: {
fontSize: 16,
fontWeight: '500',
color: '#909399',
},
activeTabText: {
color: '#409EFF',
fontWeight: '600',
},
content: {
flex: 1,
padding: 16,
},
section: {
marginBottom: 20,
},
sectionTitle: {
fontSize: 20,
fontWeight: '600',
color: '#303133',
marginBottom: 16,
},
demoRow: {
flexDirection: 'row',
alignItems: 'center',
marginBottom: 20,
backgroundColor: '#FFFFFF',
padding: 16,
borderRadius: 8,
},
label: {
fontSize: 14,
fontWeight: '500',
color: '#606266',
width: 80,
},
});
export default SvgDemo;
🎨 实际应用场景
完整示例代码已展示了以下实际应用场景:
- 粒子形状绘制: 使用 Path、Circle、Polygon 绘制各种粒子形状
- 基本图形绘制: 使用 Rect、Ellipse、Line、Polyline 绘制基本图形
- 渐变效果: 使用 LinearGradient 和 RadialGradient 实现渐变效果
- 文本渲染: 使用 SvgText、TSpan 渲染 SVG 文本
- 图形组合: 使用 G 组件组合多个图形元素
- 高级功能: 支持 Defs、Mask、ClipPath 等高级特性
⚠️ 注意事项与最佳实践
1. SDK 版本要求(重要)
!WARNING\] Image 和 RadialGradient 组件依赖 Canary3 Sp2 以上版本的 SDK 和 ROM!
- Image 组件: 需要 Canary3 Sp2 以上版本
- RadialGradient 组件: 需要 Canary3 Sp2 以上版本
2. 必需属性配置
某些组件有必需属性,必须正确配置:
javascript
// 正确:提供必需属性
<Svg width={100} height={100}>
<Circle cx={50} cy={50} r={40} fill="#409EFF" />
</Svg>
// 错误:缺少必需属性
<Svg>
<Circle fill="#409EFF" />
</Svg>
3. viewBox 使用
使用 viewBox 实现响应式缩放:
javascript
// 正确:使用 viewBox
<Svg width={200} height={200} viewBox="0 0 100 100">
<Circle cx={50} cy={50} r={40} fill="#409EFF" />
</Svg>
// SVG 内容会自动缩放以适应容器
4. 渐变定义
渐变必须在 Defs 中定义,并通过 url 引用:
javascript
// 正确:在 Defs 中定义渐变
<Svg width={200} height={200}>
<Defs>
<LinearGradient id="myGradient" x1="0%" y1="0%" x2="100%" y2="0%">
<Stop offset="0%" stopColor="#409EFF" />
<Stop offset="100%" stopColor="#67C23A" />
</LinearGradient>
</Defs>
<Rect width={200} height={200} fill="url(#myGradient)" />
</Svg>
5. Path 路径命令
正确使用 Path 的 d 属性:
javascript
// 常用路径命令
// M: 移动到 (Move to)
// L: 画线到 (Line to)
// C: 三次贝塞尔曲线 (Cubic Bézier curve)
// Q: 二次贝塞尔曲线 (Quadratic Bézier curve)
// A: 弧线 (Arc)
// Z: 闭合路径 (Close path)
<Path
d="M10 10 L50 10 L50 50 L10 50 Z" // 矩形
d="M50 10 L90 50 L50 90 L10 50 Z" // 菱形
d="M50 5 L65 35 L95 35 L75 55 L85 85 L50 70 L15 85 L25 55 L5 35 L35 35 Z" // 星形
/>
6. 性能优化
避免在列表中使用过多的复杂 SVG,影响性能:
javascript
// 不推荐:每个列表项都使用复杂 SVG
<FlatList
data={items}
renderItem={({ item }) => (
<Svg>
<Path d={complexPath} />
</Svg>
)}
/>
// 推荐:简化 SVG 或使用缓存
<FlatList
data={items}
renderItem={({ item }) => (
<Svg>
<Circle cx={10} cy={10} r={5} />
</Svg>
)}
/>
7. 字体配置(可选)
使用自定义字体时需要配置字体文件:
typescript
const fonts: Record<string, Resource> = {
"CustomFont": $rawfile("assets/fonts/CustomFont.ttf")
}
RNApp({
rnInstanceConfig: {
fontResourceByFontFamily: fonts
}
})
8. 动态加载 SVG
使用 SvgFromUri、SvgFromXml、SvgAst 动态加载 SVG:
javascript
// 从 URI 加载
<SvgFromUri uri="https://example.com/icon.svg" width={100} height={100} />
// 从 XML 字符串加载
<SvgFromXml xml="<svg>...</svg>" width={100} height={100} />
// 从 AST 加载
<SvgAst ast={parsedAst} width={100} height={100} />
9. 版本兼容性
根据 RN 版本选择对应的库版本:
| RN 版本 | react-native-svg | @react-native-ohos/react-native-svg |
|---|---|---|
| 0.72 | 15.0.0 | 15.0.2 |
| 0.77 | 15.12.0 | 15.12.1 |
📊 对比:原生 Image vs react-native-svg
| 特性 | 原生 Image | react-native-svg |
|---|---|---|
| 矢量图形 | ❌ 不支持 | ✅ 支持 |
| 缩放质量 | ⚠️ 位图缩放 | ✅ 矢量缩放 |
| 文件大小 | ⚠️ 较大 | ✅ 较小 |
| 自定义形状 | ❌ 不支持 | ✅ 支持 |
| 渐变效果 | ❌ 不支持 | ✅ 支持 |
| 动态修改 | ⚠️ 有限 | ✅ 完全支持 |
| 性能 | ✅ 优秀 | ✅ 优秀 |
| 使用复杂度 | ✅ 简单 | ⚠️ 中等 |
📝 总结
通过集成 react-native-svg(CAPI),我们为项目添加了强大的 SVG 矢量图形支持。这个库基于 CAPI 实现,提供了完整的 SVG 功能,可以轻松绘制各种矢量图形、图标、图表等,是 react-native-shadow-2 等库的底层依赖。
关键要点回顾
- ✅ 安装依赖 :
npm install react-native-svg和npm install @react-native-ohos/react-native-svg - ✅ 配置平台: 通过 har 包或直接链接源码,配置 CMakeLists.txt 和 PackageProvider.cpp
- ✅ 集成代码: 使用 Svg、Path、Circle 等组件提供的各种 API
- ✅ 支持功能: 矢量图形绘制、渐变效果、文本渲染、高级特性等
- ✅ 测试验证: 确保三端表现一致
- ✅ 重要提醒: Image 和 RadialGradient 需要 Canary3 Sp2 以上版本
常用组件快速参考
javascript
// 基础图形
<Svg width={100} height={100}>
<Circle cx={50} cy={50} r={40} fill="#409EFF" />
<Rect x={10} y={10} width={80} height={80} fill="#67C23A" />
<Ellipse cx={50} cy={50} rx={40} ry={20} fill="#E6A23C" />
<Line x1={10} y1={10} x2={90} y2={90} stroke="#F56C6C" strokeWidth={3} />
<Polygon points="50,10 90,90 10,90" fill="#909399" />
<Polyline points="10,90 50,10 90,90" stroke="#409EFF" strokeWidth={3} />
</Svg>
// 路径绘制
<Svg width={100} height={100}>
<Path
d="M10 10 L90 10 L90 90 L10 90 Z"
fill="#409EFF"
/>
</Svg>
// 渐变效果
<Svg width={100} height={100}>
<Defs>
<LinearGradient id="gradient" x1="0%" y1="0%" x2="100%" y2="0%">
<Stop offset="0%" stopColor="#409EFF" />
<Stop offset="100%" stopColor="#67C23A" />
</LinearGradient>
</Defs>
<Rect width={100} height={100} fill="url(#gradient)" />
</Svg>
// 文本渲染
<Svg width={100} height={100}>
<SvgText
x={50}
y={50}
fontSize={16}
fill="#303133"
textAnchor="middle"
>
SVG Text
</SvgText>
</Svg>
// 图形组合
<Svg width={100} height={100}>
<G>
<Circle cx={30} cy={30} r={20} fill="#409EFF" />
<Rect x={50} y={50} width={30} height={30} fill="#67C23A" />
</G>
</Svg>