如何显示 SVG 文件的反应本机?

我想显示 svg 文件(我有一些 svg 图像) ,但是我找不到显示的方法。我尝试使用 一个 href = “ https://github.com/magicismight/response-national-svg”rel = “ norefrer”> response-national-svg 形象使用组件,但它们不能工作。我尝试用本地化的方式做到这一点,但是仅仅显示 svg 图像真的很难。

示例代码:

import Svg, {
Use,
Image,
} from 'react-native-svg';


<View>
<Svg width="80" height="80">
<Image href={require('./svg/1f604.svg')} />
</SvgRn>
</View>

我也知道本地响应基本上不支持 svg,但我认为有人用棘手的方法(有/没有本地响应-svg)解决了这个问题

299268 次浏览

我也遇到了同样的问题。我正在使用我发现的这个解决方案: 从文件中反应本机显示 SVG

它并不完美,我今天重新研究一下,因为它在 Android 上的表现要差很多。

在尝试了许多方法和库之后,我决定创建一个新的字体(使用 象形文字或这个 教程) ,并将我的 SVG 文件添加到其中,然后使用自定义字体的“ Text”组件。

希望这可以帮助任何在本地反应中遇到 SVG 相同问题的人。

这种方法使用矢量字体(来自 SVG)代替 SVG 文件。 反应原生向量图标是处理反应原生 SVG 的最佳方法,也适用于 iOS 和 android 系统。您将能够改变您的矢量图标的颜色和大小。

如果您想直接将 svg 插入到应用程序中,可以尝试使用第三方库: response-national-svg。拥有超过3000颗星星的 github 是最好的方法之一。

使用 npm安装其中任何一个:

然后将其链接到本地使用

react-native link react-native-svg

react-native-svg-uri的一个例子:

import * as React from 'react';
import SvgUri from 'react-native-svg-uri'; // SVG Package
import testSvg from './test.svg';          // SVG File


export default () => (
<SvgUri
width="200"
height="200"
svgXmlData={testSvg}
/>
);

我使用了以下解决方案:

  1. 使用 https://svg2jsx.herokuapp.com/.svg映像转换为 JSX
  2. 使用 https://react-svgr.com/playground/?native=true将 JSX 转换为 react-native-svg组件(确保勾选了“ React Native”复选框)

注意: Svg 不适用于 android 版本,因此不要考虑 android 版本。它只能在调试模式下工作。但是对 ios 来说还不错。

使用 https://github.com/vault-development/react-native-svg-uri

安装

npm install react-native-svg-uri --save
react-native link react-native-svg # not react-native-svg-uri

用法

import SvgUri from 'react-native-svg-uri';




<SvgUri source={require('./path_to_image/image.svg')} />

使用 https://github.com/kristerkari/react-native-svg-transformer

在这个包中提到,React Nativev0.57或更低版本不支持 .svg文件,因此对 svg 文件使用 .svgx扩展名。

对于网络或反应-本地网络使用 https://www.npmjs.com/package/@svgr/webpack


要使用反应原生版本为0.57或更低版本的 react-native-svg-uri呈现 svg 文件,需要向根项目添加以下文件

注意: 将扩展 svg改为 svgx

步骤1: 将文件 transformer.js添加到项目的根目录

// file: transformer.js


const cleanupSvg = require('./cleanup-svg');


const upstreamTransformer = require("metro/src/transformer");


// const typescriptTransformer = require("react-native-typescript-transformer");
// const typescriptExtensions = ["ts", "tsx"];


const svgExtensions = ["svgx"]


// function cleanUpSvg(text) {
//   text = text.replace(/width="([#0-9]+)px"/gi, "");
//    text = text.replace(/height="([#0-9]+)px"/gi, "");
//    return text;
// }


function fixRenderingBugs(content) {
// content = cleanUpSvg(content); // cleanupSvg removes width and height attributes from svg
return "module.exports = `" + content + "`";
}




module.exports.transform = function ({ src, filename, options }) {
// if (typescriptExtensions.some(ext => filename.endsWith("." + ext))) {
//  return typescriptTransformer.transform({ src, filename, options })
// }


if (svgExtensions.some(ext => filename.endsWith("." + ext))) {
return upstreamTransformer.transform({
src: fixRenderingBugs(src),
filename,
options
})
}


return upstreamTransformer.transform({ src, filename, options });
}


步骤2: 将 rn-cli.config.js添加到项目的根目录

