3

I previously made a post here: Converting SVG to PNG loses styling elements but my question was more broad - I think we identified the cause, but now I'm having issues implementing a solution.

I thought it would be beneficial to post a new question regarding specific React syntax to provide an inline custom font style to an SVG element

Here are my render() functions:

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>
    );
}

Everything looks good on the page, but when the user presses a button which then draws the SVG to the #canvas and triggers a download, it's clear that it loses styling elements, as they are not truly being rendered inline.

The icon (from this.renderIcon()) is the only thing that gets drawn correctly.

The <rect> gets stripped entirely (or at least loses its fill), and the <text> loses it's custom fonts (but correctly maintains fontSize and fill).

Speaking specifically to the custom fonts, I have found from various resources that I need to encode the font to data URI, and include that in line: Import: Using Google Fonts with SVG <object> dataURI: How to Include CSS style when converting svg to png

I've tried the following, but nothing has worked:

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

This one throws a webpack error at 'fontFamily: ...' citing the colon ':' as an unexpected character, expecting a closing bracket '}'

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

EDIT:

I came across this thread that used backticks: Embedding SVG into ReactJS And tried this, but still did not work (tried with both camelCase and traditional syntax)

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

It does not throw any errors but when drawn to canvas it is no different than before

Community
  • 1
  • 1
trm313
  • 81
  • 1
  • 9

1 Answers1

3

UPDATE: I figured it out

I had used a plugin called 'computed-style-to-inline-style', which basically sets any styles from CSS inline with your SVG. This worked great for rendering and drawing the icon (didn't have to include those inline), but it seems to have also been the culprit of why my <Rect> was being wiped out, and the fonts weren't taking within <Text>

Here is the updated styling that I used for the SVG object:

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>
    );
trm313
  • 81
  • 1
  • 9