Answers:
var bbox = textElement.getBBox();
var width = bbox.width;
var height = bbox.height;
然后相应地设置rect的属性。
链接:getBBox()
SVG v1.1标准中的链接。
关于文本的长度,链接似乎表明BBox和getComputedTextLength()可能返回略有不同的值,但它们彼此之间的距离非常接近。
这样的兼容性如何:
function svgElemWidth(elem) {
var methods = [ // name of function and how to process its result
{ fn: 'getBBox', w: function(x) { return x.width; }, },
{ fn: 'getBoundingClientRect', w: function(x) { return x.width; }, },
{ fn: 'getComputedTextLength', w: function(x) { return x; }, }, // text elements only
];
var widths = [];
var width, i, method;
for (i = 0; i < methods.length; i++) {
method = methods[i];
if (typeof elem[method.fn] === 'function') {
width = method.w(elem[method.fn]());
if (width !== 0) {
widths.push(width);
}
}
}
var result;
if (widths.length) {
result = 0;
for (i = 0; i < widths.length; i++) {
result += widths[i];
}
result /= widths.length;
}
return result;
}
这将返回这三种方法的任何有效结果的平均值。getComputedTextLength
如果元素是文本元素,则可以改进它以排除异常值或偏爱它。
警告:正如评论所说,这getBoundingClientRect
很棘手。要么将其从方法中删除,要么仅将其用于getBoundingClientRect
将返回良好结果的元素上,因此不进行旋转并且可能不进行缩放
不知道为什么,但是以上方法都不适合我。我在canvas方法上取得了一些成功,但是我不得不应用各种比例因子。即使使用比例因子,Safari,Chrome和Firefox之间的结果仍然不一致。
因此,我尝试了以下方法:
var div = document.createElement('div');
div.style.position = 'absolute';
div.style.visibility = 'hidden';
div.style.height = 'auto';
div.style.width = 'auto';
div.style.whiteSpace = 'nowrap';
div.style.fontFamily = 'YOUR_FONT_GOES_HERE';
div.style.fontSize = '100';
div.style.border = "1px solid blue"; // for convenience when visible
div.innerHTML = "YOUR STRING";
document.body.appendChild(div);
var offsetWidth = div.offsetWidth;
var clientWidth = div.clientWidth;
document.body.removeChild(div);
return clientWidth;
很棒且非常精确,但仅在Firefox中有效。可以使用Chrome和Safari的比例因子,但并不令人高兴。事实证明Safari和Chrome错误与字符串长度或字体大小不是线性关系。
因此,方法二。对于蛮力方法,我不太在意,但是经过多年的努力,我决定尝试一下。我决定为每个可打印字符生成常量值。通常这会很乏味,但是幸运的是Firefox恰好是超级准确的。这是我的两部分暴力解决方案:
<body>
<script>
var div = document.createElement('div');
div.style.position = 'absolute';
div.style.height = 'auto';
div.style.width = 'auto';
div.style.whiteSpace = 'nowrap';
div.style.fontFamily = 'YOUR_FONT';
div.style.fontSize = '100'; // large enough for good resolution
div.style.border = "1px solid blue"; // for visible convenience
var character = "";
var string = "array = [";
for(var i=0; i<127; i++) {
character = String.fromCharCode(i);
div.innerHTML = character;
document.body.appendChild(div);
var offsetWidth = div.offsetWidth;
var clientWidth = div.clientWidth;
console.log("ASCII: " + i + ", " + character + ", client width: " + div.clientWidth);
string = string + div.clientWidth;
if(i<126) {
string = string + ", ";
}
document.body.removeChild(div);
}
var space_string = "! !";
div.innerHTML = space_string;
document.body.appendChild(div);
var space_string_width = div.clientWidth;
document.body.removeChild(div);
var no_space_string = "!!";
div.innerHTML = no_space_string;
document.body.appendChild(div);
var no_space_string_width = div.clientWidth;
console.log("space width: " + (space_string_width - no_space_string_width));
document.body.removeChild(div);
string = string + "]";
div.innerHTML = string;
document.body.appendChild(div);
</script>
</body>
注意:以上代码段必须在Firefox中执行才能生成准确的值数组。另外,您必须在控制台日志中用空格宽度值替换数组项32。
我只是复制屏幕上的Firefox文本,然后将其粘贴到我的JavaScript代码中。现在,我有了可打印字符长度的数组,可以实现get width函数。这是代码:
const LCARS_CHAR_SIZE_ARRAY = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 26, 46, 63, 42, 105, 45, 20, 25, 25, 47, 39, 21, 34, 26, 36, 36, 28, 36, 36, 36, 36, 36, 36, 36, 36, 27, 27, 36, 35, 36, 35, 65, 42, 43, 42, 44, 35, 34, 43, 46, 25, 39, 40, 31, 59, 47, 43, 41, 43, 44, 39, 28, 44, 43, 65, 37, 39, 34, 37, 42, 37, 50, 37, 32, 43, 43, 39, 43, 40, 30, 42, 45, 23, 25, 39, 23, 67, 45, 41, 43, 42, 30, 40, 28, 45, 33, 52, 33, 36, 31, 39, 26, 39, 55];
static getTextWidth3(text, fontSize) {
let width = 0;
let scaleFactor = fontSize/100;
for(let i=0; i<text.length; i++) {
width = width + LCARS_CHAR_SIZE_ARRAY[text.charCodeAt(i)];
}
return width * scaleFactor;
}
好吧,就是这样。蛮力,但在所有三个浏览器中都非常精确,我的沮丧感已降至零。不知道浏览器会持续多久,但是对于我来说,为我的SVG文本开发一种可靠的字体度量技术应该足够长。
SVG规范具有返回此信息的特定方法: getComputedTextLength()
var width = textElement.getComputedTextLength(); // returns a pixel number