有没有一种方法可以从HTML5画布访问字体图标?

3

我是html5画布的新手。

我需要显示字体图标(fontawesome)作为图片。 这个可行吗?谢谢。

1个回答

5

虽然有点麻烦,但确实是可能的。

由于Canvas会在实际字体还没有准备好时使用备用字体进行绘制,而且字体是惰性加载的,因此您需要等待字体准备好后再进行渲染。这应该可以使用类似于Google/Typekit的Web Font Loader(https://github.com/typekit/webfontloader)来实现。

一旦字体准备好,您就可以像绘制任何其他字符串一样在Canvas中绘制它,例如:

var ctx = document.getElementById('canvas').getContext('2d');
  ctx.font = '48px FontAwesome';
  ctx.fillText(String.fromCharCode(61449), 10, 50);

最大的挑战是你需要重新映射Font Awesome中所有符号,以及它们在JavaScript中的字符表示。

编辑:

实际上,可以通过名称计算CSS规则来完成此操作。

getFAChar = function (name) {
    var elm = document.createElement('i');
    elm.className = 'fa fa-' + name;
    elm.style.display = 'none';
    document.body.appendChild(elm);
    var content = window.getComputedStyle(
        elm, ':before'
    ).getPropertyValue('content')
    document.body.removeChild(elm);
    return content;
};

var ctx = document.getElementById('canvas').getContext('2d');
  ctx.font = '48px FontAwesome';
  ctx.fillText(getFAChar('bed'), 10, 50)

编辑:

为了提高性能,特别是在Canvas经常重绘时(添加和删除大量DOM元素不是达到60 fps的好方法),应该缓存FA图标。

var FontAwesome = (function () {
    var me = {},
        FACache = {};

    function find (name) {
        var elm = document.createElement('i');
        elm.className = 'fa fa-' + name;
        elm.style.display = 'none';
        document.body.appendChild(elm);
        var content = window.getComputedStyle(
            elm, ':before'
        ).getPropertyValue('content')
        document.body.removeChild(elm);
        return content;
    };

    me.get = function (name) {
        if (!!FACache[name]) return FACache[name];
        var c = find(name);
        FACache[name] = c;
        return c;
    };
    return me;
}());

var ctx = document.getElementById('canvas').getContext('2d');
  ctx.font = '48px FontAwesome';
  ctx.fillText(FontAwesome.get('bed'), 10, 50);

编辑

使用延迟渲染、自动css注入和css字符映射的完整示例,尽管只在Chrome中进行了测试(使用字体加载API和Promises,无需polyfill)。

var FontAwesome = function () {
 return new Promise(function (done, failed) {
  var me = {},
   FACache = {};

  function find (name) {
   var elm = document.createElement('i');
   elm.className = 'fa fa-' + name;
   elm.style.display = 'none';
   document.body.appendChild(elm);
   var content = window.getComputedStyle(
    elm, ':before'
   ).getPropertyValue('content')
   document.body.removeChild(elm);
   return content;
  };

  me.get = function (name) {
   if (!!FACache[name]) return FACache[name];
   var c = find(name)[1];
   FACache[name] = c;
   return c;
  };
  
  (function() {
   var l = document.createElement('link'); l.rel = 'stylesheet';
   l.onload = function () {
    document.fonts.load('10px FontAwesome')
     .then(function (e) { done(me); })
     .catch(failed);
   }
   l.href = '//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css';
   var h = document.getElementsByTagName('head')[0]; h.parentNode.insertBefore(l, h);
  }());
 });
};

FontAwesome()
.then(function (fa) {
    // All set, and ready to render!
    var ctx = document.getElementById('canvas').getContext('2d');
        ctx.font = '48px FontAwesome';
        ctx.fillText(fa.get('bed'), 10, 50);
});
<canvas id="canvas"></canvas>


谢谢,这真的很有帮助。 - tony pro
2
谢谢。最后一条评论: 在计算CSS规则中的Font Awesome字符的示例中,实际上每次都会创建元素并将其删除,如果画布经常重新绘制,则缓存这些字符可能是一个好主意。我将使用简单版本更新上面的示例。 - Morten Olsen
哇,这太棒了,它澄清了一切。再次感谢。 - tony pro

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