高级进阶 React Native 鸿蒙跨平台开发:react-native-svg(CAPI) 矢量图形代码指南

欢迎加入开源鸿蒙跨平台社区: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)
  • 官方仓库: https://github.com/software-mansion/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-svgnpm 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>
相关推荐
心中有国也有家2 小时前
Flutter for OpenHarmony:Flutter 全屏滑动引擎PageView 组件详解
flutter·华为·华为云·软件工程·harmonyos
Swift社区3 小时前
React 项目生产环境构建与静态资源优化
前端·react.js·前端框架
ZaneAI3 小时前
🚀 Vercel AI SDK 使用指南: 子代理 (Subagents)
react.js·agent
ITUnicorn6 小时前
【HarmonyOS 6】HarmonyOS 自定义时间选择器实现
华为·harmonyos·arkts·鸿蒙·harmonyos6
早點睡3906 小时前
基础入门 Flutter for OpenHarmony:SnackBar 消息提示组件详解
flutter·harmonyos
果粒蹬i6 小时前
【HarmonyOS】RN of HarmonyOS实战开发项目+Apollo GraphQL客户端
华为·harmonyos·graphql
空白诗6 小时前
基础入门 Flutter for OpenHarmony:BottomSheet 底部面板详解
flutter·harmonyos
柒儿吖7 小时前
基于 lycium 在 OpenHarmony 上交叉编译 utfcpp 完整实践
c++·c#·harmonyos
二流小码农7 小时前
鸿蒙开发:独立开发者的烦恼之icon图标选择
android·ios·harmonyos