在当前HTML页面中嵌入SVG字体并使用@font-face的方法

7

我有一个独立的HTML文档需要分发,没有任何外部依赖。我在此文档中使用了一种非标准字体,只有一些用户已安装。

对于那些未安装该字体的用户,我在<body>顶部嵌入了一个包含字体副本的SVG文档。(这个例子中我使用了一个单字符字体,真实的文档则使用了完整的字体。)

<svg style="display: none;"><defs>
  <font id="MyFontElement">
    <font-face font-family="MyFont" />
    <glyph unicode="A" horiz-adv-x="950" d="M0,0L0,100L100,100L100,200L0,200L0,300L100,300L100,400L200,400L200,500L300,500L300,600L400,600L600,600L600,500L700,500L700,400L800,400L800,300L900,300L900,200L800,200L800,100L900,100L900,0L600,0L600,100L700,100L700,200L800,200L800,300L100,300L100,200L200,200L200,100L300,100L300,0L0,0M300,400L600,400L600,500L300,500L300,400Z" />    
  </font>
</defs></svg>

SVG字体看起来比普通字体不太好看,因此我只想在本地未安装字体时使用SVG字体。如果字体是在外部SVG文档中定义的,我可以按低于本地安装字体的优先级使用它,如下所示:(参见演示)

<style>
  @font-face {
    font-family: "My Font";
    src: local("My Font"), url("fonts.svg#MyFontElement") format("svg");
  }
</style>
<p style="font: 3em 'My Font';">
    Alphabet
</p>

screenshot

很遗憾,当前文档中没有任何明显的变化可以适用于字体: (样例)

  src: local("My Font"),
       url("./#MyFontElement") format("svg"),
       url("./#MyFontElement"),
       url("#MyFontElement") format("svg"),
       url("#MyFontElement");

