我之前在这里发了帖子:Converting SVG to PNG loses styling elements但我的问题更广泛 - 我认为我们确定了原因,但现在我遇到了实施解决方案的问题。
我认为发布有关特定React语法的新问题以向SVG元素提供内联自定义字体样式是有益的
这是我的render()函数:
renderIcon() {
return this.props.logoStyle.iconGraphic.path.map((path) => {
return (
<path id={path.id} style={{"fill":this.props.logoStyle.iconColor}} d={path.d} />
);
});
}
renderLogo() {
let style = this.props.logoStyle;
return (
<svg width="300" height="100" className={"logo"} xmlns="http://www.w3.org/2000/svg">
<svg xmlns="http://www.w3.org/2000/svg">
<rect
id="background"
x="0"
y="0"
width="300"
height="100"
style={{fill: style.backgroundColor}}
/>
</svg>
<svg
xmlns="http://www.w3.org/2000/svg"
width={style.iconSize}
height={style.iconSize}
viewBox="0 0 1000 1000"
x="10"
y="13"
id="svg4272">
<g>
{this.renderIcon()}
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg">
<text
style={{
fontSize:style.fontSize,
fontFamily: style.fontFamily,
fill: style.fontColor
}}
id="text"
x="90"
y="58"
fontSize={style.fontSize}
>{style.companyName}</text>
</svg>
</svg>
);
}
render() {
let style = this.props.logoStyle;
//console.log(style);
return (
<div className="logo-preview">
{this.renderLogo()}
<canvas id="canvas" width="900" height="300"></canvas>
<button className="btn btn-success" onClick={this.onDownload}>Download</button>
</div>
);
}
页面上的一切看起来都不错,但是当用户按下按钮然后将SVG绘制到#canvas并触发下载时,很明显它会丢失样式元素,因为它们并未真正被渲染排队。
图标(来自this.renderIcon())是唯一可以正确绘制的内容。
<rect>
被完全剥离(或至少失去填充),<text>
丢失了自定义字体(但正确维护了fontSize和fill)。
专门针对自定义字体,我从各种资源中发现我需要将字体编码为数据URI,并将其包括在内: 导入:Using Google Fonts with SVG <object> dataURI:How to Include CSS style when converting svg to png
我尝试了以下方法,但没有任何效果:
@字体面
<svg xmlns="http://www.w3.org/2000/svg">
<style>
@font-face { font-family: 'pacifico'; src: url(data:application/font-woff;charset-utf08;base64,d09GR...) format('woff'); font-weight: normal; font-style: normal; }
</style>
<text
style={{
fontSize:style.fontSize,
fontFamily: style.fontFamily,
fill: style.fontColor
}}
id="text"
x="90"
y="58"
fontSize={style.fontSize}
>{style.companyName}</text>
</svg>
@fontFace (反应的camelCase)
<svg xmlns="http://www.w3.org/2000/svg">
<style>
@fontFace { fontFamily: 'pacifico'; src: url(data:application/font-woff;charset-utf08;base64,d09GR...) format('woff'); fontWeight: normal; fontStyle: normal; }
</style>
<text
style={{
fontSize:style.fontSize,
fontFamily: style.fontFamily,
fill: style.fontColor
}}
id="text"
x="90"
y="58"
fontSize={style.fontSize}
>{style.companyName}</text>
</svg>
这个在&#39; fontFamily中抛出了一个webpack错误:...&#39;引用冒号&#39;:&#39;作为一个意想不到的角色,期待一个结束括号&#39;}&#39;
@import
<svg xmlns="http://www.w3.org/2000/svg">
<style>
@import url('https://fonts.googleapis.com/css?family=Pacifico');
</style>
<text
style={{
fontSize:style.fontSize,
fontFamily: style.fontFamily,
fill: style.fontColor
}}
id="text"
x="90"
y="58"
fontSize={style.fontSize}
>{style.companyName}</text>
</svg>
修改:
我遇到过使用反引号的帖子:Embedding SVG into ReactJS 并试过这个,但仍然无法工作(尝试使用camelCase和传统语法)
<style>
{ `@fontFace { fontFamily: 'pacifico'; src: url(data:application/font-woff2;charset=utf-8;base64,....; } ` }
</style>
它不会抛出任何错误,但是当绘制到画布时它与之前没有什么不同
答案 0 :(得分:1)
更新:我想通了
我使用了一个名为&#39; computed-style-to-inline-style&#39;的插件,它基本上设置了CSS与SVG内联的任何样式。这非常适合渲染和绘制图标(不必包括那些内联),但它似乎也是我的<Rect>
被消灭的罪魁祸首,字体不是&#39 ; t <Text>
以下是我用于SVG对象的更新样式:
return (
<svg width="300" height="100" className={"logo-"+id} xmlns="http://www.w3.org/2000/svg">
<svg xmlns="http://www.w3.org/2000/svg">
<style>
{ `.rect { fill: {style.backgroundColor} }`}
</style>
<rect
id="background"
className="rect"
x="0"
y="0"
width="300"
height="100"
rx={style.bgBorderRadius}
ry={style.bgBorderRadius}
style={{fill: style.backgroundColor}}
stroke="2" />
</svg>
<svg
xmlns="http://www.w3.org/2000/svg"
width={style.iconSize}
height={style.iconSize}
viewBox="0 0 1000 1000"
x="10"
y="13"
id="svg4272">
<g>
{this.renderIcon()}
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg">
<style>
{ `@font-face {
font-family: 'Pacifico';
src: url(data:application/font-woff2;charset=utf-8;base64,d09GMgA...) format('woff');
font-weight: normal;
font-style: normal;
} ` }
</style>
<text
style={{
fontSize:style.fontSize,
fontFamily: 'Pacifico',
fill: style.fontColor,
fontWeight: style.fontWeight,
fontStyle: style.fontStyle
}}
id="text"
x="90"
y="58"
stroke={style.fontStrokeColor}
strokeWidth={style.fontStrokeWidth}
textAlign="right"
>{style.companyName}</text>
</svg>
</svg>
);