用于调整字体大小的数学逻辑
我有一个蓝色容器,它是我的文本的画布。我想做的是调整字体大小,以便整个文本尽可能多地填充蓝色容器。
我可以访问文本内容的高度,即段落和段落之间的行。另外,我还有蓝色容器的高度、每行的高度、行数和字数。
我尝试使用基于默认字体大小的行高和行数来确定我需要增加多少字体以填充蓝色容器。然而,这样做也会改变台词的数量,破坏我成功的机会,同时让我头晕目眩。
我应该使用什么公式才能使字体大小填充蓝色容器?
这是我的数字:
Content height: 342.46
Content/Container Width: 400
Font Size: 11
Line Height: 11 * 1.2 //120% of the font size gives the line height
Number of Lines: 24
Number of Words: 2055
另外,文本内容可能很长并且延伸到容器之外,因此理想情况下,我想要实现增加或减少字体大小的公式(或建议) 。
i have a blue container that is the canvas for my text. what i'm trying to do is resize the font so that the entire text fills as much of the blue container as it can.
i have access to the height of the text content, which is both paragraphs and the line in between them. also, i have the height of the blue container, the height of each line, the number of lines and the number of words.
i tried using the height of the line, based on a default font size, with the amount of lines to determine how much i need to increase the font so it would fill the blue container. however, doing so also changes the amount of lines, ruining my chances for success while making my head swim.
what formula should i use so the font size fills the blue container?
here are my numbers:
Content height: 342.46
Content/Container Width: 400
Font Size: 11
Line Height: 11 * 1.2 //120% of the font size gives the line height
Number of Lines: 24
Number of Words: 2055
also, it's possible for the text content to be long and to extend well past the container, so ideally a formula (or suggestions) for both an increase or reduction of the font size is what i'm trying to achieve.
alt text http://www.freeimagehosting.net/uploads/c1a4f77c5f.jpg
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
在 TeX 排版系统中,这个问题通常使用简单的二分算法(由 Knuth 在 The TeXbook 中提出)来解决,这里是一个伪 python:
请注意,如果不尝试每种尺寸,您可能无法做到这一点,因为每个浏览器都可能以不同的方式排版文本,制作不同的字间、字母间距;通过由用户设置最小字体大小(我见过很多网页因此而显示不正确),通过使用连字(现在可能不是,但将来有可能)。
这里的问题是网络浏览器可能会在每次尝试时重新绘制,因此这可能会很慢。您可以通过在计算时使框消失(fe display:none)来克服这个问题。我记得我曾经这样做过,甚至在 IE6 中也能工作。
In TeX typesetting system this problem is usually solved using a simple bisection algorithm (presented f.e. by Knuth in The TeXbook), here in a pseudo-python:
Note that you probably can't do this without experimenting with every size, as every browser might typeset your text in different way, making different interword, interletter spacing; by having a minimum font size set by user (I've seen lots of webpages displaying improperly because of this one), by using ligatures (probably not now, but in future it is possible).
The problem here is that the webbrowser will probably redraw every try, so this might be slow. You can overcome this by making the box disappear (f.e. display:none) for the time of computation. I remember I did that once and it worked even in IE6.
如果您可以使用固定宽度的字体,事情就会变得简单得多。然后诸如字距调整、不同的字符宽度等因素就会消失。
假设您不能(或不会)使用等宽字体,那么问题看起来很像重复浏览器所做的渲染或打印机驱动程序的“打印预览”功能。您可能会研究这种方法。
一个快速但肮脏的方案应该足够好可能是:
将
.
附加到文本末尾。 p>测量跨度相对于容器高度 (
ContainerHeight
) 的偏移量 (SpanOffset
)。将字体大小 (
FS
) 设置为:FS *= ContainerHeight / SpanOffset;
测量新的
SpanOffset
。如果
SpanOffset
仍然小于ContainerHeight
,则循环增加FS
一个微小的增量,直到SpanOffset
code> 离开容器,然后备份 1 增量。同样,如果
SpanOffset
位于ContainerHeight
之外,则循环减少FS
一个微小的增量,直到SpanOffset
> 只是进入容器。Things get a lot simpler, if you can use a fixed-width font. Then factors like: kerning, different character-widths, etc., disappear.
Assuming you can't -- or won't -- use a monospaced font, then the problem looks a lot like duplicating the rendering that a browser does -- or the "Print Preview" functionality of a printer driver. You might investigate that approach.
A quick and dirty scheme that should be good enough might be:
Append a
<span id="CanYouSeeMe">.</span>
to the end of the text.Measure the span's offset (
SpanOffset
) relative to the container height (ContainerHeight
).Set the font size (
FS
) to:FS *= ContainerHeight / SpanOffset;
Measure the new
SpanOffset
.If
SpanOffset
is still less than theContainerHeight
, IncreaseFS
a tiny increment, in a loop, untilSpanOffset
just leaves the container, then backup 1 increment.Likewise if
SpanOffset
was outside theContainerHeight
, DecreaseFS
a tiny increment, in a loop, untilSpanOffset
just enters the container.我认为这个问题没有完美的解决方案。
基本上,每行和段落末尾的“浪费”空间量很大程度上取决于相关文本。平均而言,字符宽度和字距调整会产生较小的差异(但在最坏的情况下会产生较大差异)。
所以你必须采取一些启发式的方法。如果可能的话,让您的软件“猜测”字体大小,测试文本是否合适(如何完成取决于您使用的语言/API),如果不合适,请稍微向上或向下调整。
这是一个可能的启发式:
textHeight 是文本包装到容器时预期的高度(以像素为单位)。您可以对字体大小进行二分搜索,以找到具有最佳估计高度的字体大小。
I don't think there is a perfect solution to this problem.
Basically, the amount of "wasted" space at the end of each line and paragraph depends very much on the text in question. Character widths and kerning cause minor differences on average (but major differences in the worst case).
So you have to go by some heuristic. If possible, have you software "guess" a font size, test if the text fits or not (how this is done depends on what language/API you're using), and if not, adjust up or down slightly.
Here's a possible heuristic:
textHeight is the height (in pixels) that the text is expected to take if wrapped to the container. You could binary search through your font sizes to find one with the best estimated height.
这实际上是一个相当困难的问题,因为换行符在单词边界处断开,并且单词长度各不相同,字符大小也确实如此。另外,您可以有任意数量的显式换行符。因此,要正确地做到这一点,需要考虑文本的许多细节,而一般的分析解决方案将是,嗯,相当复杂。
(在“真正的”排版中,还有很多技巧用于通过调整字母和单词间距来稍微调整布局,以便在保持良好外观的同时保持合适的外观,但我们当然不会涉及)
但是,让我们先把准确性放在一边,考虑一个简化的模型,它可能会帮助您进入正确的范围。
可用面积为
宽度*高度
。给定一段给定长度
的文本,我们希望确定合适的fontsize
,使得文本的换行高度接近height
。暂时,让我们忽略单位的所有细节和文本内容的变幻莫测,并想象我们可以仅根据
length
和fontsize
:其中
A
和B
是一些缩放常数。 (B
应该很容易计算,实际上您将其设置为 1.2。A
有点棘手,取决于您选择如何测量长度
,例如作为字符数或数字或单词数,A
只能是一个近似值,但如果您正在处理合理数量的表现良好的文本,则该近似值。可以相当不错。)那么文本占用的区域是:
将其设置为等于可用区域,为我们提供了字体大小的上限,即:
显然,这将显着高估,因为它假设文本包完美,这就是不会——即使没有明确的换行符,行尾和屏幕底部也会丢失区域。然而,通过在我们的缩放常数
A
中加入适当的模糊因子(即,通过增加我们估计的文本宽度以包含丢失的区域),我们很可能可以获得足够好的fontsize< /code> 一起去。
我们可以通过考虑文本的更多细节来使分析更加复杂。例如,如果您计算文本中硬换行符的数量,您可以将它们视为单独的,因为它们会增加高度而不增加宽度。这会产生一个稍微复杂的二次方程,您需要二次公式来求解一个简单的平方根。这是否值得可能主要取决于您正在处理的文本中显式换行率的变化有多大。
另一件需要注意的事情是,您通常可以通过仅调整行间距来作弊,因为这允许您更改垂直跨度,而不会冒任何文本回流的风险。您可能不想大量这样做,因为这看起来很愚蠢。但是,如果您的换行正确,但文本没有完全到达底部,那么添加一点垂直填充当然值得考虑。
This is actually rather a difficult problem, because the lines break at word boundaries and word lengths vary, as indeed do character sizes. Plus, you can have an arbitrary number of explicit linebreaks. So to do it properly requires taking into account a lot of the specifics of the text, and a general analytic solution will be, um, quite complicated.
(In "real" typography, there are also a bunch of tricks that are used to fiddle the layout a bit by adjusting the letter and word spacing so that things fit while maintaining a decent appearance, but we're certainly not going to get into that here.)
However, let's put aside exactness and instead consider a simplified model that might help get you into the right ballpark.
The area available is
width * height
. Given a piece of text of a givenlength
, we want to determine a suitablefontsize
such that the wrapped height of the text is close toheight
.For the time being, let's just gloss over all details of units and the vagaries of the text content and imagine that we can calculate the overall size of the text from just
length
andfontsize
:where
A
andB
are some scaling constants. (B
should be easy to calculate, and indeed you have it as 1.2.A
is a little trickier and depends on how you choose to measurelength
, eg as number of characters or number or words. However you do it,A
can only ever be an approximation, but if you're dealing with reasonable quantities of reasonably well-behaved text then the approximation can be pretty good.)Then the area occupied by the text is:
Setting this equal to the available area gives us an upper limit for the fontsize, ie:
Clearly this is going to overestimate significantly because it assumes the text packs perfectly, which it doesn't -- there will be area lost at the end of lines and at the bottom of the screen, even in the absence of explicit line breaks. However, it's quite likely that by putting an appropriate fudge factor into our scaling constant
A
(ie, by upping our estimated text width to include the lost areas) we can get a good enoughfontsize
to be going along with.We can make the analysis more sophisticated by taking into account more specifics of the text. For example, if you count the number of hard line breaks in the text you can treat those as separate, since they add height without adding width. This gives rise to a slightly more complicated quadratic equation that you'll need the quadratic formula to solve rather just a simple square root. Whether this is worthwhile probably depends mostly on how much variation there is in the rate of explicit linebreaks in the texts you're dealing with.
One other thing to note is that you can often cheat a bit by adjusting only the line spacing, since this allows you to change the vertical span without risking any reflow of the text. You probably don't want to do this by large amounts, because it will look silly. But it's certainly worth considering adding a little bit of vertical padding if you've got the wrapping about right but the text doesn't quite reach the bottom.