Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/82.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 确定HTML5画布中字符串的宽度_Javascript_Html_Text_Canvas_Fonts - Fatal编程技术网

Javascript 确定HTML5画布中字符串的宽度

Javascript 确定HTML5画布中字符串的宽度,javascript,html,text,canvas,fonts,Javascript,Html,Text,Canvas,Fonts,我在HTML5画布上的图像(一个模因生成器)上绘制文本。我想计算一个字体大小,这样字符串将跨越画布的整个宽度 因此,基本上,JavaScript中有没有一种方法可以确定对于给定宽度的特定字体的某个字符串,我应该使用什么字体大小?该方法有一个可选的第四个参数,即渲染字符串的最大宽度 MDN的文件说 maxWidth 可选;要绘制的最大宽度。如果指定,则为 计算为比此宽度宽,字体将调整为使用 更多水平压缩字体(如果有或 通过缩放当前字体,可以合成可读性较好的字体 (水平)或更小的字体 但是,在编写本

我在HTML5画布上的图像(一个模因生成器)上绘制文本。我想计算一个字体大小,这样字符串将跨越画布的整个宽度

因此,基本上,JavaScript中有没有一种方法可以确定对于给定宽度的特定字体的某个字符串,我应该使用什么字体大小?

该方法有一个可选的第四个参数,即渲染字符串的最大宽度

MDN的文件说

maxWidth

可选;要绘制的最大宽度。如果指定,则为 计算为比此宽度宽,字体将调整为使用 更多水平压缩字体(如果有或 通过缩放当前字体,可以合成可读性较好的字体 (水平)或更小的字体

但是,在编写本文时,跨浏览器不支持此参数,这导致了第二种解决方案,即使用来确定字符串的尺寸,而不渲染它

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);​

我有一个按降序排列的字体大小列表,并遍历该列表,确定渲染文本是否适合画布尺寸

如果需要,我将使文本中心对齐。如果必须在文本的左右两侧添加填充(这样看起来会更好),请在计算文本是否适合时,将填充值添加到
textdimmensions.width

如果你有一长串的字体大小要尝试,你最好使用一个。然而,这将增加代码的复杂性

例如,如果您有200种字体大小,那么通过数组元素的线性O(n)迭代可能会非常慢

二进制印章应该是O(logn)

下面是函数的核心

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);

.

我有下一个代码,它非常适合我。可能有一点错误,但我不需要有一个字体大小的列表。我只是用字体大小来计算宽度,如果太大,我会根据画布的宽度和填充(50)来计算比例大小

  • 写下所有你想要的文字。(例如,
    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=罐宽;
    var myText=“你好吗?”
    函数绘图(){
    ctx.font=can.height/2+“px verdana”;
    ctx.fillStyle=“红色”;
    ctx.textAlign=“中心”;
    ctx.textb基线=“中间”;
    设measuredWidth=ctx.measureText(myText).width;
    let比率=所需宽度/测量宽度;
    ctx.平移(罐宽/2,罐高/2);
    ctx.比例(比率、比率);
    ctx.translate(-can.width/2,-can.height/2);
    ctx.fillText(myText,can.width/2,can.height/2);
    ctx.setTransform();
    }
    draw();
    让myInput=document.getElementById('myInput');
    myInput.addEventListener('input',(e)=>{
    ctx.clearRect(0,0,罐宽,罐高);
    myText=myInput.value;
    draw();
    })
    
    

    我早该知道,如果不按以下步骤操作,您将无法获得90k+的销售代表。:)非常好。我正试图在通过文本字段的
    onkeyup
    属性运行的函数中使用它,每当我在字段中键入内容时,我的浏览器就会冻结,必须强制退出。有什么想法吗?@edc1591你能用小提琴演示一下吗?可能
    do/while
    循环的表达式的计算结果永远不会为true。看起来我只是将代码粘贴到了js文件中的错误位置。它正在工作。二进制搜索算法也非常有效,非常感谢!我认为,在这段时间里,似乎会永远循环。我不确定当字体为
    “undefinedpx Arial”
     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);