Memasukkan SVG ke dalam ReactJS

127

Apakah mungkin untuk menanamkan markup SVG ke komponen ReactJS?

render: function() {
  return (
    <span>
      <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmln ...
    </span>
  );
}

Menghasilkan kesalahan:

Atribut Namespace tidak didukung. ReactJSX bukan XML.

Apa cara teringan untuk melakukan ini. Menggunakan sesuatu seperti React ART adalah cara yang terlalu berlebihan untuk apa yang saya coba lakukan.

nicholas
sumber
1
Bisakah Anda membuat jsbin? Mungkin sesederhana mengubah tag pembuka SVG Anda menjadi adil <svg id="Layer_1">(atau bahkan lebih baik, tanpa id). Sunting: inilah sebuah contoh: jsbin.com/nifemuwi/2/edit?js,output
Brigand
@FakeRainBrigand Terima kasih! Sederhana dalam hal ini. Lihatlah jawaban Ben. Senang mengetahui bahwa Anda dapat menyiasati JSX parsing ketika Anda perlu.
nicholas

Jawaban:

178

Perbarui 2016-05-27

Pada React v15, dukungan untuk SVG di React adalah (mendekati?) 100% paritas dengan dukungan browser saat ini untuk SVG ( sumber ). Anda hanya perlu menerapkan beberapa transformasi sintaksis agar JSX kompatibel, seperti yang harus Anda lakukan untuk HTML ( classclassName, style="color: purple"style={{color: 'purple'}}). Untuk atribut namespaced (dipisahkan usus besar), misalnya xlink:href, hapus :dan kapitalisasi bagian kedua dari atribut, misalnya xlinkHref. Berikut ini adalah contoh dari svg dengan <defs>, <use>, dan gaya inline:

function SvgWithXlink (props) {
    return (
        <svg
            width="100%"
            height="100%"
            xmlns="http://www.w3.org/2000/svg"
            xmlnsXlink="http://www.w3.org/1999/xlink"
        >
            <style>
                { `.classA { fill:${props.fill} }` }
            </style>
            <defs>
                <g id="Port">
                    <circle style={{fill:'inherit'}} r="10"/>
                </g>
            </defs>

            <text y="15">black</text>
            <use x="70" y="10" xlinkHref="#Port" />
            <text y="35">{ props.fill }</text>
            <use x="70" y="30" xlinkHref="#Port" className="classA"/>
            <text y="55">blue</text>
            <use x="0" y="50" xlinkHref="#Port" style={{fill:'blue'}}/>
        </svg>
    );
}

Demo codepen bekerja

Untuk detail lebih lanjut tentang dukungan spesifik, periksa daftar dokumen tentang atribut SVG yang didukung . Dan inilah masalah GitHub (sekarang ditutup) yang melacak dukungan untuk atribut SVG namespaced.


Jawaban sebelumnya

Anda dapat melakukan embed SVG sederhana tanpa harus menggunakan dangerouslySetInnerHTMLhanya dengan menghapus atribut namespace. Misalnya, ini berfungsi:

        render: function() {
            return (
                <svg viewBox="0 0 120 120">
                    <circle cx="60" cy="60" r="50"/>
                </svg>
            );
        }

Pada titik mana Anda dapat berpikir tentang menambahkan alat peraga seperti fill, atau apa pun yang mungkin berguna untuk dikonfigurasi.

Andrew Patton
sumber
@ChinonsoChukwuogor Pertanyaan bagus! Saya tidak tahu, saya tidak pernah menggunakan React Native. Apakah Anda mencobanya?
Andrew Patton
@AndrewPatton Beberapa nama Kelas Css dengan tanda centang tidak berfungsi: ' .class1, .class2{fill: #005baa;}' Bagaimana saya bisa memperbaikinya?
HelloWorld
@ Halo Dunia Bisakah Anda memberi saya contoh di mana itu tidak berhasil? Saya baru saja memotong demo asli saya untuk ditambahkan classBdan berhasil: codepen.io/acusti/pen/BVJzNg
Andrew Patton
Terima kasih, mulai dari ini saya sudah berhasil mengimpor svg dari file sebagai komponen Bereaksi tanpa pemuat apa pun, saya baru saja menghapus `` `xmlns: osb =" openswatchbook.org/uri/2009/osb "` `` dari tag svg, hanya menyisakan xlmns. Tampaknya ini semua tentang penguraian tag. Untuk berjaga-jaga, saya telah mengikuti langkah-langkah ini juga: blog.logrocket.com/how-to-use-svgs-in-react
Funder
56

Jika Anda hanya memiliki string svg statis yang ingin Anda sertakan, Anda dapat menggunakan dangerouslySetInnerHTML:

render: function() {
    return <span dangerouslySetInnerHTML={{__html: "<svg>...</svg>"}} />;
}

dan Bereaksi akan menyertakan markup secara langsung tanpa memproses sama sekali.

Sophie Alpert
sumber
3
Saya mengendalikan beberapa jalur di dalam SVG menggunakan Bereaksi, tetapi Bereaksi tampaknya tidak mendukung elemen filter. Apakah ada cara untuk mendukung ini? Sepertinya hazardSetInnerHTML tidak akan berfungsi karena saya tidak bisa meletakkan rentang di dalam SVG dan saya tidak bisa menggunakannya untuk mengatur atribut filter di jalur. Saya tidak mengira ada cara untuk membuat elemen Bereaksi seperti biasa tetapi apakah mereka meneruskan semua atribut kata demi kata ke elemen DOM?
Andy
Seperti tahun 2019, tampaknya Anda dapat menggunakan hazardouslySetInnerHTML tapi tetap saja saya tidak bisa membuat shadow filter untuk bekerja di Chrome menggunakan hazardouslySetInnerHTML, tapi itu bekerja di Firefox.
Shnd
31

Menurut pengembang reaksi , Anda tidak perlu namespace xmlns. Jika Anda memerlukan atribut, xlink:hrefAnda dapat menggunakan xlinkHref dari reaksi 0.14

Contoh

Icon = (props) => {
  return <svg className="icon">
    <use xlinkHref={ '#' + props.name }></use>
  </svg>;
}
lastid
sumber
12

Jika Anda ingin memuatnya dari file, Anda dapat mencoba menggunakan React-inlinesvg - itu cukup sederhana dan mudah.

import SVG from 'react-inlinesvg';

<SVG
  src="/path/to/myfile.svg"
  preloader={<Loader />}
  onLoad={(src) => {
    myOnLoadHandler(src);
  }}
>
  Here's some optional content for browsers that don't support XHR or inline
  SVGs. You can use other React components here too. Here, I'll show you.
  <img src="/path/to/myfile.png" />
</SVG>
Youkko
sumber