Determine width of string in HTML5 canvas

匿名 (未验证) 提交于 2019-12-03 09:13:36

问题:

I'm drawing text in an HTML5 canvas on top of an image (a meme generator). I want to calculate a font size so that the string will span the entire width of the canvas.

So basically, is there a way in JavaScript to determine what font size I should use for some string of a certain font for a given width?

回答1:

The fillText() method has an optional fourth argument, which is the max width to render the string.

MDN's documentation says...

maxWidth

Optional; the maximum width to draw. If specified, and the string is computed to be wider than this width, the font is adjusted to use a more horizontally condensed font (if one is available or if a reasonably readable one can be synthesized by scaling the current font horizontally) or a smaller font.

However, at the time of writing, this argument isn't supported well cross browser, which leads to the second solution using measureText() to determine the dimensions of a string without rendering it.

var width = ctx.measureText(text).width; 

Here is how I may do it...

jsFiddle.

I have a list of font sizes in descending order and I iterate through the list, determining if the rendered text will fit within the canvas dimensions.

If it will, I render the text center aligned. If you must have padding on the left and right of the text (which will look nicer), add the padding value to the textDimensions.width when calculating if the text will fit.

If you have a long list of font sizes to try, you'd be better off using a binary search algorithm. This will increase the complexity of your code, however.

For example, if you have 200 font sizes, the linear iteration through the array elements will be O(n).

The binary chop should be O(log n).

Here is the guts of the function.

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.



回答2:

I have the next code and it works perfectly for me. Maybe there is a little error but I don't need to have a list of font sizes. I just get the width with a font size and if it is too big I calculate a proportional size depending of the canvas width and padding (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); 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!