module.exports = {
getTransformModulePath() {
return require.resolve("./transformer");
},
getSourceExts() {
return [/* "ts", "tsx", */ "svgx"];
}
};

上述解决方案也适用于生产应用程序

安装 本地反应式静止无功变压器

反应-本机-svg-转换器-保存-开发

我使用 SVG 作为下面的代码,它工作得很好

import LOGOSVG from "assets/svg/logo.svg"

在渲染中

<View>
<LOGOSVG
width="100%"
height="70%"
/>
</View>

所有这些解决方案都是绝对可怕的。只需将 SVG 转换为 PNG 并使用普通的 <Image/>组件即可。事实上,反应本机仍然不支持 Image组件中的 SVG 图像,这是一个笑话。您永远不应该为这样一个简单的任务安装额外的库。使用 https://svgtopng.com/

我已经尝试了所有上述解决方案和其他解决方案以外的堆栈,没有为我工作。经过长时间的研究,我终于为我的世博项目找到了一个解决方案。

如果您需要在 expo 中使用它,一个解决方案可能是使用 https://react-svgr.com/playground/并将道具的分布移动到一个 G 元素,而不是像下面这样的 SVG 根:

import * as React from 'react';
import Svg, { G, Path } from 'react-native-svg';


function SvgComponent(props) {
return (
<Svg viewBox="0 0 511 511">
<G {...props}>
<Path d="M131.5 96c-11.537 0-21.955 8.129-29.336 22.891C95.61 132 92 149.263 92 167.5s3.61 35.5 10.164 48.609C109.545 230.871 119.964 239 131.5 239s21.955-8.129 29.336-22.891C167.39 203 171 185.737 171 167.5s-3.61-35.5-10.164-48.609C153.455 104.129 143.037 96 131.5 96zm15.92 113.401C142.78 218.679 136.978 224 131.5 224s-11.28-5.321-15.919-14.599C110.048 198.334 107 183.453 107 167.5s3.047-30.834 8.581-41.901C120.22 116.321 126.022 111 131.5 111s11.28 5.321 15.919 14.599C152.953 136.666 156 151.547 156 167.5s-3.047 30.834-8.58 41.901z" />
<Path d="M474.852 158.011c-1.263-40.427-10.58-78.216-26.555-107.262C430.298 18.023 405.865 0 379.5 0h-248c-26.365 0-50.798 18.023-68.797 50.749C45.484 82.057 36 123.52 36 167.5s9.483 85.443 26.703 116.751C80.702 316.977 105.135 335 131.5 335a57.57 57.57 0 005.867-.312 7.51 7.51 0 002.133.312h48a7.5 7.5 0 000-15h-16c10.686-8.524 20.436-20.547 28.797-35.749 4.423-8.041 8.331-16.756 11.703-26.007V503.5a7.501 7.501 0 0011.569 6.3l20.704-13.373 20.716 13.374a7.498 7.498 0 008.134 0l20.729-13.376 20.729 13.376a7.49 7.49 0 004.066 1.198c1.416 0 2.832-.4 4.07-1.2l20.699-13.372 20.726 13.374a7.5 7.5 0 008.133 0l20.732-13.377 20.738 13.377a7.5 7.5 0 008.126.003l20.783-13.385 20.783 13.385a7.5 7.5 0 0011.561-6.305v-344a7.377 7.377 0 00-.146-1.488zM187.154 277.023C171.911 304.737 152.146 320 131.5 320s-40.411-15.263-55.654-42.977C59.824 247.891 51 208.995 51 167.5s8.824-80.391 24.846-109.523C91.09 30.263 110.854 15 131.5 15s40.411 15.263 55.654 42.977C203.176 87.109 212 126.005 212 167.5s-8.824 80.391-24.846 109.523zm259.563 204.171a7.5 7.5 0 00-8.122 0l-20.78 13.383-20.742-13.38a7.5 7.5 0 00-8.131 0l-20.732 13.376-20.729-13.376a7.497 7.497 0 00-8.136.002l-20.699 13.373-20.727-13.375a7.498 7.498 0 00-8.133 0l-20.728 13.375-20.718-13.375a7.499 7.499 0 00-8.137.001L227 489.728V271h8.5a7.5 7.5 0 000-15H227v-96.5c0-.521-.054-1.03-.155-1.521-1.267-40.416-10.577-78.192-26.548-107.231C191.936 35.547 182.186 23.524 171.5 15h208c20.646 0 40.411 15.263 55.654 42.977C451.176 87.109 460 126.005 460 167.5V256h-.5a7.5 7.5 0 000 15h.5v218.749l-13.283-8.555z" />
<Path d="M283.5 256h-16a7.5 7.5 0 000 15h16a7.5 7.5 0 000-15zM331.5 256h-16a7.5 7.5 0 000 15h16a7.5 7.5 0 000-15zM379.5 256h-16a7.5 7.5 0 000 15h16a7.5 7.5 0 000-15zM427.5 256h-16a7.5 7.5 0 000 15h16a7.5 7.5 0 000-15z" />
</G>
</Svg>
);
}


