前言
最近在处理一个需求,给canvas中的文字加上背景色,达到与dom相同的效果,google、baidu找了一遍,完全没找到相关的文章。
首先
拆分问题,如果只给【背景A】加上背景色,应该怎么做,这就很简单了,代码如下,上下边距再适当调整即可。
const text = '背景A';
ctx.fillStyle="red";
ctx.font = "24px Microsoft YaHei"
const { width } = ctx.measureText('背景A');
ctx.fillRect(100, 100, width, 24);
ctx.fillStyle="black";
ctx.textBaseline = 'top';
ctx.fillText("背景A",100,100);
但是
文字不只有【背景A】,还有一个字体不一样的【背景B】,两个文字对齐方式为【基线对齐】,并不是顶部对齐。
我们已知的只有文字大小,以及下图中的x,yBaseline。y是完全不知道的。由于y不知道,我们无法确定红色背景的位置。
为了解决这个问题
我们需要去了解字体的构造(在下精力有限。。。这里只介绍英文字体)
em
在css中,我们经常会去设置文字的font-size属性,当设置文字大小为16px时,实际绘制的文字(这里字体为Arial)如图所示,文字实际的高度并没有占满16px。
在字体中,存在一个em的概念,最初的英文排版中,将大写字母M的宽度作为1em,我们所设置的字体大小即1em的大小。em 是字体设计者在设计字体时的一个参考,并没有硬性规定,字体的高度一定要小于1em,或者字体的位置一定要在1em内。举个例子,microsoft YaHei
字体,可以明显看到字体的下面已经超出了1em的最底部。
文字中的线
- top:字体的最顶端
- ascentder:上升,指图中小写字母高于mean line的部分。它的存在让小写字母更加易读
- ascent:指小写字母最顶端
- capHeight:指大写字母H的高度
- mean line:位于小写字母x的最顶端
- baseline:文字绘制的基准线,大写字母一般都在基准线之上绘制。
- xHeight:即小写字母x的高度,这是字体设计中一个非常重要的概念,它定义了一个小写字母主体应该有多高。
- descender:下降,指图中小写字母低于baseline的部分。与上升相对应
- descent:小写字母最底端
- bottom:字体的最底端
如何在web中测量出上面这些度量值
测算方法
测量方法是将特定的字母绘制到canvas中,通过getImageData读取图像数据,计算得出结果。 比如测算字母x的高度
- 将字母x绘制为黑色到canvas中
- 获取绘制区域的data developer.mozilla.org/zh-CN/docs/… ,即像素点数据
- 从前到后遍历data找到第一个非255的数据,这个点即x的左上角位置,下标除以绘制区域的宽度,向下取整,即是它到顶部的距离m。
- 从后往前遍历data找到最后一个非255的数据,这个点即x的右下角位置,下标除以绘制区域的宽度,向下取整即是它到顶部的距离n。
- x的高度即等于m-n。
通过这个方式,我们可以测得任意文字的高度。
Font Metrics
*以下所说的top、bottom、ascent、descent的大小为这些线到baseline的距离
- xHeight
- 通过测量字母x的高度可得出
- Cap height
- 通过测量字母H的高度可得出
- ascent
- descent
- 绘制文字时指定绘制的基线为文字的基线,设置基线位置为
yBase
,将所有小写字母绘制到canvas中,可得到最高点为yTop
,最低点yBottom
,那么ascent = yTop - yBase,descent = yBase - yBottom
- 绘制文字时指定绘制的基线为文字的基线,设置基线位置为
- Ascender
- 文字上升部分的高度,
ascender = ascent - xheight
- 文字上升部分的高度,
- desender
- 文字下降部分的高度,大小等于
descent
- 文字下降部分的高度,大小等于
- top
- 绘制文字时指定绘制的基线为文字的顶部,即
ctx.textBaseline = top
,设置基线位置为yBase
,将字母A绘制到canvas中,可得到最低点yBottom
,那么文字最顶部到基线的距离top = yBottom - yBase
- 绘制文字时指定绘制的基线为文字的顶部,即
- bottom
- 文字最顶部到最底部的距离为1em,那么文字最低部到基线的距离
bottom = 1em - top
- 文字最顶部到最底部的距离为1em,那么文字最低部到基线的距离
回到最开始的问题
那么y的值 y = yBaseline - FontMetrics.top
。
绘制【背景B】的背景时同理可解。
结语
写文章可太难了QAQ,如果文中有任何描述错误或者需要讨论的地方,欢迎评论区指出。
参考资料
-
en.wikipedia.org/wiki/Typefa…
-
stackoverflow.com/questions/4…
-
github.com/soulwire/Fo…
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!