即使没有@font-face声明,字体已经作为<font-face />中指定的font-family在文档中可用,其名称为MyFont。然而,这将比名为MyFont的本地字体具有更高的优先级,因此不是解决方案。
我希望能够将其称为local("MyFont")...(fiddle
  src: local("My Font"), /* local */
       local("MyFont"); /* embedded */

...但这也行不通。

我可以给嵌入式字体取一个不同的名称并使用较低的优先级style="font-family: LocalFont, EmbeddedFont",但我允许用户将代码片段从本地文件导入到文档中,并且这些本地文件将仅通过标准名称引用字体。虽然当它们被导入时可以重写这些引用,但我不喜欢那个解决方案。

如何在@font-face声明中引用当前文档中嵌入的SVG字体?


读者应该注意,Google Chrome已经移除了对SVG字体的支持,并且Mozilla Firefox从未实现过。然而,苹果似乎仍在Safari中维护它。 - Jeremy
显然,Firefox目前支持嵌入在OpenType文件中的基于SVG的字形!哎呀... - Jeremy
2个回答

5

将字体转换为数据URI并嵌入CSS声明中:(示例代码)

<style>
@font-face {
  font-family: "My Font";
  src: url("data:application/octet-stream;base64,PD94bWwgdmVyc2lvbj0iMS4wIj8+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCIgPgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+CiAgPGZvbnQgaWQ9Ik15Rm9udEVsZW1lbnQiPgogICAgPGZvbnQtZmFjZSBmb250LWZhbWlseT0iTXlGb250IiAvPgogICAgPGdseXBoIHVuaWNvZGU9IkEiIGhvcml6LWFkdi14PSI5NTAiIGQ9Ik0wLDBMMCwxMDBMMTAwLDEwMEwxMDAsMjAwTDAsMjAwTDAsMzAwTDEwMCwzMDBMMTAwLDQwMEwyMDAsNDAwTDIwMCw1MDBMMzAwLDUwMEwzMDAsNjAwTDQwMCw2MDBMNjAwLDYwMEw2MDAsNTAwTDcwMCw1MDBMNzAwLDQwMEw4MDAsNDAwTDgwMCwzMDBMOTAwLDMwMEw5MDAsMjAwTDgwMCwyMDBMODAwLDEwMEw5MDAsMTAwTDkwMCwwTDYwMCwwTDYwMCwxMDBMNzAwLDEwMEw3MDAsMjAwTDgwMCwyMDBMODAwLDMwMEwxMDAsMzAwTDEwMCwyMDBMMjAwLDIwMEwyMDAsMTAwTDMwMCwxMDBMMzAwLDBMMCwwTTMwMCw0MDBMNjAwLDQwMEw2MDAsNTAwTDMwMCw1MDBMMzAwLDQwMFoiIC8+ICAgIAogIDwvZm9udD4KPC9kZWZzPjwvc3ZnPgo=") format("svg");
}
</style>
<p style="font: 3em 'My Font';">
    Alphabet
</p>

有一个注意事项:您不能像这样使用ID指定符(#MyFont)与数据URI一起使用。因此,您只能在编码文件中拥有单个字体,而不是有多个并单独引用它们。(虽然您也不想这样做;为每种字体在声明中复制多个嵌入字体的数据将浪费大量空间。)


好主意,谢谢,这个很有效!我编辑了你的帖子,加入了一个我注意到的例子和警告。但是,如果确实有一种解决方案可以允许我在普通嵌入式SVG文档中引用字体,我还不会接受这个答案。 - Jeremy
你可以声明另一个 font-face 块来使用其他字体,而不是使用片段。 - Andy Davies
是的,那就是我要做的。使用碎片是一个糟糕的决定,但如果它能够工作,我可能会在感到非常懒惰的时候这样做。我想警告其他懒惰的读者,这不起作用;对我来说并不明显。 - Jeremy
如果是svgfont,就不应该使用“application/octet-stream”,而应该使用“image/svg+xml”。据我所知,您可以使用ID指定符号,至少我很确定在上次尝试时在Opera中可以使用。并且,除非您熟悉未指定的行为,否则应始终使用ID指定符号与svgfonts一起使用。这里是一个修复后的fiddle,展示了它应该如何看起来:http://jsfiddle.net/fPg3z/ - Erik Dahlström
@ErikDahlström WC3 CSS3字体工作草案告诉我:“对于SVG字体,URL指向包含SVG字体定义的文档中的元素。如果省略元素引用,则暗示引用第一个定义的字体”。 当我尝试在数据URL上指定片段时,Chrome会出现错误。哦天啊... - Jeremy
啊,刚没注意到CSS3字体草案中的那一部分,我会为Opera提交一个bug来处理这个情况。 - Erik Dahlström

1

在 CSS 中先指定本地字体名称,然后再指定嵌入字体的名称:

p {
    font-family: MyFontLocalName, MyFontEmbeddedName;
}

http://jsfiddle.net/gilly3/xX6Bv/5/

如果用户的计算机上安装了MyFontLocalName字体,则使用该字体,否则将使用MyFontEmbeddedName。这是与IT相关的内容。

这是一个好建议,但对我不起用。很抱歉我最初在帖子中没有提到:我允许用户从本地文档导入片段,这些片段通过其标准名称引用字体,因此这对他们行不通。:((之前我用的是不同名称的字体,"X"和"X Embedded"。) - Jeremy
@Jeremy - 棘手。我之前就想过这个问题。最好的解决方法是使用一个丑陋的hack,包括JavaScript:将一段文本放入一个带有所需字体和备用字体的span中,并设置非常大的大小,例如font-size: 200px; font-family: MyEmbeddableFont, Arial。将该span的宽度与测试字体的预期宽度进行比较。如果宽度不正确,则动态加载字体。 - gilly3
请注意,此实现“glyph”已被弃用:https://developer.mozilla.org/zh-CN/docs/Web/SVG/Element/glyph - Marius

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接