Jak wyświetlić plik SVG w React Native?

111

Chcę pokazać pliki SVG (mam kilka obrazów SVG), ale coś, czego nie mogłem znaleźć sposobu na pokazanie. Próbowałem użyć komponentów Image i Use z React-native-svg, ale nie działają z tym. Próbowałem to zrobić w natywny sposób, ale pokazanie tylko obrazu svg jest naprawdę ciężką pracą.

Przykładowy kod:

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

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

Wiem też, że React Native nie obsługuje w zasadzie svg, ale myślę, że ktoś naprawił ten problem w trudny sposób (z / bez React-native-SVG)

the_bluescreen
źródło
Nie możesz użyć do wyświetlenia całego pliku, potrzebujesz do tego obrazu.
Robert Longson
Tak, próbowałem też @RobertLongson, ale to też nie działa.
the_bluescreen
Możesz dodać to jako css backgroundImage, czy próbowałeś tego?
danielarend
Próbowałem, ale komponent React Native View nie obsługuje właściwości backgroundImage w stylu css. @danielarend
the_bluescreen
Nie jestem pewien, dlaczego miałbyś użyć opakowania SVG do zawijania obrazu SVG.
Robert Longson

Odpowiedzi:

75

Użyłem następującego rozwiązania:

  1. Konwertuj .svgobraz na JSX za pomocą https://svg2jsx.herokuapp.com/
  2. Konwertuj JSX na react-native-svgkomponent za pomocą https://svgr.now.sh/ (zaznacz pole wyboru „React Native)
Ihor Burlachenko
źródło
Jak więc używać tego komponentu? Czy możesz udostępnić kod?
Indranil Dutta
Jeśli klikniesz ten link, zobaczysz przykład z importem svgr.now.sh (zaznacz pole wyboru „React Native). Użyj go jako zwykłego komponentu Reacta, zamiast <Image src = {...} /> i powinno działać
Ihor Burlachenko
1
@IhorBurlachenko Kiedy znudziłem twoje rozwiązanie, otrzymałem ten błąd Uncaught Error: Niezmienione naruszenie: Typ elementu jest nieprawidłowy: oczekiwano ciągu (dla wbudowanych komponentów) lub klasy / funkcji, ale otrzymałem: obiekt . czy możesz mi tu pomóc?
Potężny
2
Każdy, kto ma problem z użyciem tego podejścia, upewnij się, że instalujesz najnowszą wersję react-native-svgpakietu. Upewnij się również, że uruchomiłeś to polecenie, aby połączyć swój pakietreact-native link react-native-svg
connect2Coder
2
To długi proces implementacji plików SVG, lepiej korzystaj z github.com/kristerkari/react-native-svg-transformer, jak zasugerowano poniżej stackoverflow.com/a/55604442/1854104
hefgi
10

Opublikowałem tutaj inne rozwiązanie, które jest najlepszym podejściem do wstawienia wykresu wektorowego (svg) do natywnej aplikacji reagującej. To podejście wykorzystuje czcionkę wektorową (z svg) zamiast pliku svg. PS: Działa świetnie na iOS i Android, a także możesz zmienić kolor i rozmiar ikony wektora.

Jeśli chcesz wstawić plik SVG bezpośrednio do swojej aplikacji, możesz wypróbować bibliotekę innej firmy: React-native-svg. Z ponad 3 tysiącami gwiazdek na githubie jest to jedno z najlepszych rozwiązań.

  • zainstalować:
    • npm reaguję-native-svg
    • npm reaguję-native-svg-uri
  • połącz z natywnym:
    • łącze react-natywne reaguj-natywne-svg

A oto próbka:

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
źródło
Daje błąd „nie można dodać dziecka, które nie ma węzła css do węzła bez funkcji miary”.
Pulkit Aggarwal
Użyłem ostatniego z source = {require ('myImagePath')}, ale daje mi błąd.
Pulkit Aggarwal
1
Spójrz na odpowiedź, którą tutaj zamieszczam, używając czcionki zamiast svg. to lepsze rozwiązanie: stackoverflow.com/questions/49951885/ ...
Cassio Seffrin
2
Ta biblioteka działa tak wolno. Otacza każdy plik SVG we własnym widoku internetowym.
JP_
1
tnx, to było najszybsze rozwiązanie, ale zamiast svgXmlData = {testSvg} użyłem source = {testSvg} działało jak urok. tnx ponownie.
Andris Laduzans
9

Po wypróbowaniu wielu sposobów i bibliotek zdecydowałem się stworzyć nową czcionkę (z Glifami lub tym samouczkiem ) i dodać do niej moje pliki SVG, a następnie użyć komponentu "Tekst" z moją niestandardową czcionką.

Mam nadzieję, że pomoże to każdemu, kto ma ten sam problem z SVG w natywnym reagowaniu.

Amir Khorsandi
źródło
Myślę, że masz rację, rodzina czcionek to chyba najprostszy sposób na uzyskanie prostych pomostów żylnych w reagują rodzimy
Joe Lloyd
Niezły tutorial na ten temat: blog.bam.tech/developper-news/… . Wymaga pakietu Vector Icons Node.
Rafa,
To rozwiązanie nie jest poprawne, jeśli musisz zaimportować wielokolorowy plik zwisu
Joe Aspara
Wypróbowałem jego rozwiązanie z icomoon i nie wyszło, ani ich wsparcie nie jest aktywne. Fontello zmienia moje pliki SVG.
Siraj Alam,
6

Zainstaluj React-native-svg-transformer

npm reaguję-native-svg-transformer --save-dev

Używam SVG w następujący sposób i działa dobrze

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

w renderowaniu

<View>
  <LOGOSVG 
    width="100%"
    height="70%"
  />
</View>
AndroConsis
źródło
Kiedy importuję plik SVG HEARTSVG z folderu obrazu, to pokazuje błąd. I bez błędu importowania plików png. Jakieś sugestie?
Rakesh
4

Miałem ten sam problem. Używam tego rozwiązania, które znalazłem: React Native wyświetla SVG z pliku

To nie jest idealne i wracam dzisiaj, ponieważ działa o wiele gorzej na Androidzie.

Młot kowalski
źródło
Właściwie to kreatywna odpowiedź, ale nie pomaga w moich dopasowaniach :) Ponieważ użyję listy ikon (10 lub więcej ikon SVG), więc jeśli tego użyję, może to być naprawdę złe dla wydajności. Co myślisz?
the_bluescreen
Wyrenderowałem 10-15 svg na stronie. Nikt nie narzekał na iOS, wszyscy narzekali na Androida. W iOS występuje opóźnienie 0,1-0,3 sekundy (ułamek sekundy błysk bieli przed załadowaniem). Na Androidzie może to trwać 1 sekundę, a czasami nigdy się nie ładują. W końcu sprawdziłem swoje pliki SVG, a następnie napisałem skrypt, który konwertuje je na pliki PNG o dokładnie odpowiednim rozmiarze za pomocą svg2png . Następnie używany <Image>z tymi plikami PNG. Biorąc pod uwagę obecny stan SVG w React Native, nie ma ETA dla działania SVG, więc jest to najlepszy zakład, jeśli nie możesz tolerować tej obejścia.
Sledge Hammer
3

Użyj https://github.com/kristerkari/react-native-svg-transformer

W tym pakiecie jest wspomniane, że .svgpliki nie są obsługiwane w React Native v0.57 i niższych, więc używaj .svgxrozszerzenia dla plików svg.

W przypadku sieci Web lub React-Native-Web użyj https://www.npmjs.com/package/@svgr/webpack


