HTML5 画布:绘制的换行旋转文本的自动字体大小
html5 canvas: auto font size for drawn wrapped rotated text
假设在旋转的边框内绘制文本(不与法轴 x-y 对齐),并且该文本也可以旋转,给定边界框的最大宽度,如何选择用于在HTML5 Canvas和JavaScript中在该边界框内绘制包装文本的最佳字体大小?
我知道这种方法:measureText() 可以测量给定字体大小的尺寸,但我需要相反:使用已知宽度来获取问题的字体大小。
谢谢
您不必找到字体磅值来使其适合。字体将根据当前转换比例平滑地向上和向下缩放。
您要做的就是measureText
找到它的textWidth
,从 context.font
属性中获取pointSize
,然后如果您有需要适合的框的width
和height
,然后找到width / textWidth
和height / pointSize
的最小值,并且您拥有渲染字体所需的比例。
作为函数
var scale2FitCurrentFont = function(ctx, text, width, height){
var points, fontWidth;
points = Number(ctx.font.split("px")[0]); // get current point size
points += points * 0.2; // As point size does not include hanging tails and
// other top and bottom extras add 20% to the height
// to accommodate the extra bits
var fontWidth = ctx.measureText(text).width;
// get the max scale that will allow the text to fi the current font
return Math.min(width / fontWidth, height / points);
}
参数是
- CTX 是要绘制到的当前上下文
- 为要绘制的文本发送文本
- 宽度以适合文本
- 高度以适合文本
返回使文本适合宽度和高度的比例。
该演示集成了所有内容,并绘制了随机框并填充了您问题的随机文本。它将字体选择和磅值与字体缩放分开,因此您可以看到它适用于任何字体和任何磅值。
var demo = function(){
/** fullScreenCanvas.js begin **/
var canvas = (function(){
var canvas = document.getElementById("canv");
if(canvas !== null){
document.body.removeChild(canvas);
}
// creates a blank image with 2d context
canvas = document.createElement("canvas");
canvas.id = "canv";
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
canvas.style.position = "absolute";
canvas.style.top = "0px";
canvas.style.left = "0px";
canvas.style.zIndex = 1000;
canvas.ctx = canvas.getContext("2d");
document.body.appendChild(canvas);
return canvas;
})();
var ctx = canvas.ctx;
/** fullScreenCanvas.js end **/
/** FrameUpdate.js begin **/
var w = canvas.width;
var h = canvas.height;
var cw = w / 2;
var ch = h / 2;
var PI2 = Math.PI * 2; // 360 to save typing
var PIh = Math.PI / 2; // 90
// draws a rounded rectangle path
function roundedRect(ctx,x, y, w, h, r){
ctx.beginPath();
ctx.arc(x + r, y + r, r, PIh * 2, PIh * 3);
ctx.arc(x + w - r, y + r, r, PIh * 3, PI2);
ctx.arc(x + w - r, y + h - r, r, 0, PIh);
ctx.arc(x + r, y + h - r, r, PIh, PIh * 2);
ctx.closePath();
}
// random words
var question = "Suppose that there is a text to be drawn inside a rotated bounding rectangle (not aligned to normal axes x-y), and that text can be also rotated, given the max width of the bounding box, how to select the best font size to use to draw a wrapped text inside that bounding box in html5 canvas and javascript? I know that method: measureText() can measure dimensions of give font size, but I need the inverse of that: using a known width to get the problem font size. thanks.";
question = question.split(" ");
var getRandomWords= function(){
var wordCount, firstWord, s, i, text;
wordCount = Math.floor(rand(4)+1);
firstWord = Math.floor(rand(question.length - wordCount));
text = "";
s = "";
for(i = 0; i < wordCount; i++){
text += s + question[i + firstWord];
s = " ";
}
return text;
}
// fonts to use?? Not sure if these are all safe for all OS's
var fonts = "Arial,Arial Black,Verdanna,Comic Sans MS,Courier New,Lucida Console,Times New Roman".split(",");
// creates a random font with random points size in pixels
var setRandomFont = function(ctx){
var size, font;
size = Math.floor(rand(10, 40));
font = fonts[Math.floor(rand(fonts.length))];
ctx.font = size + "px " + font;
}
var scale2FitCurrentFont = function(ctx, text, width, height){
var points, fontWidth;
var points = Number(ctx.font.split("px")[0]); // get current point size
points += points * 0.2;
var fontWidth = ctx.measureText(text).width;
// get the max scale that will allow the text to fi the current font
return Math.min(width / fontWidth, height / points);
}
var rand = function(min, max){
if(max === undefined){
max = min;
min = 0;
}
return Math.random() * (max - min)+min;
}
var randomBox = function(ctx){
"use strict";
var width, height, rot, dist, x, y, xx, yy,cx, cy, text, fontScale;
// get random box
width = rand(40, 400);
height = rand(10, width * 0.4);
rot = rand(-PIh,PIh);
dist = Math.sqrt(width * width + height * height)
x = rand(0, ctx.canvas.width - dist);
y = rand(0, ctx.canvas.height - dist);
xx = Math.cos(rot);
yy = Math.sin(rot);
ctx.fillStyle = "white";
ctx.strokeStyle = "black";
ctx.lineWidth = 2;
// rotate the box
ctx.setTransform(xx, yy, -yy, xx, x, y);
// draw the box
roundedRect(ctx, 0, 0, width, height, Math.min(width / 3, height / 3));
ctx.fill();
ctx.stroke();
// get some random text
text = getRandomWords();
// get the scale that will fit the font
fontScale = scale2FitCurrentFont(ctx, text, width - textMarginLeftRigth * 2, height - textMarginTopBottom * 2);
// get center of rotated box
cx = x + width / 2 * xx + height / 2 * -yy;
cy = y + width / 2 * yy + height / 2 * xx;
// scale the transform
xx *= fontScale;
yy *= fontScale;
// set the font transformation to fit the box
ctx.setTransform(xx, yy, -yy, xx, cx, cy);
// set up the font render
ctx.fillStyle = "Black";
ctx.textAlign = "center";
ctx.textBaseline = "middle"
// draw the text to fit the box
ctx.fillText(text, 0, 0);
}
var textMarginLeftRigth = 8; // margin for fitted text in pixels
var textMarginTopBottom = 4; // margin for fitted text in pixels
var drawBoxEveryFrame = 60; // frames between drawing new box
var countDown = 1;
// update function will try 60fps but setting will slow this down.
function update(){
// restore transform
ctx.setTransform(1, 0, 0, 1, 0, 0);
// fade clears the screen
ctx.fillStyle = "white"
ctx.globalAlpha = 1/ (drawBoxEveryFrame * 1.5);
ctx.fillRect(0, 0, w, h);
// reset the alpha
ctx.globalAlpha = 1;
// count frames
countDown -= 1;
if(countDown <= 0){ // if frame count 0 the draw another text box
countDown = drawBoxEveryFrame;
setRandomFont(ctx);
randomBox(ctx);
}
if(!STOP){ // do until told to stop.
requestAnimationFrame(update);
}else{
STOP = false;
}
}
update();
}
// demo code to restart on resize
var STOP = false; // flag to tell demo app to stop
function resizeEvent(){
var waitForStopped = function(){
if(!STOP){ // wait for stop to return to false
demo();
return;
}
setTimeout(waitForStopped,200);
}
STOP = true;
setTimeout(waitForStopped,100);
}
window.addEventListener("resize",resizeEvent);
demo();
/** FrameUpdate.js end **/
相关文章:
- 将Div内容复制到文本区域或具有相同字体族样式的文本
- 尝试在随机文本和图像脚本中添加样式/更改字体
- 用于更改链接文本的字体颜色的代码
- 如何按文本长度自动更改字体大小
- Javascript:是否可以在2D画布中为不同的文本设置不同的字体大小
- 文本框导致结构 JS 中的字体出现问题
- 用于根据用户改变文本区域的字体颜色的JavaScript'的选择
- 更改UIWebView中的文本字体大小-如何设置textFontSize的初始值
- 根据文本输入更改字体大小
- 如何在execCommand所见即所得编辑器中查找选定的文本字体大小和名称
- 增加了“上传”按钮的文本字体大小
- 如何在RaphaelJS中设置文本字体
- 在 Fabric.js 中使用远程 Web 字体初始化加载文本
- 使用 AngularJS 切换文本字体
- 与其他浏览器相比,如何在 safari 或 mac 中解决字体粗细、文本过于粗体的问题
- ThreeJS:Web GL 渲染器和 Canvas 渲染器之间的文本精灵字体大小差异
- Div 中的文本/字体大小在 Firefox 的打印模式下与在“正常”模式下不同
- 将字体文本转换为呈现的图形位图
- 包含自定义字体文本的元素的jQuery height()似乎不一致
- 服务器端预处理器为脆漂亮的字体/文本,如在photoshop