在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';
...
}