使用Blob将使用Google字体的SVG转换为Canvas



我在一个使用谷歌字体的页面上显示了一个SVG。

SVG上的<text>节点很好地继承了Google字体。

现在,我正在尝试使用Blob转换SVG。

这是有效的,除了<text>是使用安装在浏览器机器上的回退"Verdana"而不是动态加载的谷歌字体"Pacifico"渲染的。

window.onload = function() {
var width = 400;
var height = 100;
var DOMURL = self.URL || self.webkitURL || self;
var data = new XMLSerializer().serializeToString(document.getElementById("test"));
var svg = new Blob([data], { type: "image/svg+xml" });
var url = DOMURL.createObjectURL(svg);
var canvas = document.getElementById("result");
canvas.width = width;
canvas.height = height;
var ctx = canvas.getContext("2d");
var img = new Image(width, height);
img.onload = function() {
ctx.drawImage(img, 0, 0);
DOMURL.revokeObjectURL(url);
}
img.src = url;
}
@import url('https://fonts.googleapis.com/css?family=Pacifico');
body {
font-family: Pacifico, Verdana;
font-size: 15px;
}
body * {
font-family: Pacifico, Verdana;
}
#test, #result {
border: 1px solid #eee;
}
h4 {
margin: 2em 0 1em 0;
}
<h4>Source SVG</h4>
<svg id="test" width="400px" height="100px" style="font-family: 'Pacifico', 'Verdana'; font-size: 15px;" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g xmlns="http://www.w3.org/2000/svg">
<rect fill="#67b7dc" transform="translate(-0.5,-0.5)" width="80" height="100" />
<rect fill="#6794dc" transform="translate(80,0)" transform="translate(-0.5,-0.5)" width="80" height="100" />
<rect fill="#6771dc" transform="translate(160,0)" transform="translate(-0.5,-0.5)" width="80" height="100" />
<rect fill="#8067dc" transform="translate(240,0)" transform="translate(-0.5,-0.5)" width="80" height="100" />
<rect fill="#a367dc" transform="translate(320,0)" transform="translate(-0.5,-0.5)" width="80" height="100" />
<text fill="#fff" transform="translate(20,20)" font-size="25" dy="20">
Some text using font</tspan>
</text>
</g>
</svg>

<h4>Result canvas</h4>
<canvas id="result" />

到目前为止,我还没能找到一种让画布文本使用自定义字体的方法,如果能提供任何帮助,我将不胜感激。

附言:为了记录在案,我知道存在第三方libs,比如fabric和canvg。他们能够在不丢失自定义字体的情况下将SVG转换为Canvas。然而,为了保持轻松,我试图不使用任何第三方libs。

p.p.S.将Google字体的@import包含到SVG的<defs><style>部分中并没有帮助,即使我们明确定义了@font-face。坦率地说,这不是一个选择,因为我还不知道库将使用什么字体。

p.p.p.S推迟出口没有帮助,所以这可能也不是时间问题。

你可能把所有的精力都集中在画布上,但问题已经从你的图像开始了。。。

这是您的代码,但只是一个非常简单的示例

<style>
@import url('https://fonts.googleapis.com/css?family=Pacifico');
body * { margin: 0; }
</style>
<h4>Source</h4>
<svg id="test" width="300px" height="30px" style="font-family: 'Pacifico', 'Verdana'; font-size: 15px;" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g xmlns="http://www.w3.org/2000/svg">
<rect fill="#67b7dc" transform="translate(-0.5,-0.5)" width="300" height="50" />
<text fill="#fff"  font-size="25" dy="20"> <tspan>Some text using font</tspan> </text>
</g>
</svg>
<h4>Image</h4>
<img id="image" />
<script>
window.onload = function() {
var DOMURL = self.URL || self.webkitURL || self;
var data = new XMLSerializer().serializeToString(document.getElementById("test"));
var svg = new Blob([data], { type: "image/svg+xml" });
var url = DOMURL.createObjectURL(svg);
var img = document.getElementById("image");
img.src = url;
}
</script>

关于SVG字体的这个问题有很多争论,这里有一篇很好的文章:

https://github.com/JChemPaint/jchempaint/wiki/The-svg-font-problem-and-its-solution

最新更新