关于jquery:如何在画布中使用具有CSS中描述的字体的文本元素

How to use in a canvas a text element with a font described in CSS

这在Bismon项目(由H2020欧洲项目资助的GPLv3软件)中,git commit 0e9a8eccc2976f。该报告草稿介绍了该软件。这个问题给出了更多的背景和动机。
它是关于(手写的)webroot / jscript / bismon-hwroot.js文件,该文件用在某些HTML页面中,该页面的代码由Bismon(libonion上方的专用Web服务器)生成。

我为跨度添加了一些CSS类,例如span.bmcl_evalprompt(例如在我的文件first-theme.css中)。

如何编码JavaScript以在画布中添加文本片段(最好将jcanvas与jquery一起使用),使其具有与span.bmcl_evalprompt相同的样式(相同的字体,颜色等)?我是否需要在DOM中创建这样的span元素?这甚至有可能吗?

我只关心Linux上的最新Firefox(至少68个)。 jQuery是3.4。我也在使用Jquery UI 1.12.1

我的想法是创建一个单独的<span class='bmcl_evalprompt'>元素,其坐标远离浏览器视口(或X11窗口),例如在x= -10000y= -10000(以像素为单位)处,然后将单个位置错误的元素添加到文档DOM中,然后使用传统的Jquery技术获取字体系列,字体大小和元素大小。但是还有更好的方法吗?还是某些兼容Jquery的库呢?


在画布中匹配DOM字体?

简单的答案是,"要努力!!"和"永远不可能是完美的。"

您能做的最好的是在答案底部的示例中找到一个近似值,该近似值还将显示与可见样式匹配与可见质量无关。
从CSS规则扩展。

如果您希望字体尽可能地与元素匹配,则除了获得Spark Fountain的答案中指出的CSS之外,还有其他一些问题。

字体大小


如果只想在画布中显示跨度中的文本,则可以使用window.getComputedStyle函数访问样式属性。要使原始跨度不可见,请将其样式设置为display: none

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// get the span element
const span = document.getElementsByClassName('bmcl_evalprompt')[0];

// get the relevant style properties
const font = window.getComputedStyle(span).font;
const color = window.getComputedStyle(span).color;

// get the element's text (if necessary)
const text = span.innerHTML;

// get the canvas element
const canvas = document.getElementById('
canvas');

// set the canvas styling
const ctx = canvas.getContext('
2d');
ctx.font = font;
ctx.fillStyle = color;

// print the span'
s content with correct styling
ctx.fillText(text, 35, 110);
1
2
3
4
5
6
7
8
9
10
11
12
#canvas {
  width: 300px;
  height: 200px;
  background: lightgrey;
}

span.bmcl_evalprompt {
  display: none;           // makes the span invisible
  font-family: monospace;  // change this value to see the difference
  font-size: 32px;         // change this value to see the difference
  color: rebeccapurple;    // change this value to see the difference
}
1
2
<span class="bmcl_evalprompt">Hello World!</span>
<canvas id="canvas" width="300" height="200"></canvas>