确定 HTML5 画布中字符串的宽度
Determine width of string in HTML5 canvas
我正在HTML5画布上的图像(模因生成器)上绘制文本。我想计算字体大小,以便字符串将跨越画布的整个宽度。
所以基本上,JavaScript 中有没有办法确定我应该为给定宽度的某种字体的某个字符串使用什么字体大小?
fillText()
方法有一个可选的第四个参数,它是呈现字符串的最大宽度。
MDN的文档说...
最大宽度
但是,在可选;要绘制的最大宽度。 如果指定,则字符串为计算为比此宽度更宽,字体调整为使用更水平压缩的字体(如果有的话,或者如果合理可读的可以通过缩放当前字体来合成水平)或较小的字体。
撰写本文时,此参数在跨浏览器上没有得到很好的支持,这导致第二个解决方案使用 measureText()
来确定字符串的尺寸而不呈现它。
var width = ctx.measureText(text).width;
这是我可以做到的...
var canvas = document.getElementById('canvas'),
ctx = canvas.getContext('2d');
// Font sizes must be in descending order. You may need to use `sort()`
// if you can't guarantee this, e.g. user input.
var fontSizes = [72, 36, 28, 14, 12, 10, 5, 2],
text = 'Measure me!';
// Default styles.
ctx.textBaseline = 'top';
ctx.fillStyle = 'blue';
var textDimensions,
i = 0;
do {
ctx.font = fontSizes[i++] + 'px Arial';
textDimensions = ctx.measureText(text);
} while (textDimensions.width >= canvas.width);
ctx.fillText(text, (canvas.width - textDimensions.width) / 2, 10);
jsFiddle。
我有一个按降序排列的字体大小列表,我遍历列表,确定渲染的文本是否适合画布尺寸。
如果是这样,我将文本中心对齐。如果必须在文本的左侧和右侧使用填充(看起来会更好),请在计算文本是否适合时将填充值添加到textDimensions.width
。
如果您有很长的字体大小列表要尝试,则最好使用二进制搜索算法。但是,这将增加代码的复杂性。
例如,如果您有 200 种字体大小,则通过数组元素的线性 O(n) 迭代可能会非常慢。
二进制斩波应为 O(log n)。
这是函数的内涵。
var textWidth = (function me(fontSizes, min, max) {
var index = Math.floor((min + max) / 2);
ctx.font = fontSizes[index] + 'px Arial';
var textWidth = ctx.measureText(text).width;
if (min > max) {
return textWidth;
}
if (textWidth > canvas.width) {
return me(fontSizes, min, index - 1);
} else {
return me(fontSizes, index + 1, max);
}
})(fontSizes, 0, fontSizes.length - 1);
jsFiddle。
-
写下所有你想要的文本。( 例如。
ctx.font
) -
在编写实际文本之前,请使用
ctx.measureText("myText").width
来获取文本的宽度,因为我们是在对ctx进行更改后调用的,因此每次更改ctx属性(例如字体)时都会有所不同 -
现在我们将从中间扩展它。
ctx.translate(midPoint_X_Of_Text, midPoint_Y_Of_Text); ctx.scale(desiredWidth/measuredWidth, desiredWidth/measuredWidth); ctx.translate(-midPoint_X_Of_Text, -midPoint_Y_Of_Text);
-
ctx.fillText()
或ctx.strokeText()
编写文本 -
通过
ctx.save()
和ctx.restore()
或像setTransform()
一样手动撤消所有更改
var can = document.getElementById('myCan');
var ctx = can.getContext("2d");
var desiredWidth = can.width;
var myText = "Hello How Are You?"
function draw(){
ctx.font = can.height/2 + "px verdana";
ctx.fillStyle = "red";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
let measuredWidth = ctx.measureText(myText).width;
let ratio = desiredWidth/measuredWidth;
ctx.translate(can.width/2,can.height/2);
ctx.scale(ratio,ratio);
ctx.translate(-can.width/2,-can.height/2);
ctx.fillText(myText,can.width/2,can.height/2);
ctx.setTransform();
}
draw();
let myInput = document.getElementById('myInput');
myInput.addEventListener('input',(e)=>{
ctx.clearRect(0,0,can.width,can.height);
myText = myInput.value;
draw();
})
<html>
<body>
<center>
<input id="myInput" value="Hello How Are You?"/><br>
<canvas id="myCan" height="300" width=300 style="border:black solid 2px;">
</canvas>
</center>
</body>
</html>
我有下一个代码,它非常适合我。也许有一点错误,但我不需要字体大小列表。我只是用字体大小获得宽度,如果它太大,我会根据画布宽度和填充(50)计算比例大小
ctx.font = FONT_SIZE+"pt Verdana";
var textWidth = ctx.measureText(markText).width;
if(textWidth > canvas.width - 50) {
ctx.font = parseInt(FONT_SIZE*(canvas.width-50)/textWidth)+"pt Verdana";
textWidth = ctx.measureText(markText).width;
}
ctx.textBaseline = "middle";
ctx.fillStyle = "rgba(255,255,255,0.5)";
ctx.strokeStyle = "rgba(0,0,0,0.5)";
var xT = image.width / 2 - textWidth / 2;
var yT = image.height / 2;
ctx.fillText(markText, xT, yT);
ctx.strokeText(markText, xT, yT);
使用第二个临时 canvas2D
function determineWidth(text, font) {
var textCtx = document.createElement("canvas").getContext("2d");
textCtx.font = font
let measure = textCtx.measureText(text);
let fontHei = parseInt(font.slice(0, font.indexOf("px")))
return [measure.width,fontHei]
}
在创建真实画布之前使用它
let font = `40px monospace`;
let [wid,hei]=determineWidth(text,font)
let textAlign = "center";
let textBaseline = "middle";
let fillStyle = "black";
var textCtx = document.createElement("canvas").getContext("2d");
textCtx.canvas.width = wid;
textCtx.canvas.height = hei;
textCtx.font = font
textCtx.textAlign = textAlign
textCtx.textBaseline = textBaseline
textCtx.fillStyle = fillStyle
textCtx.clearRect(0, 0, textCtx.canvas.width, textCtx.canvas.height);
textCtx.fillText(text, textCtx.canvas.width / 2, textCtx.canvas.height / 2);
- 到UpperCase字符串Javascript中的特定字符索引
- JSON解析字符串文本中的双引号
- 在字符串列表中搜索任何出现的单词,如果单词的第一个字符匹配,则高亮匹配单词.Javascript正则表达式
- 替换字符串javascript中的所有特殊字符..
- 停止JSON.parse()从JSON字符串数据中删除尾随零
- 从字符串 JavaScript 中过滤多个正则表达式
- 在字符串 JavaScript 中使用正则表达式替换
- 从包含另一个函数的字符串变量中返回一个函数
- 忽略字符串javascript中的字符
- 计算字符串javascript中的某些单词
- 如何在ReactNative项目中将本地文本文件加载到字符串变量中
- 从字符串javascript中获取键值对
- JavaScript字符串串联中null的影响
- Angularjs:字符串变量中的Html值
- 在字符串Javascript中查找丢失的字母
- 替换字符串 JavaScript 中的多个文本
- 在字符串匹配中忽略
- 在字符串 jquery 中添加空格
- JavaScript 警报函数如何在 Web 浏览器上的 java 字符串变量中工作
- 检查另一个字符串 JavaScript 中一个字符串是否有任何字符的最佳方法