是否可以在画布上写图像并用背景写文本?例如像这样:
3 回答
文本在画布中的工作原理
不幸的是,您不能使用 text 方法生成带有背景的文本 - 只能填充或勾勒文本本身。
这是因为如果需要,字体(字体)中的字形会转换为单独的形状或路径,其中它的背景将是字形本身的内部部分(使用填充时看到的部分)。除了使用其几何位置之外,字形正在使用的黑盒(字形适合的矩形)没有层,因此我们需要自己提供一种黑盒和轴承。
在旧计算机系统上,大多数字体在二进制字体中设置或清除像素。除了清除背景之外,还可以选择提供背景。默认情况下,基于矢量的字体不是这种情况(浏览器可以直接访问字形几何,因此可以通过这种方式提供背景)。
创建自定义背景
为了创建背景,您需要先使用其他方式(例如形状或图像)来绘制它。
例子:
ctx.fillRect(x, y, width, height);
或者
ctx.drawImage(image, x, y [, width, height]);
然后在顶部绘制文本:
ctx.fillText('My text', x, y);
您可以使用measureText
来找出文本的宽度(将来还有高度:上升 + 下降)并将其用作基础:
var width = ctx.measureText('My text').width; /// width in pixels
您可以将所有这些包装在一个函数中。这里的功能是基本的,但您可以使用颜色和背景参数以及填充等来扩展它。
/// expand with color, background etc.
function drawTextBG(ctx, txt, font, x, y) {
/// lets save current state as we make a lot of changes
ctx.save();
/// set font
ctx.font = font;
/// draw text from top - makes life easier at the moment
ctx.textBaseline = 'top';
/// color for background
ctx.fillStyle = '#f50';
/// get width of text
var width = ctx.measureText(txt).width;
/// draw background rect assuming height of font
ctx.fillRect(x, y, width, parseInt(font, 10));
/// text color
ctx.fillStyle = '#000';
/// draw text on top
ctx.fillText(txt, x, y);
/// restore original state
ctx.restore();
}
请注意,这种“测量”高度的方式并不准确。您可以使用临时 div/span 元素测量字体的高度,并在为其设置字体和文本时从中获取计算的样式。
我更简单的解决方案是调用 fillText 两次。首先是一个 Unicode+2588 █ 字符串,它是一个黑色矩形,使用背景颜色重复与文本相同的长度。然后用前景色照常调用fillText。
此功能为您提供带有背景的垂直和水平居中文本。它仅适用于等宽字体(具有相同宽度的字符)。该函数计算要打印的字符串中的字符数,并将它们乘以 0.62(假设字体的宽度略小于高度的 0.62 倍)。背景是字体大小的 1.5 倍。更改此项以满足您的需求。
function centeredText(string, fontSize, color) {
var i = string.length;
i = i*fontSize*0.62;
if (i > canvas.width) {
i = canvas.width;
}
ctx.fillStyle = "RGBA(255, 255, 255, 0.8)";
ctx.fillRect(canvas.width / 2 - i / 2,canvas.height / 2 - (fontSize * 1.5) / 2, i, (fontSize * 1.5) );
ctx.font = fontSize.toString() + "px monospace";
ctx.fillStyle = color;
ctx.textBaseline = "middle";
ctx.textAlign = "center";
ctx.fillText(string, canvas.width / 2, canvas.height / 2);
}
所以调用函数看起来像这样。
centeredText("Hello World", 30, "red");