Incorporamento di SVG in ReactJS


127

È possibile incorporare il markup SVG in un componente ReactJS?

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

Risultati nell'errore:

Gli attributi dello spazio dei nomi non sono supportati. ReactJSX non è XML.

Qual è il modo più leggero per farlo. Usare qualcosa come React ART è eccessivo per quello che sto cercando di fare.


1
Puoi creare un jsbin? Potrebbe essere semplice come cambiare il tag SVG di apertura in solo <svg id="Layer_1">(o anche meglio, senza ID). Modifica: ecco un esempio: jsbin.com/nifemuwi/2/edit?js,output
Brigand

@FakeRainBrigand Grazie! È stato così semplice in questo caso. Guarda la risposta di Ben però. Buono a sapersi che puoi aggirare l'analisi jsx quando è necessario.
nicholas

Risposte:


178

Aggiornamento 27/05/2016

A partire da React v15, il supporto per SVG in React è (vicino a?) Pari al 100% con l'attuale supporto del browser per SVG ( sorgente ). Devi solo applicare alcune trasformazioni di sintassi per renderlo compatibile con JSX, come già devi fare per HTML ( classclassName, style="color: purple"style={{color: 'purple'}}). Per qualsiasi attributo spaziato dal nome (separato da due punti), ad esempio xlink:href, rimuovere :e scrivere in maiuscolo la seconda parte dell'attributo, ad es xlinkHref. Ecco un esempio di SVG con <defs>, <use>e gli stili 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 funzionante

Per ulteriori dettagli su supporto specifico, consultare l' elenco dei documenti degli attributi SVG supportati . Ed ecco il problema (ora chiuso) di GitHub che tracciava il supporto per gli attributi SVG spaziali.


Risposta precedente

Puoi eseguire un semplice incorporamento SVG senza doverlo utilizzare dangerouslySetInnerHTMLsemplicemente rimuovendo gli attributi dello spazio dei nomi. Ad esempio, funziona:

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

A quel punto puoi pensare di aggiungere oggetti di scena come fill, o qualsiasi altra cosa possa essere utile da configurare.


@ChinonsoChukwuogor Ottima domanda! Non lo so, non ho mai usato React Native. Ci hai provato?
Andrew Patton,

@AndrewPatton Più nomi di classi Css con il segno di spunta non funzionano: ' .class1, .class2{fill: #005baa;}' Come posso risolverlo?
HelloWorld

@HelloWorld Puoi darmi un esempio in cui non funziona? Ho appena aggiunto la mia demo originale da aggiungere classBe ha funzionato: codepen.io/acusti/pen/BVJzNg
Andrew Patton,

Grazie, a partire da questo sono riuscito a importare uno svg dal file come componente React senza alcun caricatore, ho appena rimosso `` `xmlns: osb =" openswatchbook.org/uri/2009/osb "` `` da il tag svg, lasciando solo gli xlmns. Si tratta dell'analisi dei tag apparentemente. Per ogni evenienza, ho seguito anche questi passaggi: blog.logrocket.com/how-to-use-svgs-in-react
Funder

56

Se hai solo una stringa svg statica che vuoi includere, puoi usare dangerouslySetInnerHTML:

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

e React includerà il markup direttamente senza elaborarlo affatto.


3
Sto controllando alcuni percorsi all'interno di SVG usando React, ma React non sembra supportare gli elementi del filtro. C'è un modo per supportare questo? Sembra pericolosamenteSetInnerHTML non funzionerà perché non riesco a inserire un intervallo all'interno di un SVG e non posso usarlo per impostare l'attributo del filtro sui percorsi. Suppongo che non ci sia un modo per creare gli elementi React come al solito, ma farli passare tutti gli attributi alla lettera agli elementi DOM?
Andy,

Dal 2019, sembra che tu possa usare pericolosamenteSetInnerHTML ma ancora non riesco a far funzionare il filtro ombra su Chrome usando pericolosamenteSetInnerHTML, ma funziona su Firefox.
Shnd,

31

Secondo uno sviluppatore di reazioni , non è necessario lo spazio dei nomi xmlns. Se hai bisogno dell'attributo xlink:hrefpuoi usare xlinkHref dalla reazione 0.14

Esempio

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

12

Se vuoi caricarlo da un file, puoi provare a usare React-inlinesvg : è piuttosto semplice e diretto.

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>
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.