[英]How to show SVG file on React Native?
我想显示 svg 个文件(我有一堆 svg 个图像)但是我找不到显示方式。 我尝试使用React-native-svg的Image和Use组件,但它们不起作用。 我尝试用原生方式来做到这一点,但只显示 svg 图像真的很难。
示例代码:
import Svg, {
Use,
Image,
} from 'react-native-svg';
<View>
<Svg width="80" height="80">
<Image href={require('./svg/1f604.svg')} />
</SvgRn>
</View>
我也知道 react native 基本上不支持 svg 但我认为有人用棘手的方式解决了这个问题(有/没有 react-native-svg)
我使用了以下解决方案:
.svg
图像转换为 JSXreact-native-svg
组件(选中“React Native 复选框)我张贴了另一种解决方案(反应母语-矢量图标) 这里。 这种方法使用矢量字体(来自 SVG)而不是 SVG 文件。 PS:react-native-vector-icons 是在 react-native 中处理 SVG 的最佳方法,它也适用于 iOS 和 android。 您将能够更改矢量图标的颜色和大小。
如果你想直接在你的应用中插入一个 svg,你可以尝试一个 3rd 方库:react-native-svg。 在 github 中拥有超过 3k 颗星,这是最好的方法之一。
使用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}
/>
);
安装react-native-svg-transformer
npm i react-native-svg-transformer --save-dev
我使用 SVG 如下,它工作正常
import LOGOSVG from "assets/svg/logo.svg"
在渲染中
<View>
<LOGOSVG
width="100%"
height="70%"
/>
</View>
我已经尝试了上述所有解决方案和堆栈之外的其他解决方案,但没有一个对我有用。 最后,经过长时间的研究,我为我的博览会项目找到了一种解决方案。
如果您需要它在博览会中工作,一种解决方法可能是使用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" />
);
}
你可以用一种简单的方法来做到这一点
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"] } }; })();
declare module "*.svg" { import { SvgProps } from "react-native-svg"; const content: React.FC<SvgProps>; export default content; }
最后,这是一个导入方法
import USER from "../../assets/icons/user.svg"
而且,这是针对 jsx
<USER width="100%" height="100%"/>
我有同样的问题。 我正在使用我发现的这个解决方案: React Native display SVG from a file
它并不完美,我今天重新审视,因为它在 Android 上的表现要差得多。
使用https://github.com/kristerkari/react-native-svg-transformer
在这个包中提到.svg
文件在 React Native v0.57 及更低版本中不受支持,因此对 svg 文件使用.svgx
扩展名。
对于 web 或 react-native-web 使用https://www.npmjs.com/package/@svgr/webpack
要使用react-native-svg-uri
和 react-native 版本 0.57 及更低版本渲染 svg 文件,您需要将以下文件添加到您的根项目中
注意:将扩展名
svg
更改为svgx
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 });
}
rn-cli.config.js
添加到项目的根目录module.exports = {
getTransformModulePath() {
return require.resolve("./transformer");
},
getSourceExts() {
return [/* "ts", "tsx", */ "svgx"];
}
};
上面提到的解决方案也适用于生产应用程序✅
SVG 在本机应用程序中不直接支持。 为了显示那些我们需要借助第三方模块
请按照以下步骤操作
第 1 步。 安装react-native-svg和react-native-svg-transformer
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>
)
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
}
});
在react native项目中使用svg并不像在web中使用那么简单,虽然也没有那么难。
在我看来,上述许多答案都很复杂。 所以,这是我使用和喜欢的解决方案。
由于 React Native 不直接支持 svg 文件格式,您需要执行一些步骤才能使其正常工作。
1.安装react-native-svg
npm install react-native-svg --save
这个package会帮你渲染svg文件
2.安装react-native-svg-transformer
npm install react-native-svg-transformer --save
这个 package 会将您的 svg 转换为本机可以理解的格式。
3.导入svg作为普通组件
import Belsvg from "../assets/belsvg.svg";
在导入时给它一个你喜欢的名字,现在这个 svg 被react-native-svg-transformer
转换成一个反应本机组件
4.现在你可以把它当作普通组件使用了
有关详细说明和示例,请访问链接:
https://kumar2396jayant.medium.com/how-to-use-svg-in-react-native-e581eca59534
ps:我要感谢Jayant kumar yadav发布该博客
注意:Svg 不适用于 android 发行版,所以不要考虑 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')} />
我用这两个插件
首先,您需要安装该插件。 之后,您需要使用此代码更改您的 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"]
}
};
})();
有关更多详细信息,您可以访问此链接
react-native-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
文件的本机矢量资产,称为react-native-vector-image 。 它不需要任何自定义 babel 转换,您可以像处理其他基于位图的资产一样使用它,但是将 svg 转换为原生等效项还有一个额外的步骤(尽管您只需要在添加新资产时运行它) )。
使用您的示例代码看起来像这样
import VectorImage from 'react-native-vector-image';
<View>
<VectorImage source={require('./svg/1f604.svg')} />
</View>
使用react-native-svg查看它同时支持 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 并返回Image组件或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 。
以防万一我有 ErrorBoundry 来覆盖异常。
它看起来像这样:
<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,反应本机 svg版本 ^12.1.0,您也可以将此方法用于其他版本,但请务必检查首先是图书馆的文档:
通过运行这个命令来安装react-native-svg-transformer
yarn add react-native-svg-transformer --dev
或者使用 npm 如果你喜欢npm i react-native-svg react-native-svg-transformer --save-dev
通过运行yarn add babel-plugin-inline-import --dev
安装babel-plugin-inline-import
您需要更新您的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'] } }; })();
确保将您的 svg 文件导入到您的组件中,如下所示: import CreditCard from '../assets/CreditCard';
请注意我没有将.svg
文件扩展名添加到导入中,这是因为它在运行时给了我这个错误view config getter callback react-native-svg
但删除它似乎使它运行顺利。 您可以通过这种方式将文件添加为 jsx 元素,例如<CreditCard />
。
最后通过在 mac 上使用^Ctrl + C
停止它来重新启动您的打包程序,然后使用此命令重新启动它yarn start:dev --reset-cache
并再次安装该应用程序。
您可以尝试使用https:\/\/svg2jsx.herokuapp.com\/<\/a>将 .svg 图像转换为 JSX
然后导入它,例如import open from "..\/..\/..\/..\/assets\/SVGFile";<\/code>
<\/li>
最后添加<SvgXml xml={open} scaleX={2} scaleY={2} width={20} height={20} \/><\/code>
<\/li><\/ul> 确保安装,yarn add react-native-svg
一切顺利!
如果有人在 2022 年遇到此错误,以下是对我有用的解决方案:
安装 react-native-svg-transformer :
yarn add react-native-svg-transformer --dev
或使用 npm
npm install react-native-svg-transformer --save-dev
安装 react-native-svg :
yarn add react-native-svg
或使用 npm
npm install react-native-svg --save
将您的 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"]
}};
})();
svg
图像,如下所示:import {View} from 'react-native';
import SvgImage from './path/to/svg/file.svg';
function MyComponent(){
return (
<View>
<SvgImage />
</View>
)
}
如果您将 React Native 与 TypeScript 一起使用,这里是分步解决方案:
1.安装react-native-svg
npm install react-native-svg
或者
yarn add react-native-svg
2.链接本机代码
cd ios && pod install
3.安装react-native-svg-transformer
npm install --save-dev react-native-svg-transformer
或者
yarn add --dev react-native-svg-transformer
4.配置react native packager
对于 React Native v0.59 或更新版本:
将项目的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"]
}
};
})();
这就是我合并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: true,
},
}),
},
resolver: {
assetExts: assetExts.filter((ext) => ext !== 'svg'),
sourceExts: [...sourceExts, 'svg'],
},
}
})()
5、TypeScript配置:
如果您使用的是 TypeScript,您需要将其添加到您的declarations.d.ts
文件中(如果您还没有,请创建一个):
declare module "*.svg" {
import React from 'react';
import { SvgProps } from "react-native-svg";
const content: React.FC<SvgProps>;
export default content;
}
6.用法
...
import LogSvg from '../assets/images/Logo.svg'
export function LandingScreen(): JSX.Element {
...
return (
<View style={style.mainContainer}>
<LogSvg style={style.logoContainer} />
</View>
)
}
...
请参阅我的教程 ,了解如何将SVG图标添加到React Native应用程序。
所有这些解决方案都非常可怕。 只需将您的 SVG 转换为 PNG 并使用 vanilla <Image/>
组件。 react-native 仍然不支持Image
组件中的 SVG 图像这一事实是一个笑话。 你永远不应该为这样一个简单的任务安装额外的库。 使用https://svgtopng.com/
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.