จะแสดงไฟล์ SVG บน React Native ได้อย่างไร?


111

ฉันต้องการแสดงไฟล์ svg (ฉันมีภาพ svg มากมาย) แต่สิ่งที่ฉันหาวิธีแสดงไม่เจอ ฉันพยายามใช้ส่วนประกอบImage and Useของreact-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>

นอกจากนี้ฉันรู้ว่า react native ไม่รองรับ svg โดยทั่วไป แต่ฉันคิดว่ามีคนแก้ไขปัญหานี้ด้วยวิธีที่ยุ่งยาก (มี / ไม่มี react-native-svg)


คุณไม่สามารถใช้เพื่อแสดงทั้งไฟล์ได้คุณต้องใช้รูปภาพนั้น
Robert Longson

ใช่ฉันลองด้วย @RobertLongson แต่ก็ไม่ได้ผลเช่นกัน
the_bluescreen

คุณสามารถเพิ่มเป็น css backgroundImage คุณได้ลองหรือยัง
danielarend

ฉันพยายาม แต่ตอบสนองคอมโพเนนต์มุมมองดั้งเดิมไม่รองรับ backgroundImage prop ในสไตล์ css @danielarend
the_bluescreen

ฉันไม่แน่ใจว่าทำไมคุณถึงใช้กระดาษห่อ SVG เพื่อตัดภาพ SVG
Robert Longson

คำตอบ:


75

ฉันใช้วิธีแก้ปัญหาต่อไปนี้:

  1. แปลง.svgภาพเป็น JSX ด้วยhttps://svg2jsx.herokuapp.com/
  2. แปลง JSX เป็นreact-native-svgคอมโพเนนต์ด้วยhttps://svgr.now.sh/ (เลือกช่องทำเครื่องหมาย "React Native)

จะใช้ส่วนประกอบนั้นอย่างไร? คุณสามารถแบ่งปันรหัสได้หรือไม่?
Indranil Dutta

หากคุณไปที่ลิงก์นี้คุณจะเห็นตัวอย่างที่มีการนำเข้าsvgr.now.sh (เลือกช่องทำเครื่องหมาย "React Native) ใช้เป็นส่วนประกอบการตอบสนองปกติวางไว้แทน <Image src = {... } /> และควรใช้งานได้
Ihor Burlachenko

1
@IhorBurlachenko เมื่อฉันเหนื่อยวิธีการแก้ปัญหาของคุณผมมีข้อผิดพลาดนี้เกิดข้อผิดพลาด Uncaught: การละเมิดหมู่: ชนิดของธาตุไม่ถูกต้อง: คาดว่าสตริง (สำหรับในตัวส่วนประกอบ) หรือระดับ / ฟังก์ชั่น แต่มีวัตถุ คุณช่วยฉันที่นี่ได้ไหม
Mighty

2
ใครก็ตามที่มีปัญหาในการใช้แนวทางนี้โปรดตรวจสอบให้แน่ใจว่าคุณได้ติดตั้งreact-native-svgแพ็คเกจเวอร์ชันล่าสุดแล้ว อย่าลืมเรียกใช้คำสั่งนี้เพื่อเชื่อมโยงแพ็คเกจของคุณreact-native link react-native-svg
ด้วย

2
นี่เป็นกระบวนการที่ยาวนานในการใช้ไฟล์ SVG ดีกว่าใช้github.com/kristerkari/react-native-svg-transformerตามที่แนะนำไว้ด้านล่างstackoverflow.com/a/55604442/1854104
hefgi

10

ฉันโพสต์วิธีแก้ปัญหาอื่นที่นี่ซึ่งเป็นวิธีที่ดีที่สุดในการแทรกกราฟเวกเตอร์ (svg) ลงในแอปพลิเคชันเนทีฟตอบสนองวิธีนี้ใช้แบบอักษรเวกเตอร์ (จาก svg) แทนไฟล์ svg PS: ใช้งานได้ดีใน iOS และ Android และคุณยังสามารถเปลี่ยนสีและขนาดของไอคอนเวกเตอร์ของคุณได้

หากคุณต้องการแทรก svg ลงในแอปของคุณโดยตรงคุณสามารถลองใช้ไลบรารีของบุคคลที่สาม: react-native-svg ด้วยมากกว่า 3k ดาวใน github จึงเป็นแนวทางที่ดีที่สุดวิธีหนึ่ง

  • ติดตั้ง:
    • npm ฉันตอบสนองเนทีฟ -svg
    • npm ฉันตอบสนองพื้นเมือง svg-uri
  • เชื่อมโยงกับเนทีฟ:
    • ลิงก์ตอบสนองพื้นเมือง 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/…
Cassio Seffrin

2
ห้องสมุดนี้ช้าจัง มันรวมทุก svg ไว้ใน webview ของตัวเอง
JP_

1
tnx นี่เป็นวิธีแก้ปัญหาที่เร็วที่สุด แต่แทนที่จะใช้ svgXmlData = {testSvg} ฉันใช้ source = {testSvg} ทำงานได้อย่างมีเสน่ห์ tnx อีกครั้ง
Andris Laduzans

9

หลังจากลองใช้หลายวิธีและไลบรารีฉันตัดสินใจสร้างแบบอักษรใหม่ (ด้วยGlyphsหรือบทช่วยสอนนี้) และเพิ่มไฟล์ SVG ลงไปจากนั้นใช้คอมโพเนนต์ "ข้อความ" กับแบบอักษรที่กำหนดเอง

หวังว่านี่จะช่วยทุกคนที่มีปัญหาเดียวกันกับ SVG ใน react-native


ฉันคิดว่าคุณพูดถูกตระกูลแบบอักษรน่าจะเป็นวิธีที่ง่ายที่สุดในการรับ svgs ง่ายๆในการตอบสนองพื้นเมือง
โจลอยด์

บทแนะนำที่ดีในเรื่องนั้น: blog.bam.tech/developper-news/… . ต้องการแพ็คเกจVector Icons Node
Rafa

วิธีนี้ใช้ไม่ได้หากคุณต้องการนำเข้าไฟล์ย้อยหลายสี
Joe Aspara

ฉันได้ลองใช้วิธีแก้ปัญหากับ icomoon แล้วและไม่ได้ผลทั้งการสนับสนุนของพวกเขาไม่ทำงาน และ fontello กำลังแก้ไข svgs ของฉัน
Siraj Alam

6

ติดตั้งreact-native-svg-transformer

npm ฉันตอบสนอง -Native-svg-transformer --save-dev

ฉันใช้ SVG ดังต่อไปนี้และใช้งานได้ดี

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

ในการแสดงผล

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

เมื่อฉันนำเข้าไฟล์ svg HEARTSVG จากโฟลเดอร์รูปภาพมันแสดงข้อผิดพลาด และไม่มีข้อผิดพลาดในการนำเข้าไฟล์ png ข้อเสนอแนะใด ๆ ?
Rakesh

4

ผมมีปัญหาเดียวกัน. ฉันใช้วิธีนี้ที่พบ: ตอบสนองการแสดงผลพื้นเมือง SVG จากไฟล์

มันไม่สมบูรณ์แบบและฉันกำลังกลับมาในวันนี้เพราะมันทำงานได้แย่กว่าใน Android


จริงๆแล้วมันเป็นคำตอบที่สร้างสรรค์ แต่มันไม่ได้ช่วยให้เหมาะกับฉัน :) เพราะฉันจะใช้รายการไอคอน (10 ไอคอนขึ้นไป SVG) ดังนั้นถ้าฉันใช้สิ่งนี้ฉันเดาว่ามันอาจจะแย่มากสำหรับประสิทธิภาพ คุณคิดอย่างไร?
the_bluescreen

