JSX中的SVG - 如何转换defs标签

时间:2017-10-10 15:05:27

标签: css reactjs svg jsx

我有一些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来保留defs内置style标签?或者在这种情况下是不是可以使用css类?

2 个答案:

答案 0 :(得分:5)

如果您在Illustrater中创建了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>

答案 1 :(得分:3)

您可以保留样式而无需任何转换。为此,使用 {` 和 `} 将所有 CSS 类包装在 style 标签中。 现在你的 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>

这将毫无问题地呈现。