调整文本大小会忽略小数



我在文本大小调整功能时遇到问题,我为一个项目制作了。其目的是调整许多文本行的大小,以便它们在 400 像素内向上、向左和向右对齐。

问题与此类似:使用 JS 更改字体大小时忽略十进制,但存在一些差异。作者一直在使用像素 - 解决方案是使用其他东西,因为浏览器并不总是支持单个像素的划分。我使用积分。由于库文件大小,我也不能使用jQuery。

下面是调整大小的代码。它的工作原理是这样的:

如果文本宽度(跨度)小于边界框架,则递增 字体大小为1/10。

var textobject = document.getElementById(theText);
var currentFontsize = parseFloat(window.getComputedStyle(textobject, null).getPropertyValue('font-size'));
while (textobject.offsetWidth < 400) {
    currentFontsize += .1;
    console.log("Width: "+textobject.offsetWidth+ " using fontsize: "+currentFontsize);
    textobject.style.fontSize = currentFontsize+"pt";
}

以下是我的观察:

  • 它适用于我的浏览器;IE,Chrome和Firefox(全部更新)。
  • 它几乎可以在我朋友的IE,Chrome和Firefox(全部更新)中使用。宽度最多错误 6-7 像素。
  • 它在Mac/Safari上不能令人满意。在这里,对齐方式偏离了 13-15 像素。

我在控制台中偷看了一下,这些是我的观察结果:

Width: 372 using fontsize: 16.1
Width: 372 using fontsize: 16.2
Width: 390 using fontsize: 16.3
Width: 390 using fontsize: 16.4
Width: 390 using fontsize: 16.5
Width: 390 using fontsize: 16.6

如您所见,它从 372 跳到 390,而无需设置适当的字体大小。令我困惑的是,它在不同的机器上的工作方式如此不同。关于如何解决这个问题的任何想法,非常感谢!


更新:我已经放弃了自动调整字体大小的事情,而是使用 GD 库,以便所有文本都存储在单个位图中。看起来很有希望,但仍存在一些问题

由于字体的性质,字体通常不会线性缩放 - 它们在某些大小(1,尤其是面向屏幕的字体(2)下进行了优化(除非字体质量低)。

即使您增加字体大小,它也只能略微增加高度,但不一定是宽度或重量,或 vica verca 等 - 因此它在任何尺寸下看起来都很好和清晰,尤其是由于屏幕的分辨率相对较低,屏幕尺寸较小。

浏览器中的各种字体引擎将以同样不同的方式处理此问题,并尝试使用最接近优化大小的字体,以便字体看起来清晰(对于较大的尺寸,这通常不是问题,但对于较小的尺寸)。不过,它也在很大程度上取决于字体。

目前,使用较小的字体大小进行此级别控制的唯一方法是使用较大的尺寸将文本绘制到位图(即画布),并将该位图缩放到所需的确切大小(失去选择功能等)。但仍然容易出现抗锯齿等问题。

如果使用点指定字体大小,则大小将根据系统的 DPI 转换为像素:

sizeInPixels = 72 / systemDPI * sizeInPoints  (ie. 72 / 96 * 16 = 12 pixels)
像素

本质上是整数,但结果可能会有所不同,具体取决于浏览器的字体引擎处理子像素化的方式。

更新

我又给了它一轮,并提出了一个简单的可能的解决方案,不过,它没有使用各种字体进行测试,所以我不能保证它按预期 100% 工作,但这通过缩放转换而不是首先缩放预填充位图来使用上述原理。

var ctx = canvas.getContext('2d'),
    w = canvas.width,
    lines = [
      "THIS IS HEADLINE",
      "AND THIS IS SPARTA",
      "UNDERLINE",
      "How about a little longer line?"
    ],
    //we have to guess font height as TextMetrics object is not fully implemented
    th = 30;
// setup text
ctx.font = "32px sans-serif";
for(var i = 0, line; line = lines[i]; i++) {
  var tw = ctx.measureText(line).width, // measure width of text in pixels
      s = w / tw;                       // scale based on canvas and text width
  
  ctx.translate(0, th*s);               // move line down, font heigh x scale
  ctx.scale(s, s);                      // scale canvas
  ctx.fillText(line, 0, 0);             // draw text at this scale
  ctx.scale(1/s, 1/s);                  // reset scale
}
#canvas{border:1px solid red}
<canvas width=500 height=240 id=canvas></canvas>


1)大小通常是指字体上方的高度,不一定只对应于字体的可见部分,还包括任何空白区域。
2)在印刷界,这通常不是问题,因为印刷品具有更高的分辨率。

最新更新