【问题标题】:Bug rendering text in canvas in Windows在 Windows 中的画布中渲染文本的错误
【发布时间】:2014-12-09 19:00:35
【问题描述】:

我正在制作一个在画布中使用文本渲染的应用程序,但遇到了一个奇怪的问题。我已经在许多计算机上进行了测试,它只发生在带有 Windows 的系统上。我来解释一下:

当我使用带有一些字体大小、填充颜色、文本笔划和斜体样式的 Times New Roman 时,一些字母显示笔划移位。

起初我认为这是我用于画布的库的问题,但我已经使用原生画布进行了测试,并且它也在发生。

这里是 jsfiddle:http://jsfiddle.net/ekm3o977/1/(记住它只发生在 Windows 中)

<body>
    <canvas id="myCanvas" width="1000" height="400"></canvas>
    <script>
      var canvas = document.getElementById('myCanvas');
      var context = canvas.getContext('2d');
      var x = 80;
      var y = 110;

      context.font = 'italic 70px Times New Roman';

      context.lineWidth = 1;
      // stroke color
      context.strokeStyle = 'red';
      context.fillStyle = 'blue';
      context.fillText('abcdefghijklmnñ', x, y);
      context.strokeText('abcdefghijklmnñ', x, y);
      context.fillText('opqrstuvwxyz', x, y+100);
      context.strokeText('opqrstuvwxyz', x, y+100);
    </script>
</body> 

关于如何解决的任何想法?谢谢

【问题讨论】:

  • 这里确认 Win8.1 IE11、Chrome39 和 FF33 上的位移。作为一种解决方法,您可以使用 webfont Times New Roman 代替系统字体。

标签: html canvas


【解决方案1】:

无法解决此问题的主要原因是子系统(浏览器与之交互)与此字体本身的内部问题。

不过,您可以尝试几种方法:

  1. 如 cmets 中所述,尝试使用它的网络字体版本(注意:requires license)。对于画布,您需要使用font-loader,以便在将文本绘制到画布之前知道字体何时正确加载。

  2. 我注意到问题在大小为 100 像素时消失了。我们可以使用它来制作一个包装函数来将其缩放到我们需要的大小。我在下面的解决方案中采取了一些妥协,例如降低基线和对齐。但是,如果需要,您可以使用它们进行扩展。

var ctx = canvas.getContext("2d");

ctx.fillStyle = "blue";
ctx.strokeStyle = "red";
ctx.lineWidth = 1;
ctx.font = "italic 70px Times New Roman";
ctx.textBaseline = "top";
ctx.fillText("This is native fillText/strokeText", 10, 10);
ctx.strokeText("This is native fillText/strokeText", 10, 10);

tnrWrapper(ctx, "This is wrapper function", 10, 80, 70, "italic");

function tnrWrapper(ctx, txt, x, y, size, style) {

  var width, hf = 1.1, // height factor
      tcanvas = document.createElement("canvas"),
      tctx = tcanvas.getContext("2d");

  style = style || ""; // italic, bold or nothing
  
  tctx.font = style + " 100px Times New Roman"; // fixed at 100px here  
  width = tctx.measureText(txt).width;
  
  tcanvas.width = width; // this will reset font, optionally set a fixed width
  tcanvas.height = 100*hf;  // todo: find a better proportional factor

  tctx.font = style + " 100px Times New Roman";  // new width resets context
  tctx.textBaseline = "top";
  tctx.textAlign = "start";  // rtl sensitive, or use left/right
  
  tctx.lineWidth = ctx.lineWidth * (100/size);   // scale line width
  tctx.fillStyle = ctx.fillStyle;
  tctx.strokeStyle = ctx.strokeStyle;

  tctx.fillText(txt, 0, 0);
  tctx.strokeText(txt, 0, 0);
  
  ctx.drawImage(tcanvas, x, y, width * (size/100), 100*hf * (size/100));
}
&lt;canvas id=canvas width=600 height=180&gt;&lt;/canvas&gt;

如您所见,我们现在得到了大致相同的大小,但没有对齐问题。

注意 1:字体的大小不是线性的。它们针对以不同尺寸显示进行了优化。这将影响实际宽度等,因此不要期望它们在所有尺寸下都相同。但它应该提供一个可行的解决方案,直到解决这个问题(这可能需要一段时间,因为它似乎是 Windows 中的系统级别)。

注意2:字体设置了两次。这是因为我们需要测量它并更新画布以匹配。当画布获得新的尺寸上下文时,会重置丢失设置的字体。您可以通过设置固定的画布宽度来避免这种情况。

希望这会有所帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-07-30
    • 2023-03-20
    • 1970-01-01
    • 2013-06-24
    • 2016-02-03
    • 1970-01-01
    • 2011-02-20
    • 2015-09-28
    相关资源
    最近更新 更多