如何在React Native上显示SVG文件?


101

我想显示svg文件(我有一堆svg图像),但是我找不到显示方法。我尝试使用react-native-svg的ImageUse组件,但是它们不能使用。我试图用本机的方式做到这一点,但是要显示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)


您不能使用use来显示整个文件,您需要使用图像。
罗伯特·朗森,2016年

是的,我也尝试过@RobertLongson,但它也不起作用。
the_bluescreen

您可以将其添加为CSS backgroundImage,您是否尝试过?
danielarend '16

我试过了,但做出反应,本机View组件在CSS样式上不支持backgroundImage prop。@danielarend
the_bluescreen

我不确定为什么要使用SVG包装器包装SVG图像。
罗伯特·朗森

Answers:


69

我使用以下解决方案:

  1. .svg使用https://svg2jsx.herokuapp.com/将图像转换为JSX
  2. react-native-svg使用https://svgr.now.sh/将JSX转换为组件(选中“ React Native”复选框)

然后如何使用该组件?可以共享代码吗?
Indranil Dutta

如果您点击此链接,您将看到一个带有import svgr.now.sh的示例(选中“ React Native”复选框)。将其用作常规的React组件,放置它而不是<Image src = {...} />它应该工作。
伊霍尔Burlachenko

1
@IhorBurlachenko,当我厌倦了您的解决方案时,出现了此错误Uncaught Error:Invariant Violation:元素类型无效:预期为字符串(用于内置组件)或类/函数,但得到了:object。你能帮我吗?
全能,

2
如果有人在使用此方法时遇到问题,请确保您确实安装了最新版本的react-native-svg软件包。还要确保运行此命令来链接您的程序包react-native link react-native-svg
connect2Coder

2
这是实现SVG文件的漫长过程,最好使用github.com/kristerkari/react-native-svg-transformer,如下所示stackoverflow.com/a/55604442/1854104
hefgi

10

我在这里发布了另一个解决方案,这是将向量(SVG)图插入React Native应用程序的最佳方法,该方法使用向量字体(来自svg)而不是svg文件。PS:它在ios和android上都很好用,您还可以更改矢量图标的颜色和大小。

如果您想将svg直接插入到您的应用中,可以尝试使用第3方库:react-native-svg。github中有超过3k的星星,这是最好的方法之一。

  • 安装:
    • NPM我反应本机SVG
    • npm我react-native-svg-uri
  • 链接到本机:
    • react-native链接react-native-svg

这是一个示例:

import * as React from 'react';
import SvgUri from 'react-native-svg-uri';
import testSvg from './test.svg';
export default () => (
  <SvgUri
    width="200"
    height="200"
    svgXmlData={testSvg}
  />
);

它给出了一个错误“无法将没有css节点的子节点添加到没有度量函数的节点中”。
Pulkit AGGARWAL

我将最后一个与source = {require('myImagePath')}一起使用,但这给了我错误。
Pulkit AGGARWAL

1
看看我在这里发布的答案,使用字体而不是svg。这是一个更好的解决方案:stackoverflow.com/questions/49951885/...
凯西奥Seffrin

2
这个库太慢了。它将每个svg包装在自己的web视图中。
JP_19年

1
tnx,这是最快的解决方案,但是我使用的是source = {testSvg}而不是svgXmlData = {testSvg}。再次tnx。
Andris Laduzans

9

在尝试了多种方法和库之后,我决定创建一种新字体(使用Glyphs或本教程),并向其中添加SVG文件,然后使用具有自定义字体的“文本”组件。

希望这对任何在本机上与SVG有相同问题的人有所帮助。


我认为您是对的,字体家族可能是使简单的svg转换为本机脚本的最简单方法
Joe Lloyd

关于该主题的不错的教程:blog.bam.tech/developper-news/…。需要“矢量图标”节点软件包。
拉法

如果您需要导入多色sag文件,此解决方案无效
Joe Aspara

我曾在icomoon上尝试过其解决方案,但仍无法解决他们的支持问题。Fontello正在改变我的svg。
Siraj Alam

6

安装react-native-svg-transformer

npm我react-native-svg-transformer-保存开发

我正在使用以下SVG,它工作正常

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

在渲染

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

当我从图像文件夹导入SVG文件HEARTSVG时,它显示错误。导入png文件也没有错误。有什么建议吗?
拉克什

4

我有同样的问题。我正在使用以下解决方案:从文件中响应本机显示SVG

它不是完美的,我今天要回顾一下,因为它在Android上的表现要差很多。


实际上,这是一个有创意的答案,但并不能帮助我适应问题:)因为我将使用图标列表(10个或更多个SVG图标),所以如果我使用它,则可能会降低性能。你怎么看?
the_bluescreen '16

我在页面上渲染了10-15个svg。没有人抱怨iOS,每个人都抱怨Android。在iOS上有0.1-0.3秒的延迟(加载前会瞬间闪烁白色)。在Android上可能是1秒,有时它们永远不会加载。最后,我签入了SVG,然后编写了一个脚本,使用svg2png将它们转换为大小正确的PNG 。然后<Image>与这些PNG一起使用。考虑到SVG在react native中的当前状态,没有适用于SVG的ETA,因此,如果您不能忍受这种解决方法,那么这是最好的选择。
大锤2013年

3

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

在这个包中,提到.svgReact Native v0.57及更低版本不支持文件,因此请使用.svgx对svg文件扩展名。

对于Web或react-native-web使用https://www.npmjs.com/package/@svgr/webpack


要使用react-native-svg-urireact-native版本0.57及更低版本渲染svg文件,您需要在根项目中添加以下文件

注意:将扩展名更改svgsvgx

步骤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"];
    }
  };

上面提到的解决方案也可以在生产应用中使用✅


2

我已经尝试了上述所有解决方案以及堆栈之外的其他解决方案,但没有一个对我有用。最终,经过长期的研究,我为我的世博项目找到了一种解决方案。

如果您需要它在博览会上工作,一种解决方法可能是使用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" />
  );
}

这对我也很好。通过在浏览器中打开svg文件的路径并查看页面源代码,然后直接使用path并用react-native-svg <Path />替换<path />标记,我们可以轻松获取svg文件的路径。非常感谢
Rakesh

0

注意: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')} />

@ AravindVemula你是对的。它不适用于android发行版本。我也找不到解决方案。到目前为止可能还没有解决方案。我放弃了使用svg的方法,转而使用了反应本地图像的传统方式
Daniel Raouf

0

我使用这两个插件

  1. [react-native-svg] https://github.com/react-native-community/react-native-svg
  2. [react-native-svg-transformer] 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"]
    }
  };
})();

有关更多详细信息,您可以访问此链接



0
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
  }
});

用于npm install react-native-svg-uri --save安装所需的软件包
bello hargbola

-6

所有这些解决方案都是绝对可怕的。只需将SVG转换为PNG并使用香草<Image/>成分即可。React-native仍然不支持Image组件中的SVG图像这一事实是个玩笑。您绝对不应为此类简单任务安装其他库。使用https://svgtopng.com/


1
这是一个开源项目-如果您有比上述更好的解决方案,我相信他们会对您的请求请求感到满意... :)
Herald Smit
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.