Встраивание SVG в ReactJS

127

Можно ли встроить разметку SVG в компонент ReactJS?

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

Приводит к ошибке:

Атрибуты пространства имен не поддерживаются. ReactJSX - это не XML.

Какой самый легкий способ сделать это. Использование чего-то вроде React ART является излишним для того, что я пытаюсь сделать.

Николай
источник
1
Можете ли вы создать jsbin? Это может быть так же просто, как изменить открывающий тег SVG на просто <svg id="Layer_1">(или даже лучше без идентификатора). Изменить: вот пример: jsbin.com/nifemuwi/2/edit?js,output
Brigand
@FakeRainBrigand Спасибо! В данном случае все было так просто. Но посмотрите на ответ Бена. Приятно знать, что вы можете обойти парсинг jsx, когда вам нужно.
Николай

Ответы:

179

Обновление 2016-05-27

Начиная с React v15, поддержка SVG в React является (близкой к?) 100% паритетом с текущей поддержкой SVG в браузере ( источник ). Вам просто нужно применить некоторые синтаксические преобразования, чтобы сделать его JSX-совместимым, как вы уже сделали для HTML ( classclassName, style="color: purple"style={{color: 'purple'}}). Для любого атрибута с пространством имен (разделенных двоеточиями), например xlink:href, удалите :и используйте вторую часть атрибута с заглавной буквы, например xlinkHref. Вот пример СВГ с <defs>, <use>и встроенных стилей:

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

Демо-версия рабочего кода

Дополнительные сведения о конкретной поддержке см. В списке поддерживаемых атрибутов SVG в документации . И вот (теперь закрытая) проблема GitHub, которая отслеживала поддержку атрибутов SVG с пространством имен.


Предыдущий ответ

Вы можете выполнить простую вставку SVG без необходимости dangerouslySetInnerHTML, просто удалив атрибуты пространства имен. Например, это работает:

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

В этот момент вы можете подумать о добавлении таких свойств fillили о том, что еще может быть полезно настроить.

Эндрю Паттон
источник
@ChinonsoChukwuogor Отличный вопрос! Не знаю, я никогда не использовал React Native. Вы попробовали?
Эндрю Паттон
@AndrewPatton Несколько имен классов Css с символом галочки не работают: .class1, .class2{fill: #005baa;}«Как я могу это исправить?
HelloWorld
@HelloWorld Можете привести мне пример, когда это не работает? Я просто раздвоил свою оригинальную демонстрацию, чтобы добавить, classBи она сработала: codepen.io/acusti/pen/BVJzNg
Эндрю Паттон
Спасибо, начиная с этого мне удалось импортировать svg из файла как компонент React без загрузчика, я только что удалил `` xmlns: osb = " openswatchbook.org/uri/2009/osb " `` из тег svg, оставив только xlmns. Очевидно, все дело в разборе тегов. На всякий случай, я следовал эти шаги , а также: blog.logrocket.com/how-to-use-svgs-in-react
финансирующей
56

Если у вас есть просто статическая строка svg, которую вы хотите включить, вы можете использовать dangerouslySetInnerHTML:

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

и React будет включать разметку напрямую, не обрабатывая ее вообще.

Софи Альперт
источник
3
Я контролирую некоторые пути внутри SVG с помощью React, но React, похоже, не поддерживает элементы фильтра. Есть ли способ поддержать это? Похоже, что dangerouslySetInnerHTML не будет работать, потому что я не могу поместить диапазон внутри SVG и не могу использовать его для установки атрибута фильтра на пути. Я не думаю, что есть способ создавать элементы React как обычно, но чтобы они передавали все атрибуты дословно элементам DOM?
Энди
В 2019 году кажется, что вы можете использовать опасноSetInnerHTML, но все же я не мог заставить теневой фильтр работать в Chrome с помощью dangerousSetInnerHTML, но он работает в Firefox.
Shnd
31

По словам разработчика реакции , вам не нужно пространство имен xmlns. Если вам нужен атрибут, xlink:hrefвы можете использовать xlinkHref из реакции 0.14

пример

Icon = (props) => {
  return <svg className="icon">
    <use xlinkHref={ '#' + props.name }></use>
  </svg>;
}
lastid
источник
12

Если вы хотите загрузить его из файла, вы можете попробовать использовать React-inlinesvg - это довольно просто и понятно .

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
источник