将SVG转换为PNG会丢失样式元素

时间:2017-01-10 20:48:48

标签: javascript reactjs svg

在ReactJS中,我有一个允许用户对SVG块进行自定义的界面。 SVG中有三个组件:矩形(用于背景),文本和SVG路径图像。

SVG是这样渲染的,其中道具来自父组件的状态:

renderLogo() {
    let style = this.props.logoStyle;

    return (
        <svg width="300" height="100" className={"logo"} xmlns="http://www.w3.org/2000/svg">

            <g>
                <rect id="background" x="0" y="0" width="300" height="100" rx={style.bgBorderRadius} ry={style.bgBorderRadius} 
                fill={style.backgroundColor} stroke="2" />
            </g>

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

        <g>             
            <text 
                x="90" 
                y="58" 
                fontSize={style.fontSize}
                fontFamily={style.fontFamily}
                fontWeight={style.fontWeight}
                stroke={style.fontStrokeColor}
                strokeWidth={style.fontStrokeWidth}
                fill={style.fontColor}
                textAlign="right"
                >{style.companyName}</text>
          </g>          
        </svg>
    );
}

render() {
    let style = this.props.logoStyle;
    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>
    );
}

按钮触发函数onDownload()然后尝试绘制到#canvas,然后启动PNG下载

onDownload() {

    var svg = document.querySelector('svg.logo');

// This function is from here that I hoped would help with the issue: https://github.com/lukehorvat/computed-style-to-inline-style 
    var computedToInline = require('computed-style-to-inline-style');
    computedToInline(svg, true);


    var canvas = document.querySelector('canvas');

     var ctx = canvas.getContext('2d');
     var data = (new XMLSerializer()).serializeToString(svg);

    var DOMURL = window.URL || window.webkitURL || window;

     var img = new Image();
     var svgBlob = new Blob([data], {type: 'image/svg+xml;charset=utf-8'});
     var url = DOMURL.createObjectURL(svgBlob);

      img.onload = () => {
        // clip and scale up
        ctx.drawImage(img, 0, 0, 300, 100, 0, 0, 900, 300);
        DOMURL.revokeObjectURL(url);

        var imgURI = canvas
            .toDataURL('image/png')
            .replace('image/png', 'image/octet-stream');

          this.triggerDownload(imgURI);

      };

      img.src = url;
}

triggerDownload(imgURI) {
    console.log("triggerDownload");
    var evt = new MouseEvent('click', {
        view: window,
        bubbles: false,
        cancelable: true
    });


    var a = document.createElement('a');
    a.setAttribute('download', 'imageFile.png');
    a.setAttribute('href', imgURI);
    a.setAttribute('target','_blank');

    a.dispatchEvent(evt);
}

问题:

将其绘制到画布时,图标正确呈现,但背景(SVG组件)被删除,属性(例如font-family)默认为Helvetica Neue而不是选定的字体/属性。这进入下载文件。

编辑:

如前所述,其中一个问题是字体,这些字体确实来自Google。从评论中提供的链接,似乎我需要通过数据URI内联引用这些。我使用FontSquirrel.com对它们进行了编码,但我不确定如何在React中的SVG内联中引用它们:

@font-face {
font-family: 'pacificoregular';
src: url(data:application/font-woff2;charset=utf-8;base64,d09GMgA...),
     url(data:application/font-woff;charset=utf-8;base64,d09Grg...) format('woff');
font-weight: normal;
font-style: normal;
}

我尝试将其插入到<defs><style>...</style></defs>中的元素中,但它出错了。我尝试过像这样转换为React语法,但它也失败了:

<style>
@fontFace {
fontFamily: 'pacificoregular';
src: url(data:application/font-woff2;charset=utf-8;base64,d09GMgA...),
     url(data:application/font-woff;charset=utf-8;base64,d09Grg...) format('woff');
fontWeight: normal;
fontStyle: normal;
}
</style>

如果我不能使用@ font-face,如何将内联字体引用到SVG?或者实际上是否有正确的方法在这里使用@ font-face?

编辑2:

删除了<def>代码,并使用了@fontFace{}语法:

尝试此语法时出错我收到一个语法错误,抱怨&#34;:&#34;之后&#39; fontFamily&#39;在:

@fontFace {
fontFamily: 'pacificoregular';
...
}

0 个答案:

没有答案