export default function App() {
return (
<SvgComponent width="100%" height="100%" strokeWidth={5} stroke="black" />
);
}

我用这两个插件,

  1. [反应-本地-svg ] https://github.com/react-native-community/react-native-svg)
  2. [ 反应-本地-svg-变压器] https://github.com/kristerkari/react-native-svg-transformer)

首先, 你需要安装这个插件,然后你需要用这段代码修改你的 Metro.config.js。

const { getDefaultConfig } = require("metro-config");


module.exports = (async () => {
const {
resolver: { sourceExts, assetExts }
} = await getDefaultConfig();
return {
transformer: {
babelTransformerPath: require.resolve("react-native-svg-transformer")
},
resolver: {
assetExts: assetExts.filter(ext => ext !== "svg"),
sourceExts: [...sourceExts, "svg"]
}
};
})();

有关详情,请浏览此连结

您可以将任何 SVG 转换为组件并使其可重用。

这是我的答案,最简单的方法你可以做到这一点

SVG 到组件

import React from 'react'
import SvgUri from 'react-native-svg-uri';


export default function Splash() {
return (
<View style={styles.container}>
{/* provided the svg file is stored locally */}
<SvgUri
width="400"
height="200"
source={require('./logo.svg')}
/>
{/* if the svg is online */}
<SvgUri
width="200"
height="200"
source=\{\{ uri: 'http://thenewcode.com/assets/images/thumbnails/homer-simpson.svg' }}
/>


<Text style={styles.logoText}>
Text
</Text>
</View>
)
}


const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center'
},
logoText: {
fontSize: 50
}
});

你可以用一个简单的方法做到这一点

首先,你应该采取安装,

  1. Npm install-s response-national-svg
  2. 本机链接
  3. Npm 安装-s 反应-本机-svg-变压器

然后,您应该在您的 Metro.config.js 文件中添加以下代码

const { getDefaultConfig } = require("metro-config");
module.exports = (async () => {
const {
resolver: { sourceExts, assetExts }
} = await getDefaultConfig();
return {
transformer: {
babelTransformerPath: require.resolve("react-native-svg-transformer")
},
resolver: {
assetExts: assetExts.filter(ext => ext !== "svg"),
sourceExts: [...sourceExts, "svg"]
}
};
})();

在此之后,您应该使用以下代码在根目录中创建一个新文件,名称为 Declaration ations.d.js

declare module "*.svg" {
import { SvgProps } from "react-native-svg";
const content: React.FC<SvgProps>;
export default content;
}

终于, 这是一个导入方法

import USER from "../../assets/icons/user.svg"

and, this is for jsx

<USER width="100%" height="100%"/>

  1. 首先在项目中安装 react-native-svg
  2. 打开 https://react-svgr.com/,到操场上选择 React national
  3. 复制粘贴您的 SVG 代码并使用输出代码。

例句:-这是我得到的 SVG 样本。

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="17" height="17" viewBox="0 0 17 17">
<defs>
<path id="a" d="M16.191 1.027L9.023 8.196l7.168 7.168-.83.83-7.169-7.167-7.168 7.168-.831-.831L7.36 8.196.19 1.027l.832-.83L8.19 7.366 15.359.197z"/>
</defs>
<g fill="none" fill-rule="evenodd">
<mask id="b" fill="#fff">
<use xlink:href="#a"/>
</mask>
<use fill="#FFF" fill-rule="nonzero" xlink:href="#a"/>
<g fill="#3D3D3D" mask="url(#b)">
<path d="M0 0h16v16H0z"/>
</g>
</g>
</svg>

产出:-

import * as React from "react"
import Svg, { Defs, Path, G, Mask, Use } from "react-native-svg"


