ReactJS - 内联SVG样式和Google字体

时间:2017-01-11 23:08:46

标签: javascript css reactjs svg

我之前在这里发了帖子: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>

它不会抛出任何错误,但是当绘制到画布时它与之前没有什么不同

1 个答案:

答案 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>
    );