简体   繁体   English

画布上的文字位置在FireFox和Chrome中是不同的

[英]Text position on canvas is different in FireFox and Chrome

I need to draw a text string at a precise position on HTML5 canvas. 我需要在HTML5画布上的精确位置绘制文本字符串。

Here's my test code : 这是我的测试代码

<!DOCTYPE html>
<html>
<body>
<canvas id="mainCanvas" width="320" height="240" style = "border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.
</canvas>
<script>
   window.onload = function() {
      var canvas = document.getElementById("mainCanvas");
      var ctx = canvas.getContext("2d");      
      ctx.textBaseline = "top";
      ctx.font = '100px Arial';
      ctx.textAlign = 'left';
      ctx.fillStyle = 'rgba(0, 0, 0, 255)';
      ctx.fillText('Test', 0, 0);
   }
</script>
</body>
</html>

The margin at the top is different in Chrome and Firefox: Chrome和Firefox顶部的边距不同: Chrome与Firefox中的文字

I'm going to draw other elements (eg images, shapes) on the canvas, and I need to make sure the text appears at the same position in all browsers. 我将在画布上绘制其他元素(例如图像,形状),并且我需要确保文本出现在所有浏览器中的相同位置。 Is it possible? 可能吗?

Cause 原因

As @iftah says: This mis-alignment is caused by a Firefox bug . 正如@iftah所说:这种错误对齐是由Firefox错误引起的。

Please add your voice to the Firefox's bug page so they fix it soon. 请将您的声音添加到Firefox的错误页面,以便他们尽快修复。

Workaround 解决方法

(Unfortunately), The workaround is to draw the text on a second canvas and scan that pixel data to find the topmost & leftmost pixel of the text. (不幸的是),解决方法是在第二个画布上绘制文本并扫描该像素数据以找到文本的最顶部和最左边的像素。

Then draw the text on the main canvas but pulled upward and leftward by the calculated pixel offsets. 然后在主画布上绘制文本,但是通过计算的像素偏移向上和向左拉动。

Here is annotated code and a Demo: 这是带注释的代码和演示:

 // canvas vars var canvas=document.getElementById("canvas"); var ctx=canvas.getContext("2d"); var cw=canvas.width; var ch=canvas.height; // test vars var text='Test'; var fontsize=100; var fontface='arial'; drawTextAtXY(0,0,text,fontsize,fontface,'black'); function drawTextAtXY(x,y,text,fontsize,fontface,fill){ // find the leftmost & topmost pixel of the text var minXY=getTextTop(text,fontsize,fontface); // set the font styles ctx.textBaseline='top'; ctx.font=fontsize+'px '+fontface; ctx.fillStyle=fill; // draw the text // Pull the text leftward and topward by minX & minY ctx.fillText(text,x-minXY.x,y-minXY.y); } function getTextTop(text,fontsize,fontface){ // create temp working canvas var c=document.createElement('canvas'); var w=canvas.width; var h=fontsize*2; c.width=w; c.height=h; var cctx=c.getContext('2d'); // set font styles cctx.textBaseline='top'; cctx.font=fontsize+'px '+fontface; cctx.fillStyle='red'; // draw the text cctx.fillText(text,0,0); // get pixel data var imgdata=cctx.getImageData(0,0,w,h); var d=imgdata.data; // scan pixel data for minX,minY var minX=10000000; var minY=minX; for(var y=0;y<h;y++){ for(var x=0;x<w;x++){ var n=(y*w+x)*4 if(d[n+3]>0){ if(y<minY){minY=y;} if(x<minX){minX=x;} } }} // return the leftmost & topmost pixel of the text return({x:minX,y:minY}); } 
 body{ background-color: ivory; } #canvas{border:1px solid red; margin:0 auto; } 
 <h4>Text drawn exactly at specified X,Y</h4> <canvas id="canvas" width=300 height=200></canvas> 

You can fix it easily. 你可以轻松修复它。

you can use textBaseline = "middle"; 你可以使用textBaseline =“middle”; and must use transform to 50px of top 并且必须使用变换到50px的顶部

means: 手段:

    <canvas id="mainCanvas" width="320" height="240" style = "border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.
    </canvas>
    <script>
    window.onload = function() {
          var canvas = document.getElementById("mainCanvas");
          var ctx = canvas.getContext("2d");      
          ctx.textBaseline = "middle";
          ctx.font = '100px Arial';
          ctx.textAlign = 'left';
          ctx.fillStyle = 'rgba(0, 0, 0, 1)';
          ctx.save();
          ctx.transform(1, 0, 0, 1, 0, 50);
          ctx.fillText('Test', 0, 0);
          ctx.restore();
       }
    </script>

A another bug is in your code: rgba(0, 0, 0, 255 ) fourth number in rgba must be between 0-1 for example 0.75. 甲另一个错误是在代码:RGBA(0,0,0,255)在第四RGBA数必须是0-1之间,例如0.75。

why I write .save() and .restore() ? 为什么我写.save()和.restore()? for reset transform and clear after use it. 用于重置转换并在使用后清除它。

Of course you can use 当然可以使用

ctx.fillText('Test', 0, 50);

Instead 代替

ctx.save();
ctx.transform(1, 0, 0, 1, 0, 50);
ctx.fillText('Test', 0, 0);
ctx.restore();

This appears to be a bug in Firefox dating back to 2012 and still not fixed! 这似乎是Firefox中可以追溯到2012年的一个错误,但仍然没有修复!

See https://bugzilla.mozilla.org/show_bug.cgi?id=737852 请参阅https://bugzilla.mozilla.org/show_bug.cgi?id=737852

Edit: Setting the baseLine to "alphabetic" (the default) results in both Chrome and Firefox having the same vertical location for the text. 编辑:将baseLine设置为“字母”(默认)会导致Chrome和Firefox具有相同的文本垂直位置。

Edit: Unfortunately, the vertical location isn't the only difference between Firefox and Chrome. 编辑:不幸的是,垂直位置并不是Firefox和Chrome之间的唯一区别。 Changing the string to "Testing" shows clearly that not only is the vertical location different, but also the space between the letters is slightly different - resulting in different width of the text. 将字符串更改为“测试”清楚地表明,不仅垂直位置不同,而且字母之间的空间也略有不同 - 导致文本的宽度不同。

If you really must have pixel perfect location AND size of the text maybe you should use Bitmap fonts 如果你真的必须有像素完美的位置和文本大小可能你应该使用位图字体

As stated in other answer it's some king of bug (or maybe just a different implementation). 正如其他答案中所述,它是bug的一个王者(或者可能只是一个不同的实现)。 textBaseline bottom and Y position to 100 can fix it. textBaseline bottom和Y位置为100可以修复它。

 <canvas id="mainCanvas" width="320" height="240" style = "border:1px solid #d3d3d3;"> Your browser does not support the HTML5 canvas tag. </canvas> <script> window.onload = function() { var canvas = document.getElementById("mainCanvas"); var ctx = canvas.getContext("2d"); ctx.textBaseline = "bottom"; ctx.font = '100px Arial'; ctx.textAlign = 'left'; ctx.fillStyle = 'rgba(150, 50, 0, 1)'; ctx.fillText('Test', 0, 100); } </script> 

In general: Use baseline bottom and increase Y position the font size amount 通常:使用基线底部并增加字体大小量的Y位置

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM