Как показать файл SVG на React Native?

Я хочу показать файлы SVG (у меня есть куча изображений SVG), но я не смог найти способ показать. Я пытался использовать компоненты Image и Useact-native-svg, но они не работают с этим. И я попытался сделать это с родным способом, но это действительно тяжелая работа, чтобы показать только изображение SVG.

Пример кода:

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

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

Также я знаю, что реактивный native не поддерживает svg, но я думаю, что кто-то исправил эту проблему хитрым способом (с / без response-native-svg)

25 ответов

Я использовал следующее решение:

  1. Преобразуйте изображение.svg в JSX с помощью https://svg2jsx.herokuapp.com/
  2. Конвертировать JSX в react-native-svg компонент с https://svgr.now.sh/ (установите флажок "React Native")

Установите https://github.com/kristerkari/react-native-svg-transformer

npm я реагирую-родной-SVG-трансформатор --save-dev

Я использую SVG следующим образом, и он отлично работает

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

в рендере

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

Я разместил другое решение здесь. Как я могу вставить изображение в формате svg в реактивное приложение. Этот подход использует векторный шрифт (из svg) вместо файла svg. PS: он прекрасно работает в iOS и Android, и вы также можете изменить цвет и размер вашего векторного значка.

Если вы хотите попробовать вставить svg непосредственно в свое приложение, вы можете попробовать response-native-remote-svg, у этого подхода есть проблемы с android https://github.com/seekshiva/react-native-remote-svg

установите lib: yarn, добавьте реактив-native-remote-svg, импортируйте на экран:

import Image from 'react-native-remote-svg'

и использовать

 <View>
    <Image source={require('./money.svg')} />
</View>

Я пробовал все вышеперечисленные решения и другие решения вне стека, и ни один из них не работал у меня. наконец, после долгих исследований я нашел одно решение для своего выставочного проекта.

Если вам нужно, чтобы он работал в 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" />
  );
}

Метод, который работает у меня в 2022 году для тех, кто все еще застрял на этом, реагируйте на нативную версию 0.63.4, реагируйте на нативную-svg версию ^12.1.0, вы можете использовать этот метод и для других версий, но всегда проверяйте сначала документы для библиотеки:

  1. Установить react-native-svg-transformerвыполнив эту команду yarn add react-native-svg-transformer --devили используя npm, если вы предпочитаете npm i react-native-svg react-native-svg-transformer --save-dev

  2. Установить babel-plugin-inline-importзапустив yarn add babel-plugin-inline-import --dev

  3. Вам необходимо обновить свой metro.config.jsфайл выглядит следующим образом:

  1. Обязательно импортируйте файл svg в свой компонент следующим образом: import CreditCard from '../assets/CreditCard';обратите внимание, как я не добавляю .svgрасширение файла для импорта, это потому, что это дало мне эту ошибку view config getter callback react-native-svgво время его запуска, но его удаление, кажется, делает его более плавным. Вы можете добавить свой файл таким образом, как элемент jsx, подобный этому <CreditCard />.

  2. Наконец, перезапустите упаковщик, остановив его с помощью ^Ctrl + Cна Mac, затем перезапустите его снова с помощью этой команды yarn start:dev --reset-cacheи снова установите приложение.

вы можете сделать это простым способом

сначала следует заняться установкой,

  1. npm install -s react-native-svg
  2. реакция-родная ссылка реакция-родной-svg
  3. npm install -s react-native-svg-transformer

тогда вы должны добавить следующий код в свой файл metro.config.js

Попробовав множество способов и библиотек, я решил создать новый шрифт (с помощью Glyphs или этого учебного пособия) и добавить к нему мои SVG-файлы, а затем использовать компонент "Текст" с моим собственным шрифтом.

Надеюсь, что это поможет любому, у кого такая же проблема с SVG в реакции-нативной.

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 . Используйте файл SVG как компонент React

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

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

Используйте https://github.com/kristerkari/react-native-svg-transformer

В этом пакете упоминается, что .svg файлы не поддерживаются в React Native v0.57 и ниже, поэтому используйте .svgx расширение для файлов SVG.

Для веб-сайта или для реагирования на родной веб-сайт используйте https://www.npmjs.com/package/@svgr/webpack


Для рендеринга SVG-файлов с помощью react-native-svg-uri с реактивной версией 0.57 и ниже, вам нужно добавить следующие файлы в ваш корневой проект

Примечание: изменить расширение 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"];
    }
  };

Вышеупомянутые решения будут работать и в производственных приложениях ✅

У меня такая же проблема. Я использую это решение, которое я нашел: React Native display SVG из файла

Он не идеален, и я возвращаюсь сегодня, потому что он работает намного хуже на Android.

Если вы используете 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 v0.59 или новее:

Объедините содержимое файла вашего проекта с этой конфигурацией (создайте файл, если он еще не существует).

      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 не так просто, как в вебе, хотя и не так сложно.

Многие из приведенных выше ответов сложны, на мой взгляд. Итак, вот решение, которое я использую и которое мне нравится.

Поскольку react native не поддерживает формат файла svg напрямую, вам нужно выполнить несколько шагов, чтобы заставить его работать.

1. Установите реактивный родной SVG

       npm install react-native-svg --save

Этот пакет поможет вам визуализировать файл svg

2. Установите реактивный трансформер svg

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

Этот пакет преобразует ваш 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: Я хотел бы поблагодарить Джаянта Кумара Ядава за публикацию этого блога .

Вы можете преобразовать любой 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
  }
});

я пытаюсь использоватьSvgCssUriи это работает

      import { SvgCssUri } from 'react-native-svg';
...
...
...
<SvgCssUri 
style={{height: 100, width: 100}} 
uri={"http://thenewcode.com/assets/images/thumbnails/homer-simpson.svg"} />

Я использую эти два плагина,

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

Более подробную информацию вы можете найти по этой ссылке.

Я написал новую библиотеку, чтобы иметь возможность использовать собственные векторные ресурсы на основе .svgфайлы, называемые response-native-vector-image. Ему не нужны никакие пользовательские преобразования babel, и вы можете использовать его, как и для других активов на основе растровых изображений, но есть дополнительный шаг в преобразовании svg в нативные эквиваленты (вам нужно только запускать его, когда вы добавляете новые активы, хотя ).

Используя ваш пример, код будет выглядеть примерно так

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

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

Используйте 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/seekshiva/react-native-remote-svg.

Я дополнительно сделал условный рендеринг с https://github.com/react-native-svg/react-native-svg , чтобы получить наилучший результат на обеих платформах, потому что есть известная проблема с Android, как указано здесь /questions/42734530/kak-pokazat-fajl-svg-na-react-native/42734541#42734541.

На всякий случай у меня есть 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>
  1. Первая установка react-native-svg к вашему проекту.
  2. Откройте https://react-svgr.com/, перейдите на игровую площадку и выберите React native.
  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

Если кто-то застрял на этой ошибке в 2022 году, вот решение, которое сработало для меня:

  1. Установите react-native-svg-transformer :
    yarn add react-native-svg-transformer --dev
    или используя нпм
    npm install react-native-svg-transformer --save-dev

  2. Установите react-native-svg :
    yarn add react-native-svg
    или используя нпм
    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 в JSX с помощью https://svg2jsx.herokuapp.com/

  • Затем сохраните код JSX в Assest/SVGFile.js.
  • Затем импортируйте его, например import open from "../../../../assets/SVGFile";
  • Наконец добавьте <SvgXml xml={open} scaleX={2} scaleY={2} width={20} height={20} />

Обязательно установите пряжу, добавьте react-native-svg

Всего наилучшего!

Пожалуйста, обратитесь к моему руководству о том, как добавить иконки SVG в ваше приложение React Native.

Используйте response-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, и возвращает компонент изображения или 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"

Все эти решения абсолютно ужасны. Просто конвертируйте свой SVG в PNG и используйте ванильный<Image/>составная часть. Тот факт, что react-native по-прежнему не поддерживает изображения SVG вImageкомпонент - это шутка. Никогда не устанавливайте дополнительную библиотеку для такой простой задачи. Используйте https://svgtopng.com/

Другие вопросы по тегам