JSX 中的 SVG - 如何转换 defs 标签
Posted
技术标签:
【中文标题】JSX 中的 SVG - 如何转换 defs 标签【英文标题】:SVG in JSX - how to convert defs tag 【发布时间】:2018-03-22 01:23:10 【问题描述】:我有一些 SVG 有一个 defs
属性,里面有一个 style
标签。
像这样:
<svg ...>
<defs>
<style>.cls-1,.cls-7fill:#b2488d;.cls-1,.cls-2,.cls-3,.cls-4,.cls-5,.cls-6stroke:#671f4d;</style>
</defs>
...
</svg>
我想在 React 中使用这些 SVG,所以我想将它们转换为有效的 JSX。我已经使用过svg2jsx 之类的工具,但它们会去掉defs
标记,因此不再存在任何样式属性。有没有办法通过在JSX中转换SVG来保留defs
和style
标签?还是在这种情况下不能使用 css 类?
【问题讨论】:
必须转换吗?你不能在你的html中使用<img src="/images/logo.svg" />
或者在你的css中使用background-image: url("/images/logo.svg");
吗?
@cyonder 内联 SVG 在大多数浏览器中得到更好的支持
我想使用 SVG 来操作属性。
你想如何操作它们?您想在 svg 标签元素中使用状态/道具吗?
@lumio 是的,这就是我想做的。
【参考方案1】:
您可以保留样式而无需任何转换。为此,使用 ` 和 ` 将样式标签内的所有 CSS 类包装起来。 现在你的 SVG 变成了这样
<svg ...>
<defs>
<style>`.cls-1,.cls-7fill:#b2488d;.cls-1,.cls-2,.cls-3,.cls-4,.cls-5,.cls-6stroke:#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" />
<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 />
<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。 :) 这并不能完全回答我的问题,但是我发现它是解决我的问题的好方法。以上是关于JSX 中的 SVG - 如何转换 defs 标签的主要内容,如果未能解决你的问题,请参考以下文章