- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
假设有一个文本要在旋转的边界矩形内绘制(不与法线轴 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);
}
参数是
返回在宽度和高度范围内适合文本的比例。
该演示将所有内容集成在一起,它会绘制随机框并填充问题中的随机文本。它将字体选择和磅值与字体缩放分开,因此您可以看到它适用于任何字体和任何磅值。
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 **/
关于javascript - html5 Canvas : auto font size for drawn wrapped rotated text,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34899911/
我创建了一个包含社交图标的列表。这些图标应该环绕在小屏幕上。 我使用 flex-wrap: wrap; 它在 Firefox 和 Chrome 中完美运行: 但是 Internet Explorer
我很惊讶地发现我的 white-space: pre-wrap;文本在 > 换行和 "人物。我以为它只会换行,- , 以及一个或多个空格之后。 这是一个fiddle . 它在" 之后换行, 在
我被分配了重新创建以下网站的任务:https://plantanapp.com/learn 我做了一些事情,但是每次我解决一个问题时,都会出现另外两个问题。 我是HTML和CSS的新手,并不真正了解元
我偶然发现了 jQuery 的 wrap() 函数。 当我试图包装两个 div 标签时,它们之间有一些文本,而不是两个 div 之间没有文本时,它的行为不知何故不同。 j查询: var wrapper
我正在尝试在 w3c css 验证器上验证一个 css 文件。当它被测试时,它返回一个错误,指出 “属性 flex-wrap- 不存在:wrap”。这是我 css 验证器认为错误的部分。 .row {
这个问题在这里已经有了答案: Flex items create space between them when they wrap [duplicate] (1 个回答) 关闭 6 年前。 我正在
我正在制作一个网页,其中的标题有一个主要主题和一个描述符,每个都包含在标签中。 我已经查找了 标签,它似乎只在你有长字符串时才有效没有空格。但是我在文本中断断续续地有空格。 我需要的是我可以在两个元
我听到很多关于 wrap 面板加载速度较慢的消息,因此我们需要一个虚拟化面板。 有人可以给我一个小的环绕面板示例,它可以证明加载速度较慢等它需要一个虚拟面板。 我设置了一个环绕面板作为列表框的面板控件
我需要用 sinon 多次包装一个方法,以便能够根据参数返回不同的对象。我该怎么做? 我要测试的 Controller 看起来像这样: const servicePackagesOfferingRep
我在运行测试时收到了上述错误消息。下面是我的代码(我正在使用 Backbone JS 和 Jasmine 进行测试)。有谁知道为什么会这样? $(function() { describe("Ca
问题是关于.text-wrapper,它有display:flex; flex-wrap:wrap 应用于它。使用 flex-wrap:wrap 的原因是,否则 .text-wrapper 和 .ta
我有三个带有 Bootstrap 3 的 DIV 容器,其中前两个在第一行,第三个在下一行,直到浏览器宽度直到 991 px。高于 992 px,所有三个容器应排成一行。每行容器的高度应该是最高的 (
(我使用的是 Chrome v.39+) 我正在尝试使用 flex-wrap 属性水平和垂直堆叠子 div,但我看到了一些非常奇怪的行为。例如,如果有 3 个子 div,最后一个的宽度为 100%(使
我必须这样做。适用于宽屏、中屏和小屏 https://pp.vk.me/c629328/v629328337/21bd7/izp9QG8Qcg4.jpg 这是我的代码 .section-items-c
我想要一个每行 3 个元素的容器 flex div,问题是当我添加第四个元素时(它应该自动换行到第二行),而不是它停留在一行并缩小其他元素。我启用了 flex-wrap: wrap; 这是我的代码:
假设我正在使用一个带有 flex-direction:row 和 flex-wrap:wrap 的 flexbox 容器。 根据浏览器窗口的大小,每行中可能有 2、3、4 或更多项。 我想在每隔一行的
我已经添加了所有属性。当我更改浏览器宽度时,它们开始相互粘连,这是因为我有太多图像而无法正常工作? 无法将图像换行: #skills>div { margin-top: 80px; displ
我想制作一个网格,其中每行有两张图片。我正在使用 flex-wrap: wrap;它在 android 4.4+ 上运行良好,但不适用于低于 android 4.4 的系统。我想在不使用 flex-w
我的网站出现异常行为。我最近在网站管理员工具上发现,它发现我网站上的许多网页都出现抓取错误 404。我无法理解这些页面是如何创建的,因为所有 404 页面最后都包含这几个字 wrap-function
我正在使用 MongoDB C# 驱动程序构建一些更新语句。 The C# API在 Builder 命名空间中包括 Wrapped 和“Un-Wrapped”方法。 从表面上看,这些似乎因泛型不同而
我是一名优秀的程序员,十分优秀!