我正在使用convas context measureText
来获取画布上文本的宽度。以下是代码:
ctx.fillStyle = color;
ctx.fontWeight = FONT_WEIGHT;
ctx.font = `bolder italic ${fontsize}px`;
const textWidth = ctx.measureText(text).width;
问题是,如果字体样式为italic
,则文本右侧将偏离边界。这是因为measureText
未将italic
考虑在内。如何计算italic
样式的文本宽度?
以下是convas上italic
字体的两个屏幕截图。第一个是没有斜体的文本,而第二个是斜体。你可以看到第二个有一点偏离边界。
答案 0 :(得分:1)
这是字体及其容器框的斜体渲染所固有的问题
我不是专家,也不会扩展这个已经在Q/A关于DOM + CSS处理过的主题。请注意,2DCanvas measureText
也会遇到同样的问题。
我能想到的唯一解决方法是通过一个svg元素,它通过getBBox
方法提供更好的图形边界框表示。
// Calculate the BBox of a text through an svg Element
function getTextBox(txt, x, y) {
var svg = document.createElementNS("http://www.w3.org/2000/svg", 'svg');
var text = document.createElementNS("http://www.w3.org/2000/svg", 'text');
// so we don't see the svg element in page
svg.style = 'position: absolute; z-index:-1; width:0; height: 0';
text.setAttribute('x', x || 0);
text.setAttribute('y', y || 0);
text.setAttribute('text-anchor', getAlignment(this.textAlign));
text.setAttribute('alignment-baseline', this.textBaseline);
text.style.font = this.font;
text.textContent = txt;
svg.appendChild(text);
document.body.appendChild(svg);
var box = text.getBBox();
document.body.removeChild(svg);
return box;
// convert CSS text-align notation to correpsonding SVG text-anchor
function getAlignment(css) {
return {
'left': 'start',
'right': 'end',
'center': 'middle'
}[css] || '';
}
}
// attach it to the proto so it's easier to grab context's current status
Object.defineProperty(CanvasRenderingContext2D.prototype, 'getTextBox', {get: function() {return getTextBox;}});
var x = 20,
y = 100;
var ctx = canvas.getContext('2d');
ctx.font = 'bolder italic 100px serif';
var txt = 'Right';
ctx.fillText(txt, x, y);
// red => ctx.measureText
var m_width = ctx.measureText(txt).width;
ctx.strokeStyle = 'red';
ctx.strokeRect(x, 0, m_width, y);
ctx.strokeStyle = 'green';
// green => svg.getBBox
var box = ctx.getTextBox(txt, x, y);
ctx.strokeRect(box.x, box.y, box.width, box.height);
<canvas id="canvas"></canvas>
答案 1 :(得分:0)
首先设置ctx.font
。 ctx.measureText
的结果基于上下文的当前字体,与您在绘图时看到的字体相同。执行ctx.fillText
检查是否正确设置了字体,我发现语法很容易出错。
答案 2 :(得分:0)
您需要将文本加载到隐藏的HTML div中并获取计算出的宽度。