Вбудовування 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">(а ще краще, без ідентифікатора). Edit: ось приклад: jsbin.com/nifemuwi/2/edit?js,output
розбійник

@FakeRainBrigand Дякую! Це було так просто в цьому випадку. Хоча подивись на відповідь Бена. Приємно знати, що ви можете обійти jsx розбору, коли потрібно.
ніколас

Відповіді:


178

Оновлення 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 не підтримує фільтруючі елементи. Чи є спосіб підтримати це? Схоже, небезпечноSetInnerHTML не буде працювати, тому що я не можу помістити проміжок всередині SVG і не можу використовувати його для встановлення атрибута фільтра на шляхах. Я не думаю, що існує спосіб створити елементи React як зазвичай, але чи повинні вони передати всі атрибути дословно елементам DOM?
Енді

Як і в 2019 році, здається, ви можете використовувати небезпечноSetInnerHTML, але все-таки я не міг змусити тіньовий фільтр працювати в Chrome за допомогою небезпечногоSetInnerHTML, але він працює на Firefox.
Шнд


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>
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.