我正在创建一个在画布中使用文本渲染的应用程序,但我遇到了一个奇怪的问题。我已经在许多计算机上进行了测试,它只发生在使用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>
有关如何解决的任何想法?感谢
答案 0 :(得分:1)
导致此问题的主要原因无法解决,因为子系统(浏览器与之交互)的内部问题本身就存在问题。
你可以试试几种方法:
如评论中所述,请尝试使用它的网络字体版本(注意:requires license)。对于画布,您需要使用font-loader,以便在将文本绘制到画布之前知道字体何时正确加载。
我注意到问题在100px的大小完全消失了。我们可以使用它来创建一个包装函数来将其缩放到我们需要的大小。我在下面的解决方案中采取了一些妥协措施,例如降低基线和对齐方式。但是,如果需要,可以使用它们进行扩展。
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));
}
<canvas id=canvas width=600 height=180></canvas>
正如您所看到的,我们现在得到大致相同的尺寸但没有对齐问题。
注1:字体的大小不是线性的。它们针对各种尺寸进行了优化。这会影响实际宽度等。所以不要指望它们在所有尺寸上都是相同的。但是它应该提供一个可行的解决方案,直到解决了这个问题(这可能需要一段时间,因为它似乎是Windows中的系统级别)。
注2:字体设置两次。这是因为我们需要测量它并更新画布以匹配。当canvas获取新的维度上下文时,重置丢失设置的字体。您可以通过设置固定宽度的画布来避免这种情况。
希望这有帮助!