function SvgComponent(props) {
return (
<Svg
xmlns="http://www.w3.org/2000/svg"
xmlnsXlink="http://www.w3.org/1999/xlink"
width={17}
height={17}
viewBox="0 0 17 17"
{...props}
>
<Defs>
<Path
id="prefix__a"
d="M16.191 1.027L9.023 8.196l7.168 7.168-.83.83-7.169-7.167-7.168 7.168-.831-.831L7.36 8.196.19 1.027l.832-.83L8.19 7.366 15.359.197z"
/>
</Defs>
<G fill="none" fillRule="evenodd">
<Mask id="prefix__b" fill="#fff">
<Use xlinkHref="#prefix__a" />
</Mask>
<Use fill="#FFF" fillRule="nonzero" xlinkHref="#prefix__a" />
<G fill="#3D3D3D" mask="url(#prefix__b)">
<Path d="M0 0h16v16H0z" />
</G>
</G>
</Svg>
)
}


export default SvgComponent

但是当我在我的项目中使用上面的代码时,它不能正确地呈现。所以我按照下面的步骤做了,不知怎么的,它对我起作用了。

import * as React from "react"
import Svg, { Path, G } from "react-native-svg"


function SvgComponent(props) {
return (
<Svg
width={17}
height={17}
{...props}
>
<G>
<Path
id="prefix__a"
d="M16.191 1.027L9.023 8.196l7.168 7.168-.83.83-7.169-7.167-7.168 7.168-.831-.831L7.36 8.196.19 1.027l.832-.83L8.19 7.366 15.359.197z"
/>
</G>
</Svg>
)
}


export default SvgComponent

我已经编写了一个新的库,以便能够使用基于 .svg文件的本机向量资产,称为 反应-本机-矢量-图像。它不需要任何自定义的 babel 转换,你可以像使用其他基于位图的资产一样使用它,但是在将 svg 转换为本机等价物时还有一个额外的步骤(不过你只需要在添加新资产时运行它)。

使用您的示例,代码如下所示

import VectorImage from 'react-native-vector-image';


<View>
<VectorImage source={require('./svg/1f604.svg')} />
</View>

SVG 不直接支持本机应用程序。要显示这些应用程序,我们需要借助第三方模块

请按照以下步骤操作

步骤1 。安装 反应-原生 svg 和 < em > 本地反应式静止无功变压器

npm i react-native-svg react-native-svg-transformer

步骤2 . 添加不存在的文件 Metro.config.js

const { getDefaultConfig } = require("metro-config");


module.exports = (async () => {
const {
resolver: {
sourceExts,
assetExts
}
} = await getDefaultConfig();


return {
transformer: {
babelTransformerPath: require.resolve("react-native-svg-transformer")
},
resolver: {
assetExts: assetExts.filter(ext => ext !== "svg"),
sourceExts: [...sourceExts, "svg"]
}};
})();

步骤3 . 像使用 React 组件一样使用 SVG 文件

import Invest from '../assets/invest.svg'; // import SVG


return (
<View>
<Invest /> // Use SVG as component
</View>
)

使用 本地反应 它支持 android 和 Ios。

这是最基本的例子

import * as React from 'react';
import { SvgUri } from 'react-native-svg';


export default () => (
<SvgUri
width="100%"
height="100%"
uri="http://thenewcode.com/assets/images/thumbnails/homer-simpson.svg"
/>
);

如果希望在一个组件中同时使用普通图像和 svg 图像,可以创建一个自定义函数来检查 url 是否包含 svg,并返回 形象组件或 SvgUri

        const ImageComponent = (Props) => {
const {Istyle, url, mode} = props;
const isSvg = url?.includes('.svg') ?? false;
        

if (isSvg) {
return <SvgCssUri style={Istyle} uri={defaultAvatar} />;
}
if (!isSvg) {
return <Image style={Istyle} source=\{\{uri: url}} resizeMode={mode} />;
}
};


//let testURl = "https://avatars.dicebear.com/api/male/john.svg"

在这两个平台上对我都有效的最佳解决方案是 https://github.com/seekshiva/react-native-remote-svg

我还用 https://github.com/react-native-svg/react-native-svg做了一个条件渲染,以便在两个平台上都获得最好的效果,因为这里提到的 Android 有一个已知的问题 https://stackoverflow.com/a/54182426/4934132

以防我有错误边界来覆盖异常。

它看起来像这样:

           <ErrorBoundary
