不知道字体族群的情况下如何更改画布的字体大小

30
有没有一种方法能够只改变画布上下文的字体大小,而不必知道或编写字体族?
 var ctx = document.getElementById("canvas").getContext("2d");

 ctx.font = '20px Arial'; //Need to speficy both size and family...     

注意:
ctx.fontSize = '12px'; //doesn't exist so won't work...
ctx.style.fontSize = '20 px' //doesn't exist so won't work... 
                         //we are changing the ctx, not the canvas itself

另外注意:我可以做一些事情,比如检测'px'出现的位置,去掉'px'前面的内容并替换为我的字体大小。但如果有更简单的方法,我希望使用更简单的方法。

5个回答

26

这里有一种更简单、更清晰的改变字体大小的方法,无论你是否使用了 font-variant 或 font-weight 都可以使用。

首先,使用一些正则表达式来匹配并返回当前字体大小。

const match = /(?<value>\d+\.?\d*)/;

假设您的新字体大小为12px,请设置绝对大小。

ctx.font = ctx.font.replace(match, 12);

设置相对大小,增加5:

const newSize = parseFloat(ctx.font.match(match).groups.value + 5);
ctx.font = ctx.font.replace(match, newSize);

工作示例:

const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");

// Match on digit at least once, optional decimal, and optional digits
// Named group `value`
const match = /(?<value>\d+\.?\d*)/;

const setFontSize = (size) => ctx.font = ctx.font.replace(match, size);

const adjustFontSize = (amount) => {
  const newSize = parseFloat(ctx.font.match(match).groups.value + amount);
  return ctx.font = ctx.font.replace(match, newSize);
}

// Default font is 12px sans-serif
console.log( setFontSize(18) );    // 18px sans-serif
console.log( adjustFontSize(2) );  // 20px sans-serif
console.log( adjustFontSize(-5) ); // 15px sans-serif
<canvas id="canvas"></canvas>


"replace" 可以接受一个函数来进行替换,您无需对正则表达式进行两次匹配... - anon
有时候,需要使用浮点数而不是整数。ctx.font = ctx.font.replace(/[0-9.]+px/, (parseFloat(ctx.font.match(/[0-9.]+px/)) + 2) + "px") 可以解决这种情况。 - syviad

14

更新:(来自评论)没有办法绕过指定字体。Canvas 的字体是基于 CSS 中的简写版本来进行建模的。

然而,画布上始终会设置一个字体(或者字体类型),因此你可以通过以下方式提取当前字体:

var cFont = ctx.font;

然后替换大小参数并将其设置回去(请注意,那里可能还有样式参数)。

为了举例而进行的简单拆分:

var fontArgs = ctx.font.split(' ');
var newSize = '12px';
ctx.font = newSize + ' ' + fontArgs[fontArgs.length - 1]; /// using the last part

如果需要,您将需要支持样式(如果使用,则首先出现)。 请注意,字体大小是第四个参数,因此如果您具有/不具有字体变体(粗体、斜体、倾斜),字体变体(正常、小型大写)和字体重量(粗体等),则此方法将无法正常工作。


你正在做我在另一个笔记中提到的事情: - RainingChain
@RainingChain,也许是我眼花了,你在哪里展示它? - user1693593
@RainingChain,无论如何都必须指定字体。Canvas的字体是基于CSS中字体的简写版本建模的。 - user1693593
好像很蠢,不能单独指定字体属性 :( - SuperUberDuper
5
这个答案没有考虑包含空格的字体名称,比如sakkal majallaTimes New Roman等。按空格分割将产生一个数组,其中包含字体大小以及与字体名称相同数量的单词,每个单词都在一个元素中。 - Ahmad

2

一种更简洁的方法,不必担心抓取其他参数:

canvas.style.font = canvas.getContext("2d").font;
canvas.style.fontSize = newVal + "px";

canvas.getContext("2d").font = canvas.style.font;

解释: 正如第一个答案中提到的,画布上下文始终会有字体。因此,canvas.getContext("2d").font可能返回类似于"10px sans-serif"的字符串。为了不解析此字符串,我们可以使用Canvas DOM元素(或任何其他元素)来解析完整的字体规范并填充其他字体字段。这意味着在设置之后:

canvas.style.font = "10px sans-serif";
canvas.style.fontSize = "26px";
canvas.style.font 将变成 "26px sans-serif"。我们可以将这个字体规范传回画布上下文。

你没有在任何地方设置新的 fontSize - lambshaanxy
如第一个答案中所述,画布上下文将始终具有字体。因此,canvas.getContext("2d").font可能返回类似于"10px sans-serif"的内容。为了不解析此字符串,我们可以使用Canvas DOM元素(或任何其他元素)来解析完整的字体规范并填充其他字体字段。这意味着在设置canvas.style.fontSize = "26px";之后,canvas.style.font将变为"26px sans-serif"。然后,我们将此字体规范反馈给画布上下文。 - user5480949

1
为了正确回答您的问题,如果不知道或不写出字体系列,就无法更改画布上下文的字体大小。

1
尝试这个(使用jQuery):

    var span = $('<span/>').css('font', context.font).css('visibility', 'hidden');
    $('body').append(span);
    span[0].style.fontWeight = 'bold';
    span[0].style.fontSize = '12px';
    //add more style here.
    var font = span[0].style.font;
    span.remove();
    return font;

2
好主意。无需附加到body,也不需要使用jQuery。var span = document.createElement('span'); span.style.font = ctx.font; return span.style.fontSize; - RainingChain

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