ReactJS - 内联SVG样式和Google字体

3
我之前在这里发过一篇帖子: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)。

具体说到自定义字体,我从各种资源中发现需要将字体编码为Data URI,并包含在行内:

导入:使用Google Fonts与SVG<object> dataURI: 将CSS样式包含在转换svg为png时

我尝试了以下方法,但均无效:

@font-face

 <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 for React)

 <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>

这段代码中,'fontFamily:...'引起了webpack错误,错误提示为出现了意外字符':',期望是一个闭合括号'}'。同时,文中还出现了@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>

编辑:

我看到了这个使用反引号的帖子:在 ReactJS 中嵌入 SVG 我尝试了这个方法,但仍然没有起作用(使用了驼峰和传统语法都试过了)。

<style>
    { `@fontFace { fontFamily: 'pacifico'; src: url(data:application/font-woff2;charset=utf-8;base64,....; } ` }
</style>

它不会抛出任何错误,但在绘制到画布时与之前没有任何区别。
1个回答

3

更新:我解决了问题

我使用了一个名为“computed-style-to-inline-style”的插件,它基本上会将CSS中的任何样式与您的SVG内联设置。这对于渲染和绘制图标非常有用(不必包含那些内联样式),但似乎也是导致我的<Rect>被清除以及<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>
    );

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接