Javascript 使用从SVG字体中提取的SVG.js+字形手动呈现SVG文本

Javascript 使用从SVG字体中提取的SVG.js+字形手动呈现SVG文本,javascript,html,svg,Javascript,Html,Svg,我正在从事一个项目,我必须在浏览器中动态创建设计资源。在过去的几个月里,我一直在使用canvas来完成这项工作,但现在有人问我是否可以直接从客户机创建基于向量的资产 在研究了HTML5 SVG之后,我似乎能够做到这一点,在玩了raphael.js和SVG.js之后,我决定更喜欢SVG.js。对我来说,更加轻量级和

我正在从事一个项目,我必须在浏览器中动态创建设计资源。在过去的几个月里,我一直在使用canvas来完成这项工作,但现在有人问我是否可以直接从客户机创建基于向量的资产

在研究了HTML5 SVG之后,我似乎能够做到这一点,在玩了raphael.js和SVG.js之后,我决定更喜欢SVG.js。对我来说,更加轻量级和 使用SVG的主要问题是,我必须将文本呈现到我的SVG中,并使文本向量基于最终资源并可用。不仅如此,我还需要能够完美地测量文本的边界区域到最近的像素。在这方面,我看到了两个问题:

仅仅使用标准的draw.text调用来创建元素是不好的,因为这意味着我必须将字体与资源捆绑在一起,由于许可的原因,这是不可能的

在高度方面,调用text.bbox获取文本元素的边界区域是不准确的。我相信它只是返回字体中最高/最低字符的高度,而不是实际使用的字符,就像getClientRect对标准html元素所做的那样

我看到了一个可以解决这些问题的解决方案,这就是我寻求建议的地方:

我相信我可以使用draw.path和从SVG字体提取的路径信息手动渲染glyph。这样,我的最终资源将有基于向量的字形,它不绑定到任何字体,希望在绘制路径后调用bbox比使用文本更准确


有人知道是否可以使用svg.js提取这些标志符号信息吗?或者我必须通过解析xml并从中提取路径信息来手动完成吗?还有人知道内核在这种情况下可能如何工作吗?或者更确切地说,如果不使用这种手动且复杂的方法,您是否知道解决上述问题1和2的其他方法?

我以前曾对此进行过半心半意的尝试,这确实是可能的,但并不简单。要从SVG字体XML中提取字体信息,您需要

document.querySelector("glyph[unicode=a]").getAttribute("d");
这将为您找到字母a的路径。但是,此路径位于与w3c不同的坐标系中:

与SVG中的标准图形不同,SVG中的初始坐标系 y轴朝下,参见初始坐标系, SVG字体的设计网格,以及初始坐标 用于图示符的系统,y轴朝上以保持一致性 具有许多流行字体格式的公认行业惯例

这意味着您必须将坐标从一个系统转换为另一个系统。这本身不应该太难,然后将其缩放到所需的大小

然后你必须在第一个字母之后画下一个字母,这是字形的horiz-adv-x属性,你还必须根据文本大小进行缩放。尽管SVG字体考虑了字距调整,但实际上没有支持SVG文本的浏览器引擎实现它,因此间距不会因字形对的不同而变化


根据您的具体要求,这个过程可能会从简单变成噩梦。如果范围逐渐扩大,您最终可以实现一个迷你文本呈现引擎。

我以前对此做过一次半心半意的尝试,这确实是可能的,但并不简单。要从SVG字体XML中提取字体信息,您需要

document.querySelector("glyph[unicode=a]").getAttribute("d");
这将为您找到字母a的路径。但是,此路径位于与w3c不同的坐标系中:

与SVG中的标准图形不同,SVG中的初始坐标系 y轴朝下,参见初始坐标系, SVG字体的设计网格,以及初始坐标 用于图示符的系统,y轴朝上以保持一致性 具有许多流行字体格式的公认行业惯例

这意味着您必须将坐标从一个系统转换为另一个系统。这本身不应该太难,然后将其缩放到所需的大小

然后你必须在第一个字母之后画下一个字母,这是字形的horiz-adv-x属性,你还必须根据文本大小进行缩放。尽管SVG字体考虑了字距调整,但实际上没有支持SVG文本的浏览器引擎实现它,因此间距不会因字形对的不同而变化

根据您的具体要求,这个过程可能会从简单变成噩梦。如果范围逐渐扩大,您最终可以实现一个迷你文本呈现引擎。

看看。js可用于解析Opentype和TrueType字体

使用opentype.js,可以获得一条路径,该路径可用于使用HTML5画布进行绘制:

var font = opentype.parseFont(arrayBuffer);
var path = font.getPath("Hello, World!", {x:0, y:150, fontSize:72});
path.draw(ctx);
正如在回答中所说,演示网站上有一个实例。

看一看。js可用于解析Opentype和TrueType字体

使用opentype.js,可以获得一条路径,该路径可用于使用HTML5画布进行绘制:

var font = opentype.parseFont(arrayBuffer);
var path = font.getPath("Hello, World!", {x:0, y:150, fontSize:72});
path.draw(ctx);

正如在回答中所说,演示网站上有一个实例。

我实际上认为我最终将不得不使用一个迷你文本渲染引擎,因为这似乎是我实现所需的唯一方法!我刚刚看了一个SVG,看到了您提到的属性:horiz-adv-x=375。你能不能让我更深入地了解一下,这是什么单位?它如何影响我绘制下一个图示符的位置?例如,假设我的字体大小为20,我需要如何缩放与此字体大小相关的属性?在SVG字体描述中,您应该使用单位/em=1000或其他值。这个单位表示每行文字之间的垂直间隔,我猜是零前导?因此,horiz-adv-x=375的字形会将下一个字符放置在线条高度的1/3左右。你说的“线条高度”是指字符的宽度吗。如果是这样的话,这是有意义的。根据W3C:在这个模型中,各种字体度量,如进阶值和基线位置,以及字形轮廓本身,都是以相对于一个抽象正方形的单位来表示的,该正方形的高度是相同字体大小的字体行之间的预期距离。该正方形称为em正方形,它是定义轮廓轮廓的设计网格。事实上,我认为我最终将不得不做一个迷你文本渲染引擎,因为这似乎是我实现我想要的唯一方法!我刚刚看了一个SVG,看到了您提到的属性:horiz-adv-x=375。你能不能让我更深入地了解一下,这是什么单位?它如何影响我绘制下一个图示符的位置?例如,假设我的字体大小为20,我需要如何缩放与此字体大小相关的属性?在SVG字体描述中,您应该使用单位/em=1000或其他值。这个单位表示每行文字之间的垂直间隔,我猜是零前导?因此,horiz-adv-x=375的字形会将下一个字符放置在线条高度的1/3左右。你说的“线条高度”是指字符的宽度吗。如果是这样的话,这是有意义的。根据W3C:在这个模型中,各种字体度量,如进阶值和基线位置,以及字形轮廓本身,都是以相对于一个抽象正方形的单位来表示的,该正方形的高度是相同字体大小的字体行之间的预期距离。该正方形称为em正方形,它是定义轮廓轮廓的设计网格。url需要更新url需要更新