HTML5画布上的外部字体

19

我完全不知道如何在画布上绘制文本时更改使用的字体。以下是我在 CSS 中定义的字体:

@font-face{
 font-family:"Officina";
 src:url(OfficinaSansStd-Book.otf);
}

现在在我的HTML/JavaScript中,我很想说:

context.font = '30px "Officina"';

但是这样并不起作用。如果我使用一个网络可用的字体(比如Arial),它可以正常工作,而且当我直接将纯文本写入网页时,Officina字体也能正常显示。我错过了什么吗?


2
不确定,但也许你需要等待字体加载完成后再运行JS?你可以尝试在DOM加载后设置5秒的超时,然后查看它是否有效(因为字体很可能会在DOM加载后的5秒内加载完成)。这只是一个假设。 - Oscar Godson
怎么做呢?我对DOM不是很熟悉。 - cryptic_star
尝试只执行document.body.onload函数,如下所示: function(){ setTimeout(function(){ /* all your code here */ },5000) }; 这并不等待DOM加载完成,但它很接近。 - Oscar Godson
7个回答

3
为了实现跨浏览器兼容性,您应该像这样使用CSS来嵌入字体:

@font-face {
    font-family: 'BankGothicMdBTMedium';
    src: url('bankgthd-webfont.eot');
    src: local('BankGothic Md BT'), local('BankGothicBTMedium'), url('bankgthd-webfont.woff') format('woff'), url('bankgthd-webfont.ttf') format('truetype'), url('bankgthd-webfont.svg#webfontNgZtDOtM') format('svg');
    font-weight: normal;
    font-style: normal;
}

注意:我在某个地方得到了这些字体文件 http://fontsquirrel.com
对我来说这很有效,但我还在HTML标记中使用此字体,因此如果font-face定义无法帮助,可以使用该字体在某些隐藏的
中解决问题,当然,我在页面加载后运行所有JS。

3

2

所以我尝试在所有的JS之前添加一个带有一些文本的<div>,但没有成功。你可以在这里看到 - 白色框上方的文本是正确的字体,"Computer"这个词是无衬线字体(应该是这样的),但另一个文本框也是无衬线字体,但被定义为Officina。 - cryptic_star

2

您可以使用Google Web字体加载器,但对于许多用途而言,它可能过于笨重或繁琐。相反,我建议使用Jennifer Simonds的 FontDetect 库,该库可在GitHub上获取:

一个JavaScript类,您可以使用它来确定是否加载了Web字体,哪个字体被元素使用,或对Web字体的加载(或加载失败)做出反应。


1
你可以使用FontFace API在画布中使用字体之前加载它们:
// new FontFace(familyName, fontSrc, descriptorOnly)
const myFont = new FontFace('My Font', 'url(https://myfont.woff2)');

myFont.load().then((font) => {
  document.fonts.add(font);

  console.log('Font loaded');
});

首先下载字体资源myfont.woff2。下载完成后,将字体添加到文档的FontFaceSet中。

FontFace API规范在撰写本文时仍为工作草案。请查看此处的浏览器兼容性表格

然后,您可以使用字体参数来设置您的字体系列。

var ctx = document.getElementById('c').getContext('2d');
var kitty = new Image();
kitty.src = 'http://i954.photobucket.com/albums/ae30/rte148/891blog_keyboard_cat.gif';
kitty.onload = function(){
  ctx.drawImage(this, 0,0,this.width, this.height);
  ctx.font         = '68px KulminoituvaRegular';
  ctx.fillStyle = 'orangered';
  ctx.textBaseline = 'top';
  ctx.fillText  ('Keyboard Cat', 0, 270);
};

注意:
  1. 你可以使用"@font-face" CSS简单地加载字体,但请记住,在绘制画布之前,必须将字体加载到文档中。

  2. 所有的字体和图片(实际上所有资源)都应该在同一个源或启用了cors-origin,否则大多数浏览器都会拒绝网络请求。


0

注意:截至2016年已过时

使用这个技巧并将onerror事件绑定到一个Image元素上。

演示在此处:http://jsfiddle.net/g6LyK/ - 在最新的Chrome浏览器上可以正常工作。

var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');

var link = document.createElement('link');
link.rel = 'stylesheet';
link.type = 'text/css';
link.href = 'http://fonts.googleapis.com/css?family=Vast+Shadow';
document.getElementsByTagName('head')[0].appendChild(link);

// Trick from https://dev59.com/H3E85IYBdhLWcg3wvGKm
var image = new Image;
image.src = link.href;
image.onerror = function() {
    ctx.font = '50px "Vast Shadow"';
    ctx.textBaseline = 'top';
    ctx.fillText('Hello!', 20, 10);
};

@KarelBílek 确认了,但我现在没有时间更新。 - a paid nerd

-7

不妨尝试将您的URL作为字符串放置:

@font-face{
 font-family:"Officina";
 src:url('OfficinaSansStd-Book.otf');
}

context.font = "30px Officina";

“我不确定它是否有效,但是试一下”这个陈述立即揭示了你的问题的主要问题。 - Luke Taylor

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