ฉันแสดงผล 10-15 svgs ในหนึ่งหน้า ไม่มีใครบ่นบน iOS ทุกคนบ่นบน Android บน iOS จะมีการหน่วงเวลา 0.1-0.3 วินาที (แฟลชแยกวินาทีเป็นสีขาวก่อนที่จะโหลด) ใน Android อาจเป็นเวลา 1 วินาทีและบางครั้งก็ไม่เคยโหลดเลย ในที่สุดผมตรวจสอบใน SVGs ของฉันแล้วเขียนบทซึ่งแปลงให้ PNGs ของว่าขนาดที่ถูกต้องโดยใช้svg2png แล้วใช้<Image>กับ PNG เหล่านั้น เนื่องจากสถานะปัจจุบันของ SVG ในการตอบสนองเนทีฟจึงไม่มี ETA สำหรับ SVG ที่ทำงานได้ดังนั้นนี่จึงเป็นทางออกที่ดีที่สุดของคุณหากคุณไม่สามารถทนต่อการแก้ไขได้
Sledge Hammer

3

ใช้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-urireact-native เวอร์ชัน 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"];
    }
  };

โซลูชันที่กล่าวถึงข้างต้นจะใช้งานได้ในแอปการผลิตด้วย✅


3

ฉันได้ลองใช้วิธีแก้ปัญหาข้างต้นและวิธีแก้ปัญหาอื่น ๆ นอกสแต็กทั้งหมดแล้วและไม่มีวิธีใดได้ผลสำหรับฉัน ในที่สุดหลังจากค้นคว้ามานานฉันก็พบทางออกหนึ่งสำหรับโครงการเอ็กซ์โปของฉัน

หากคุณต้องการใช้งานในงานแสดงสินค้าวิธีแก้ปัญหาหนึ่งอาจใช้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" />
  );
}

1
สิ่งนี้ก็ใช้ได้ดีสำหรับฉันเช่นกัน เราสามารถรับเส้นทางของไฟล์ svg ได้อย่างง่ายดายโดยเปิดบนเบราว์เซอร์ & ดูแหล่งที่มาของหน้าจากนั้นใช้เส้นทางโดยตรงและแทนที่แท็ก <path /> ด้วย react-native-svg <Path /> ขอบคุณมาก
Rakesh

1

คุณสามารถทำได้โดยใช้วิธีง่ายๆ

ก่อนอื่นคุณควรทำการติดตั้ง

  1. npm install -s react-native-svg
  2. ลิงก์ตอบสนองพื้นเมือง react-native-svg
  3. npm ติดตั้ง -s 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"]
    }
  };
})();

หลังจากนั้นคุณควรสร้างไฟล์ใหม่ในไดเรกทอรีรากของคุณด้วยชื่อ declarations.d.js ด้วยรหัสต่อไปนี้

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

สุดท้ายนี่คือ mathod นำเข้า

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

และนี่คือ jsx

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


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 ยังไม่รองรับภาพ SVG ในImageคอมโพเนนต์นั้นเป็นเรื่องตลก คุณไม่ควรติดตั้งไลบรารีเพิ่มเติมสำหรับงานง่ายๆเช่นนี้ ใช้https://svgtopng.com/


1
เป็นโครงการโอเพ่นซอร์ส - ฉันแน่ใจว่าพวกเขาจะพอใจกับคำขอดึงของคุณหากคุณมีทางออกที่ดีกว่าที่กล่าวไว้ข้างต้น ... :)
Herald Smit
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.