Einbetten von SVG in ReactJS

127

Ist es möglich, SVG-Markup in eine ReactJS-Komponente einzubetten?

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

Ergebnisse im Fehler:

Namespace-Attribute werden nicht unterstützt. ReactJSX ist kein XML.

Was ist der leichteste Weg, dies zu tun. Die Verwendung von React ART ist für das, was ich versuche, ein Übermaß.

Nikolaus
quelle
1
Können Sie einen JSBIN erstellen? Es kann so einfach sein, wie das Öffnen Ihres SVG-Tags in "Nur" <svg id="Layer_1">(oder noch besser ohne ID) zu ändern . Bearbeiten: Hier ist ein Beispiel: jsbin.com/nifemuwi/2/edit?js,output
Brigand
@FakeRainBrigand Danke! So einfach war das in diesem Fall. Schau dir Bens Antwort an. Gut zu wissen, dass Sie das jsx-Parsing umgehen können, wenn Sie es brauchen.
Nicholas

Antworten:

178

Update 27.05.2016

Ab React v15 entspricht die Unterstützung für SVG in React (nahezu?) 100% der aktuellen Browserunterstützung für SVG ( Quelle ). Sie müssen nur einige Syntaxtransformationen anwenden, um JSX-kompatibel zu machen, wie Sie es bereits für HTML ( classclassName, style="color: purple"style={{color: 'purple'}}) tun müssen . xlink:hrefEntfernen Sie für jedes Namespace-Attribut (durch Doppelpunkte getrennt) z. B. das :und schreiben Sie den zweiten Teil des Attributs groß, z xlinkHref. Hier ist ein Beispiel eines svg mit <defs>, <use>und Inline - Styles:

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

Funktionierende Codepen-Demo

Weitere Informationen zur spezifischen Unterstützung finden Sie in der Liste der unterstützten SVG-Attribute in den Dokumenten . Und hier ist das (jetzt geschlossene) GitHub-Problem , bei dem die Unterstützung für SVG-Attribute mit Namespace verfolgt wurde.


Vorherige Antwort

Sie können eine einfache SVG-Einbettung durchführen, ohne sie verwenden zu müssen, dangerouslySetInnerHTMLindem Sie nur die Namespace-Attribute entfernen. Zum Beispiel funktioniert dies:

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

An diesem Punkt können Sie darüber nachdenken, Requisiten wie filloder was auch immer nützlich sein könnte, um es zu konfigurieren.

Andrew Patton
quelle
@ChinonsoChukwuogor Gute Frage! Ich weiß nicht, ich habe React Native noch nie benutzt. Hast du es versucht?
Andrew Patton
@AndrewPatton Mehrere CSS-Klassennamen mit dem Häkchen char funktionieren nicht: ' .class1, .class2{fill: #005baa;}' Wie kann ich das beheben?
HelloWorld
@HelloWorld Kannst du mir ein Beispiel geben, wo es nicht funktioniert? Ich habe gerade meine ursprüngliche Demo zum Hinzufügen gegabelt classBund es hat funktioniert: codepen.io/acusti/pen/BVJzNg
Andrew Patton
Danke, ausgehend davon habe ich es geschafft, ein SVG aus einer Datei als React-Komponente ohne Loader zu importieren. Ich habe gerade `` `xmlns: osb =" openswatchbook.org/uri/2009/osb "` `` aus entfernt das svg-tag, wobei nur die xlmns übrig bleiben. Anscheinend dreht sich alles um das Parsen von Tags. Für alle Fälle habe ich auch diese Schritte ausgeführt: blog.logrocket.com/how-to-use-svgs-in-react
Funder
56

Wenn Sie nur eine statische SVG-Zeichenfolge haben, die Sie einschließen möchten, können Sie Folgendes verwenden dangerouslySetInnerHTML:

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

und React wird das Markup direkt einschließen, ohne es überhaupt zu verarbeiten.

Sophie Alpert
quelle
3
Ich steuere einige Pfade in SVG mit React, aber React scheint die Filterelemente nicht zu unterstützen. Gibt es eine Möglichkeit, dies zu unterstützen? Scheint gefährlich zu sein. SetInnerHTML funktioniert nicht, weil ich keine Spanne in eine SVG einfügen kann und damit das Filterattribut für die Pfade nicht festlegen kann. Ich nehme nicht an, dass es eine Möglichkeit gibt, React-Elemente wie gewohnt zu erstellen, aber haben sie alle Attribute wörtlich an die DOM-Elemente übergeben?
Andy
Wie 2019 scheint es, dass Sie gefährlich SetInnerHTML verwenden können, aber ich konnte keinen Schattenfilter für Chrome verwenden, um mit gefährlich SetInnerHTML zu arbeiten, aber es funktioniert unter Firefox.
Shnd
31

Laut einem Reaktionsentwickler benötigen Sie den Namespace xmlns nicht. Wenn Sie das Attribut benötigen, können xlink:hrefSie xlinkHref aus Reaktion 0.14 verwenden

Beispiel

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

Wenn Sie es aus einer Datei laden möchten, können Sie versuchen, React-inlinesvg zu verwenden - das ist ziemlich einfach und unkompliziert.

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
quelle