Aby renderować pliki svg przy użyciu oprogramowania react-native-svg-uriReact-Native w wersji 0.57 i starszych, musisz dodać następujące pliki do projektu głównego

Uwaga: zmień rozszerzenie svgnasvgx

krok 1: dodaj plik transformer.jsdo katalogu głównego projektu

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

krok 2: dodaj rn-cli.config.jsdo katalogu głównego projektu

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

Powyższe rozwiązania sprawdzą się również w aplikacjach produkcyjnych ✅

Aravind Vemula
źródło
3

Wypróbowałem wszystkie powyższe rozwiązania i inne rozwiązania poza stosem i żadne z nich nie działało dla mnie. wreszcie po długich poszukiwaniach znalazłem jedno rozwiązanie dla mojego projektu na targi.

Jeśli potrzebujesz go do pracy w expo, jednym obejściem może być użycie https://react-svgr.com/playground/ i przeniesienie rozprzestrzeniania się rekwizytów do elementu G zamiast do katalogu głównego SVG w następujący sposób:

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
źródło
1
To również działa dobrze dla mnie. Możemy łatwo uzyskać ścieżkę do pliku svg, otwierając go w przeglądarce i przeglądając źródło strony, a następnie bezpośrednio użyj ścieżki i zamień tag <path /> na react-native-svg <Path />. WIELKIE DZIĘKI
Rakesh
1

możesz to zrobić w prosty sposób

najpierw należy przeprowadzić instalację,

  1. npm install -s respond-native-svg
  2. łącze react-natywne reaguj-natywne-svg
  3. npm install -s respond-native-svg-transformer

Następnie należy dodać następujący kod do pliku 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"]
    }
  };
})();

następnie powinieneś utworzyć nowy plik w swoim katalogu głównym o nazwie declarations.d.js z następującym kodem

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

Wreszcie, to jest mathod importu

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

i to jest dla jsx

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

vasanth saravanan
źródło
0

Uwaga: Svg nie działa dla wersji Androida, więc nie rozważaj dla Androida. Będzie działać tylko dla Androida w trybie debugowania. Ale działa dobrze na iOS.

Użyj https://github.com/vault-development/react-native-svg-uri

zainstalować

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

Stosowanie

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


<SvgUri source={require('./path_to_image/image.svg')} />
Daniel Raouf
źródło
@AravindVemula masz rację. Nie działa w wersjach Androida. Nie mogłem też znaleźć rozwiązania. Prawdopodobnie do tej pory nie ma rozwiązania. Porzuciłem używanie svg i wróciłem do tradycyjnego sposobu reagowania na rodzime obrazy
Daniel Raouf
0

Używam tych dwóch wtyczek,

  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 )

Przede wszystkim musisz zainstalować tę wtyczkę. Następnie musisz zmienić swój metro.config.js za pomocą tego kodu.

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

Aby uzyskać więcej informacji, możesz odwiedzić ten link

Ganda Rain Panjaitan
źródło
0

możesz przekonwertować dowolny plik SVG na komponent i uczynić go wielokrotnego użytku.

oto moja odpowiedź na najłatwiejszy sposób, w jaki możesz to zrobić

SVG do komponentu

Anas
źródło
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
źródło
użyj, npm install react-native-svg-uri --saveaby zainstalować potrzebny pakiet
bello hargbola
-6

Wszystkie te rozwiązania są absolutnie okropne. Po prostu przekonwertuj plik SVG na PNG i użyj <Image/>komponentu waniliowego . Fakt, że react-native nadal nie obsługuje obrazów SVG w Imagekomponencie, to żart. Nigdy nie powinieneś instalować dodatkowej biblioteki dla tak prostego zadania. Użyj https://svgtopng.com/

YungGun
źródło
1
Jest to projekt typu open source - jestem pewien, że byliby zadowoleni z twojej prośby o ściągnięcie, gdybyś miał lepsze rozwiązanie niż wspomniane powyżej ... :)
Herald Smit