FallbackComponent={error => ErrorFallback(error)}
onReset={() => {
// reset the state of your app so the error doesn't happen again
}}
onError={myErrorHandler}
>
{Platform.OS === 'ios' ?
<SvgCssUri width="100%" height="100%" uri={url} />
:
<Image
source=\{\{ uri: url }}
style=\{\{ width: "100%", height: '100%' }}
/>
}
</ErrorBoundary>

这个方法在2022年适用于任何还在使用它的人,反应本机版本反应本机版本0.63.4,本地反应版本 ^ 12.1.0,你也可以在其他版本中使用这个方法,但总是先查看库的文档:

  1. 通过运行此命令 yarn add react-native-svg-transformer --dev或使用 npm (如果您更喜欢 npm i react-native-svg react-native-svg-transformer --save-dev)安装 react-native-svg-transformer

  2. 通过运行 yarn add babel-plugin-inline-import --dev安装 babel-plugin-inline-import

  3. 你需要更新你的 metro.config.js文件如下:

const { getDefaultConfig } = require('metro-config');


module.exports = (async () => {
const {
resolver: { sourceExts, assetExts }
} = await getDefaultConfig();
return {
transformer: {
babelTransformerPath: require.resolve('react-native-svg-transformer'),
getTransformOptions: async () => ({
transform: {
experimentalImportSupport: false,
inlineRequires: false
}
})
},
resolver: {
assetExts: assetExts.filter(ext => ext !== 'svg'),
sourceExts: [...sourceExts, 'svg']
}
};
})();

  1. 一定要像这样导入你的 svg 文件到你的组件中: import CreditCard from '../assets/CreditCard';请注意我没有添加 .svg文件扩展名到导入中,这是因为在运行它的时候它给了我这个错误 view config getter callback react-native-svg,但是删除它似乎让它运行得很顺利。您可以这样添加文件,将其作为类似于 <CreditCard />的 jsx 元素。

  2. 最后重新启动您的打包程序停止使用 ^Ctrl + C在 Mac 上,然后重新启动它与这个命令 yarn start:dev --reset-cache和安装应用程序再次。

您可以尝试使用 https://svg2jsx.herokuapp.com/将.svg 映像转换为 JSX

  • 然后将 JSX 代码保存在 assest/SVGFile.js 中
  • 然后导入它,例如 import open from "../../../../assets/SVGFile";
  • 最后加入 <SvgXml xml={open} scaleX={2} scaleY={2} width={20} height={20} />

请务必安装,纱线添加反应-本地-svg

一切顺利!

如果有人在2022年困在这个问题上,这里有一个对我有效的解决方案:

  1. 安装反应本机 svg 变压器 :
    yarn add react-native-svg-transformer --dev
    或使用 npm
    npm install react-native-svg-transformer --save-dev

  2. 安装 response-national-svg :
    yarn add react-native-svg
    或使用 npm
    npm install react-native-svg --save

  3. 将您的 Metro.config.js 文件更新如下:

// Learn more https://docs.expo.io/guides/customizing-metro
const { getDefaultConfig } = require('expo/metro-config');


module.exports = (() => {
const {
resolver: {
sourceExts,
assetExts
}
} = getDefaultConfig(__dirname);


return {
transformer: {
babelTransformerPath: require.resolve("react-native-svg-transformer")
},
resolver: {
assetExts: assetExts.filter(ext => ext !== "svg"),
sourceExts: [...sourceExts, "svg"]
}};
})();
  1. 在代码中导入和显示 svg图像,如下所示:
import {View} from 'react-native';
import SvgImage from './path/to/svg/file.svg';


function MyComponent(){
return (
<View>
<SvgImage />
</View>
)
}

在一个本地反应项目中使用 svg 并不像在 Web 中使用它那么简单,尽管它也不是那么困难。

以上的许多答案在我看来都很复杂,因此,这里有一个我使用并喜欢的解决方案。

由于反应本机不直接支持 svg 文件格式,所以需要遵循一些步骤使其工作。

1. 安装 response-national-svg

 npm install react-native-svg --save

This package will help you render the svg file

2. Install react-native-svg-transformer

npm install react-native-svg-transformer --save 

这个包将把 svg 转换为本地理解的反应格式。

3. 将 svg 作为普通组件导入

import Belsvg from "../assets/belsvg.svg"; 

While importing give it a name that you like now this svg is transformed into a react native component by the react-native-svg-transformer

4. Now you can use this as a normal component

For a detailed explanation and example visit the link :

https://kumar2396jayant.medium.com/how-to-use-svg-in-react-native-e581eca59534

ps: I would like to thank Jayant kumar yadav for posting that blog