Comment afficher le fichier SVG sur React Native?

103

Je veux afficher des fichiers svg (j'ai un tas d'images svg) mais je n'ai pas trouvé le moyen de le montrer. J'ai essayé d'utiliser les composants Image et Use de react-native-svg mais ils ne fonctionnent pas avec ça. Et j'ai essayé de le faire de manière native, mais c'est vraiment difficile de montrer juste une image svg.

Exemple de code:

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

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

De plus, je sais que le natif de réaction ne prend pas en charge le svg, mais je pense que quelqu'un a résolu ce problème de manière délicate (avec / sans react-native-svg)

the_bluescreen
la source
Vous ne pouvez pas utiliser pour afficher un fichier entier, vous auriez besoin d'une image pour cela.
Robert Longson
Ouais je l'ai essayé aussi @RobertLongson mais ça ne marche pas non plus.
the_bluescreen
Vous pouvez l'ajouter en tant que backgroundImage css, l'avez-vous essayé?
danielarend
J'ai essayé mais le composant natif de réaction ne prend pas en charge la prop backgroundImage sur le style css. @danielarend
the_bluescreen
Je ne sais pas pourquoi vous utiliseriez un wrapper SVG pour envelopper une image SVG.
Robert Longson

Réponses:

70

J'ai utilisé la solution suivante:

  1. Convertir l' .svgimage en JSX avec https://svg2jsx.herokuapp.com/
  2. Convertissez le JSX en react-native-svgcomposant avec https://svgr.now.sh/ (cochez la case "React Native)
Ihor Burlachenko
la source
Comment utiliser ce composant alors? Pouvez-vous partager un code?
Indranil Dutta
Si vous suivez ce lien, vous verrez un exemple avec les importations svgr.now.sh (cochez la case "React Native). Utilisez-le comme un composant React normal, placez-le à la place de <Image src = {...} /> et ça devrait marcher.
Ihor Burlachenko
1
@IhorBurlachenko quand j'ai fatigué votre solution, j'ai obtenu cette erreur Erreur non interceptée: Violation invariante: le type d'élément n'est pas valide: une chaîne attendue (pour les composants intégrés) ou une classe / fonction mais obtenu: objet . pouvez-vous m'aider ici?
Mighty
2
Si vous rencontrez des problèmes avec cette approche, assurez-vous d'installer la dernière version du react-native-svgpackage. Assurez-vous également d'exécuter cette commande pour lier votre packagereact-native link react-native-svg
connect2Coder
2
Il s'agit d'un long processus pour implémenter les fichiers SVG, mieux utiliser github.com/kristerkari/react-native-svg-transformer comme suggéré ci-dessous stackoverflow.com/a/55604442/1854104
hefgi
10

J'ai posté une autre solution ici Quelle est la meilleure approche pour insérer un graphique vectoriel (svg) dans une application native react , Cette approche utilise une police vectorielle (de svg) à la place d'un fichier svg. PS: Cela fonctionne très bien sous iOS et Android, et vous pouvez également modifier la couleur et la taille de votre icône vectorielle.

Si vous souhaitez insérer un svg directement dans votre application, vous pouvez essayer une bibliothèque tierce: react-native-svg. Avec plus de 3k étoiles dans github, c'est l'une des meilleures approches.

  • installer:
    • npm je réagis-natif-svg
    • npm je réagis-natif-svg-uri
  • liez le au natif:
    • React-Native Link React-Native-SVG

Et voici un échantillon:

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}
  />
);
Cassio Seffrin
la source
Cela donne une erreur "impossible d'ajouter un enfant qui n'a pas de noeud css à un noeud sans fonction de mesure".
Pulkit Aggarwal
J'ai utilisé le dernier avec source = {require ('myImagePath')} mais cela me donne une erreur.
Pulkit Aggarwal
1
Regardez la réponse que je poste ici, en utilisant une police à la place d'un svg. c'est une meilleure solution: stackoverflow.com/questions/49951885/…
Cassio Seffrin
2
Cette bibliothèque est si lente. Il enveloppe chaque svg dans sa propre vue Web.
JP_
1
tnx, c'était la solution la plus rapide, mais au lieu de svgXmlData = {testSvg}, j'ai utilisé source = {testSvg} fonctionnait comme un charme. tnx à nouveau.
Andris Laduzans
9

Après avoir essayé de nombreuses méthodes et bibliothèques, j'ai décidé de créer une nouvelle police (avec des glyphes ou ce tutoriel ) et d'y ajouter mes fichiers SVG, puis d'utiliser le composant "Texte" avec ma police personnalisée.

J'espère que cela aidera quiconque a le même problème avec SVG en React-Native.

Amir Khorsandi
la source
Je pense que vous avez raison, une famille de polices est probablement le moyen le plus simple d'obtenir des svgs simples en natif de réaction
Joe Lloyd
Beau tutoriel sur ce sujet: blog.bam.tech/developper-news/… . Nécessite le package Vector Icons Node.
Rafa
Cette solution n'est pas valide si vous devez importer un fichier d'affaissement multicolore
Joe Aspara
J'ai essayé sa solution avec icomoon et cela n'a pas fonctionné ni leur support n'est actif. Et fontello modifie mes svgs.
Siraj Alam
6

