在Fabric.js中使用远程网络字体初始化加载文本

9
我正在开发一个使用Fabric JS的大型自定义应用程序,已经完成了很多工作。但是我遇到了一个问题,就是初始化加载文本对象时使用了Web字体。
只要该字体在客户端计算机上是本地的,它就可以正常工作。否则,Web字体将无法加载,画布上的文本对象将以默认的Sans-serif字体族呈现。
以下是我所做的简要说明(在这个例子中,我使用“allstar”作为我的Web字体):
CSS:css在fonts.css中加载,位于head中fabric.js之前。
@font-face{
    font-family:'allstar';
    src:
        url('/path-to-fonts/all_star-webfont.eot');
    src:
        url('/path-to-fonts/all_star-webfont.eot?#iefix') format('embedded-opentype'),
        url('/path-to-fonts/all_star-webfont.woff') format('woff'),
        url('/path-to-fonts/all_star-webfont.ttf') format('truetype'),
        url('/path-to-fonts/all_star-webfont.svg#allstarregular') format('svg');
    font-weight:normal;
    font-style:normal
}

Javascript: 这段代码被加载在页面底部,放在$(document).ready(function(){})函数内。

var textSample = new fabric.Text(text, {
    fontFamily: "allstar",
});
canvas.add(textSample);
canvas.renderAll();

如果我在页面的其他地方使用这种字体(例如:在一个透明的带有点和已加载字体的span标签中),它可以正常工作。但我认为这不是编码的正确方式。
我使用的是fabric.js版本1.3.0。
6个回答

4
问题:
  1. 画布立即渲染
  2. 谷歌加载网络字体
  3. 画布在下一次重新渲染之前不知道
解决方案:
  1. 画布立即渲染
  2. 谷歌通过回调函数加载网络字体
  3. 强制重新渲染
  4. 画布现在有了

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

WebFontConfig = {
    google: { families: [ 'Ribeye::latin', 'Lora::latin', 'Croissant+One::latin', 'Emblema+One::latin', 'Graduate::latin', 'Hammersmith+One::latin', 'Oswald::latin', 'Oxygen::latin', 'Krona+One::latin', 'Indie+Flower::latin', 'Courgette::latin', 'Ranchers::latin' ] }
};

(function() {
    var src = ('https:' === document.location.protocol ? 'https' : 'http') +
        '://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js';

    $.getScript(src, function(data) {      
        // Not sure why I need to run this twice but it makes it load the font and then reposition the font to it's correct coords.
        canvas.renderAll();
        canvas.renderAll();
    });
})();

1
无法工作(Google Chrome)。我不得不使用setTimeout进行重新渲染。 - Alexander Selishchev
1
+1 WebFont加载器为我解决了问题,甚至无需显式设置任何回调函数。我只需加载Web字体,然后加载画布,现在它可以正常工作了。 - Josh Ribakoff
那其实是个更好的想法。你还可以使用异步设置来按顺序正确加载所有内容。https://github.com/caolan/async#seriestasks-callback - Michael J. Calkins

2
短途:
<script src="//ajax.googleapis.com/ajax/libs/webfont/1.4.7/webfont.js"></script>
<script>
WebFont.load({
            google: {
                families: [ 'Abel', 'Aclonica']
            },
            fontinactive: function(familyName, fvd) {
                console.log("Sorry " + familyName + " font family can't be loaded at the moment. Retry later.");
            },
            active: function() {
                // do some stuff with font   
                $('#stuff').attr('style', "font-family:'Abel'");
                var text = new fabric.Text("Text Here", {
                    left: 200,
                    top: 30,
                    fontFamily: 'Abel',
                    fill: '#000',
                    fontSize: 60
                });

                canvas.add(text);
            }
        });
</script>

长路 网页字体何时加载,是否可以预加载? 更多关于网页字体加载器 https://github.com/typekit/webfontloader 特定问题 https://groups.google.com/forum/#!topic/fabricjs/sV_9xanu6Bg

1
使用fabric.js和Google Web Fonts,以下代码适用于我:
演示:http://jsfiddle.net/DanBrown180/vvL6f/ CSS
<Style>
@font-face {
font-family: 'Jolly Lodger';
font-style: normal;
font-weight: 400;
src: local('Jolly Lodger'), local('JollyLodger'),
url(http://themes.googleusercontent.com/static/fonts/jollylodger/v1/RX8HnkBgaEKQSHQyP9itiaRDOzjiPcYnFooOUGCOsRk.woff) format('woff');
}
<style>

JavaScript

<script type = "text/javascript">
canvas = new fabric.Canvas('c'); 
var text = new fabric.Text("Web Font Example", {
                    left: 200,
                    top: 30,
                    fontFamily: 'Jolly Lodger',
                    fill: '#000',
                    fontSize: 60
                });

canvas.add(text);
</script>

HTML
<canvas id="c" height="200px" width="400px"></canvas>

看起来是因为Google Web Fonts的css代码使用了:

src: local('Jolly Lodger'), local('JollyLodger')

在CSS中

3
嗨丹,谢谢你的回答,但是那与我所做的类似,只是你使用了Google字体。不幸的是,在我的项目中,我必须使用存储在我们服务器上的自己的字体。此外,如果我查看你的jsfiddle示例,你也有同样的问题。就像我一样,当你在画布上单击时,文本会以正确的字体重新呈现。 - Jens

1
我有同样的问题。 字体在某个事件触发后才正确渲染。 因此,在创建对象后,我们可以将其设置为活动状态:
var textSample = new fabric.Text(text, {
    fontFamily: "allstar",
});
canvas.add(textSample);
canvas.setActiveObject(textSample); // Selects the object
canvas.renderAll();

0
最好的方法是使用 setTimeout();
setTimeout(function(){
    var activeObject = canvas.getActiveObject();
    activeObject.set({
        fontFamily: font,
        useNative: true
    });
canvas.renderAll();},500);

请查看jsfiddle

http://jsfiddle.net/muthupandiant/x3ptsgex/1/


8
不,那不是最佳方法,因为1)如果字体加载时间超过500毫秒,它无法解决问题,2)如果字体加载时间少于500毫秒,我们的应用程序仍会等待那么长时间,并感觉很慢。 - Josh Ribakoff

0

截至2017年,在Firefox中很容易地在Fabric.js中使用Web字体。

您只需要通过样式表中的 @import<head> 中的 <link href="..."> 包含它们。然后,您可以使用 fabric.Text 的属性 'fontFamily' 选择任何字体。

关于您最初的问题,调用 canvas.renderAll(); 应该重新绘制画布,从而正确显示所有已加载的Web字体。

在jsFiddle上看一个 简单的例子


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