【问题标题】:SVG in JSX - how to convert defs tagJSX 中的 SVG - 如何转换 defs 标签
【发布时间】:2018-03-22 01:23:10
【问题描述】:

我有一些 SVG 有一个 defs 属性,里面有一个 style 标签。 像这样:

<svg ...>
  <defs>
    <style>.cls-1,.cls-7{fill:#b2488d;}.cls-1,.cls-2,.cls-3,.cls-4,.cls-5,.cls-6{stroke:#671f4d;}</style>
  </defs>
  ...
</svg>

我想在 React 中使用这些 SVG,所以我想将它们转换为有效的 JSX。我已经使用过svg2jsx 之类的工具,但它们会去掉defs 标记,因此不再存在任何样式属性。有没有办法通过在JSX中转换SVG来保留defsstyle标签?还是在这种情况下不能使用 css 类?

【问题讨论】:

  • 必须转换吗?你不能在你的html中使用&lt;img src="/images/logo.svg" /&gt;或者在你的css中使用background-image: url("/images/logo.svg");吗?
  • @cyonder 内联 SVG 在大多数浏览器中得到更好的支持
  • 我想使用 SVG 来操作属性。
  • 你想如何操作它们?您想在 svg 标签元素中使用状态/道具吗?
  • @lumio 是的,这就是我想做的。

标签: css reactjs svg jsx


【解决方案1】:

您可以保留样式而无需任何转换。为此,使用 {` 和 `} 将样式标签内的所有 CSS 类包装起来。 现在你的 SVG 变成了这样

<svg ...>
  <defs>
    <style>{`.cls-1,.cls-7{fill:#b2488d;}.cls-1,.cls-2,.cls-3,.cls-4,.cls-5,.cls-6{stroke:#671f4d;}`}</style>
  </defs>
  ...
</svg>

这将毫无问题地呈现。

【讨论】:

    【解决方案2】:

    如果您在 Illustter 中创建了 SVG,请将其保存,并将 CSS 属性 设置为 Presentation Attributes。这样一来,您就不会得到一个 CSS 类,并且可以直接更改所有属性。

    我导出了一个看起来像这样的 SVG:

    <?xml version="1.0" encoding="utf-8"?>
    <!-- Generator: Adobe Illustrator 21.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
    <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
         viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
    <g>
        <rect x="15.5" y="15.5" fill="#FFFFFF" width="44" height="44"/>
        <path d="M59,16v43H16V16H59 M60,15H15v45h45V15L60,15z"/>
    </g>
    <g>
        <path fill="#FFFFFF" d="M60.5,81.5c-12.1,0-22-9.9-22-22s9.9-22,22-22s22,9.9,22,22S72.6,81.5,60.5,81.5z"/>
        <path d="M60.5,38C72.4,38,82,47.6,82,59.5S72.4,81,60.5,81S39,71.4,39,59.5S48.6,38,60.5,38 M60.5,37C48.1,37,38,47.1,38,59.5
            S48.1,82,60.5,82S83,71.9,83,59.5S72.9,37,60.5,37L60.5,37z"/>
    </g>
    </svg>
    

    然后我去掉了所有不需要的标记,只在我的组件中使用它:

    const Image = ( props ) => {
      const {
        hideSquare,
        hideCircle,
      } = props;
      
      const colorSquare = props.colorSquare || '#fff';
      const colorCircle = props.colorCircle || '#fff';
      
      return (
        <svg x="0px" y="0px" viewBox="0 0 100 100">
          { hideSquare ? null : (
            <g>
              <rect x="15.5" y="15.5" fill={ colorSquare } width="44" height="44"/>
              <path d="M59,16v43H16V16H59 M60,15H15v45h45V15L60,15z"/>
            </g>
          ) }
          { hideCircle ? null : (
            <g>
              <path fill={ colorCircle } d="M60.5,81.5c-12.1,0-22-9.9-22-22s9.9-22,22-22s22,9.9,22,22S72.6,81.5,60.5,81.5z"/>
              <path d="M60.5,38C72.4,38,82,47.6,82,59.5S72.4,81,60.5,81S39,71.4,39,59.5S48.6,38,60.5,38 M60.5,37C48.1,37,38,47.1,38,59.5
                S48.1,82,60.5,82S83,71.9,83,59.5S72.9,37,60.5,37L60.5,37z"/>
            </g>
          ) }
        </svg>
      );
    };
    
    class Wrapper extends React.Component {
      constructor( props ) {
        super( props );
        
        // Set default state
        this.state = {
          selectedColor: 'lightgreen',
          hideSquare: false,
          hideCircle: false,
        };
      }
      
      // onInput callback
      changeColor = ( e ) => {
        this.setState( { selectedColor: e.target.value } );
      }
      
      changeVisibility = ( e ) => {
        const { name, checked } = e.target;
        this.setState( { [ name ]: checked } );
      }
      
      render() {
        return (
          <div>
            <select onInput={ this.changeColor }>
              <option>lightgreen</option>
              <option>pink</option>
              <option>red</option>
            </select><br />
            <label><input type="checkbox" name="hideSquare" onChange={ this.changeVisibility } /> hideSquare</label>
            <label><input type="checkbox" name="hideCircle" onChange={ this.changeVisibility } /> hideCircle</label><br />
            <Image
              hideSquare={ this.state.hideSquare }
              hideCircle={ this.state.hideCircle }
              colorSquare={ this.state.selectedColor }
              colorCircle={ this.state.selectedColor }
            />
          </div>
        );
      }
    }
    
    ReactDOM.render( <Wrapper />, document.getElementById( 'app' ) );
    svg {
      width: 200px;
      height: 200px;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
    <div id="app"></div>

    【讨论】:

    • 后者是否允许我使用 React 状态值更改属性值?如,字符串插值会起作用吗?
    • 我更新了我的答案。 tl;dr:您需要在不生成 CSS 样式的情况下导出 SVG。 :)
    • 这并不能完全回答我的问题,但是我发现它是解决我的问题的好方法。
    猜你喜欢
    • 1970-01-01
    • 2023-03-23
    • 2014-05-31
    • 1970-01-01
    • 1970-01-01
    • 2012-05-12
    • 2016-10-05
    • 2018-07-06
    • 2020-04-20
    相关资源
    最近更新 更多