Installez react-native-svg-transformer

npm je réagis-native-svg-transformer --save-dev

J'utilise SVG comme suit et cela fonctionne bien

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

en rendu

<View>
  <LOGOSVG 
    width="100%"
    height="70%"
  />
</View>
AndroConsis
la source
Lorsque j'importe le fichier svg HEARTSVG à partir du dossier d'image, il affiche une erreur. Et aucune erreur pour importer des fichiers png. Toute suggestion?
Rakesh
4

J'ai eu le même problème. J'utilise cette solution que j'ai trouvée: React Native display SVG à partir d'un fichier

Ce n'est pas parfait, et je revisite aujourd'hui, car il fonctionne bien moins bien sur Android.

Marteau de forgeron
la source
En fait, c'est une réponse créative mais cela n'aide pas mes ajustements :) Parce que j'utiliserai une liste d'icônes (10 icônes SVG ou plus), donc si j'utilise cela, cela peut être vraiment mauvais pour les performances, je suppose. Qu'est-ce que tu penses?
the_bluescreen
J'ai rendu 10 à 15 svgs sur une page. Personne ne s'est plaint sur iOS, tout le monde s'est plaint sur Android. Sur iOS, il y a un délai de 0,1 à 0,3 seconde (une fraction de seconde flash de blanc avant le chargement). Sur Android, cela peut prendre 1 seconde et parfois ils ne se chargent jamais. À la fin, j'ai vérifié mes SVG, puis j'ai écrit un script qui les convertit en PNG de la taille exacte en utilisant svg2png . Puis utilisé <Image>avec ces PNG. Compte tenu de l'état actuel du SVG dans React native, il n'y a pas d'ETA pour les SVG fonctionnant, c'est donc votre meilleur pari si vous ne pouvez pas tolérer le travail.
Sledge Hammer
3

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

Dans ce package, il est mentionné que les .svgfichiers ne sont pas pris en charge dans React Native v0.57 et versions antérieures, utilisez donc l' .svgxextension pour les fichiers svg.

Pour le Web ou React-Native-Web, utilisez https://www.npmjs.com/package/@svgr/webpack


Pour rendre les fichiers svg à l'aide react-native-svg-uride la version 0.57 et inférieure de react-native, vous devez ajouter les fichiers suivants à votre projet racine

Remarque: remplacez l'extension svgparsvgx

étape 1: ajouter un fichier transformer.jsà la racine du projet

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

étape 2: ajouter rn-cli.config.jsà la racine du projet

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

Les solutions mentionnées ci-dessus fonctionneront également dans les applications de production ✅

Aravind Vemula
la source
2

J'ai essayé toutes les solutions ci-dessus et d'autres solutions en dehors de la pile et aucune ne fonctionne pour moi. enfin, après de longues recherches, j'ai trouvé une solution pour mon projet d'expo.

Si vous en avez besoin pour fonctionner dans expo, une solution de contournement pourrait être d'utiliser https://react-svgr.com/playground/ et de déplacer la répartition des accessoires vers un élément G au lieu de la racine SVG comme ceci:

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" />
  );
}
Akshay Italiya
la source
Cela fonctionne également très bien pour moi. Nous pouvons facilement obtenir le chemin du fichier svg en l'ouvrant sur le navigateur et afficher la source de la page, puis utiliser directement le chemin et remplacer la balise <path /> par react-native-svg <Path />. GRAND MERCI
Rakesh
0

Remarque: Svg ne fonctionne pas pour les versions Android, donc ne considérez pas pour Android. Cela fonctionnera pour Android en mode débogage uniquement. Mais cela fonctionne bien pour iOS.

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

Installer

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

Usage

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


<SvgUri source={require('./path_to_image/image.svg')} />
Daniel Raouf
la source
@AravindVemula vous avez raison. Cela ne fonctionne pas pour les versions Android. Je n'ai pas non plus trouvé de solution. Il n'y a probablement pas de solution jusqu'à présent. J'ai abandonné l'utilisation du svg et je suis revenu à la manière traditionnelle de réagir aux images natives
Daniel Raouf
0

J'utilise ces deux plugins,

  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 )

Tout d'abord, vous devez installer ce plugin. Après cela, vous devez changer votre metro.config.js, avec ce code.

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"]
    }
  };
})();

Pour plus de détails, vous pouvez visiter ce lien

Ganda Rain Panjaitan
la source
0

vous pouvez convertir n'importe quel SVG en composant et le rendre réutilisable.

voici ma réponse pour la façon la plus simple de le faire

SVG vers composant

Anas
la source
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
  }
});
bello hargbola
la source
utiliser npm install react-native-svg-uri --savepour installer le package nécessaire
bello hargbola
-6

Toutes ces solutions sont absolument horribles. Convertissez simplement votre SVG en PNG et utilisez le <Image/>composant vanilla . Le fait que react-native ne supporte toujours pas les images SVG dans le Imagecomposant est une blague. Vous ne devez jamais installer une bibliothèque supplémentaire pour une tâche aussi simple. Utilisez https://svgtopng.com/

YungGun
la source
1
C'est un projet open-source - Je suis sûr qu'ils seraient satisfaits de votre pull request si vous avez une meilleure solution que celle mentionnée ci-dessus ... :)
Herald Smit