Canvas仅使用fabric.js在click事件上呈现自定义webfont

时间:2015-03-05 11:37:20

标签: javascript canvas fabricjs

我的自定义webfonts和fabric.js一直存在问题。 我的应用程序使用了很多自定义webfonts,我在向画布添加iText时启动它们:

var text = new fabric.IText("My Text", {
    fontFamily: "Some Custom Font Family",
    fontSize: 50,
    top: 0,
    left: 0,
    fill: "#000000"
  });

  canvas.add(text);
  canvas.bringToFront(text);
  canvas.setActiveObject(text);

  canvas.renderAll();

只有当我点击画布上的iText并与之互动时才有效。然后,一旦加载了字体,它就不再是问题了。问题是最初和第一次添加iText。

我研究了很多并且来到这个主题:

Init loaded text with remote web font in Fabric.js

但这对我没有帮助。 jsfiddle提供了完全相同的问题:

http://jsfiddle.net/vvL6f/6/

使用已清除缓存的全新浏览器(例如Chrome CMD + Shift + R)打开此小提琴。一旦打开小提琴,您将看到自定义的webfont未加载,但是当您单击右侧的iText时会立即加载。

现在,我们如何解决这个问题?

建议的方法是将useNative设置为false,让Cufon渲染文本,但这不起作用。

我将我的webfonts加载到这样的CSS文件中:

@font-face {
    font-family: 'ApolloASM';
    src: url('ApolloASM-webfont.eot');
    src: url('ApolloASM-webfont.eot?#iefix') format('embedded-opentype'),
         url('ApolloASM-webfont.woff2') format('woff2'),
         url('ApolloASM-webfont.woff') format('woff'),
         url('ApolloASM-webfont.ttf') format('truetype'),
         url('ApolloASM-webfont.svg#apollo_asmregular') format('svg');
    font-weight: normal;
    font-style: normal;
}

5 个答案:

答案 0 :(得分:14)

@Prominic答案几乎就在那里。我还有一个使用Fabric的自定义字体的画布应用程序。我像你一样在CSS中加载所有字体。问题是,仅在样式表中声明@font-face是不够的。除非在文档中使用,否则浏览器不会请求字体文件。 您必须确保在初始化画布之前加载并应用webfont。这可以通过一些工作来实现,我将通过下面的示例来说明这一点。缺点是您可能需要预加载应用程序可供用户使用的所有字体。

  1. 声明您的webfont

    在样式表中添加@font-face语句。只需确保它已加载到<head>部分。让我们用你的例子:
  2.  @font-face {
        font-family: 'ApolloASM';
        src: url('ApolloASM-webfont.eot');
        src: url('ApolloASM-webfont.eot?#iefix') format('embedded-opentype'),
             url('ApolloASM-webfont.woff2') format('woff2'),
             url('ApolloASM-webfont.woff') format('woff'),
             url('ApolloASM-webfont.ttf') format('truetype'),
             url('ApolloASM-webfont.svg#apollo_asmregular') format('svg');
        font-weight: normal;
        font-style: normal;
    }
    

    奖金提示:如果您在应用中使用斜体和/或粗体,建议您在不同浏览器中使用一致的结果时,为这些样式添加字体 - 面。例如,Android Browser 4.2无法计算字体的斜体,并将正常显示。

    1. 强制请求字体文件

    2. 如上所述,您需要实际使用DOM中的字体来强制加载字体。只需添加带有一些文本的div并使用您的字体设置样式就足够了:

      <div style="font-family:'ApolloASM'">&nbsp;</div>
      

      奖金提示:不要忘记添加斜体和粗体变体

      1. 在DOM load事件后初始化FabricJS Canvas

      2. 在浏览器加载字体后,您需要同步canvas init(或至少文本添加),否则您可能会看到FOUT效果(无格式文本的Flash)。幸运的是,在加载所有字体文件之前,浏览器不会触发load事件,这可以用来安全地将样式文本添加到画布:

        window.addEventListener('load', function onLoad() {
            var canvas = new Fabric.Canvas({...});
            var text = new fabric.Text("Web Font Example", {
                left: 200,
                top: 30,
                fontFamily: 'ApolloASM',
                fill: '#000',
                fontSize: 60
            });
        
            canvas.add(text);
            canvas.renderAll();
        })
        

        奖励提示:您可以将这些字体<div>包装在另一个字体中,并在DOM load事件后将其删除,以避免破坏您可能拥有的任何布局。

答案 1 :(得分:4)

您可以使用网络字体加载器。

    <script src="//ajax.googleapis.com/ajax/libs/webfont/1.5.18/webfont.js">    </script>
    <script>
    var c = new fabric.Canvas('canvas');
    WebFont.load({
    	google: {
    		families: ['Fredoka One']
    	},
    	active: function() {
            var text = new fabric.IText('Hello world !', {
                fontFamily: 'Fredoka One',
                top: 100,
                left: 100,
                fontSize: 20
            });
    	    c.add(text);
    	},
    });
    </script>

JSFiddle here

答案 2 :(得分:1)

当您的脚本首次渲染画布时,Webfont尚未加载。

我说最好的执行方法是使用HTML标记加载webfont。这将在DOM的顶部加载字体,以便在浏览器呈现时为您的画布脚本准备好字体。这是一个例子。

https://jsfiddle.net/j47k79e8/1/

<link href='http://fonts.googleapis.com/css?family=Ranchers' rel='stylesheet' type='text/css'>

虽然如果您仍想使用Javascript方法加载webfont,您可以在运行FabricJS脚本之前等待加载文档。只需将其包装在文档就绪声明中即可。

$(document).ready(function(){
  // FabricJS scripts
});

https://jsfiddle.net/ahxpeu0v/3/

答案 3 :(得分:0)

您只需在插入文本后插入canvas.renderAll();命令,如下所示:

canvas = new fabric.Canvas('c'); 
var text = new fabric.Text("Web Font Example", {
    left: 200,
    top: 30,
    fontFamily: 'Ranchers',
    fill: '#000',
    fontSize: 60
});

canvas.add(text);
canvas.renderAll();

小提琴:http://jsfiddle.net/vvL6f/107/

答案 4 :(得分:0)

回答@Bernardo Domingues对我不好,因为我edit databases有超过500种字体,我不想因为交通限制而预加载所有字体。

所以我通过每500ms重复调用<select>方法解决了这个问题。一次又一次。这种方式我将字体更改为新的(尚未被浏览器加载) - 首先它将被浏览器下载(我不知道,我不在乎需要花多少时间)。一旦加载了新的字体 - 我的代码将在500毫秒内更新整个画布并瞧!我的字体也更新了:)