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

时间:2016-03-11 03:44:40

标签: javascript html5 google-chrome firefox 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>

Chrome和Firefox顶部的边距不同: Text in Chrome vs Firefox

我将在画布上绘制其他元素(例如图像,形状),我需要确保文本出现在所有浏览器中的相同位置。有可能吗?

4 个答案:

答案 0 :(得分:10)

<强>原因

正如@iftah所说:这种错位是由Firefox bug引起的。

请将您的声音添加到Firefox的错误页面,以便他们尽快解决。

解决方法

(不幸的是),解决方法是在第二个画布上绘制文本并扫描该像素数据以找到最顶层的&amp;最左边的文字像素。

然后在主画布上绘制文本,但是通过计算的像素偏移向上和向左拉动。

以下是带注释的代码和演示:

// 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>

答案 1 :(得分:3)

您可以轻松修复它。

你可以使用textBaseline =“middle”; 并且必须使用变换到50px的顶部

表示:

    <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>

您的代码中还有另一个错误:rgba(0,0,0, 255 ) rgba中的第四个数字必须介于0-1之间,例如0.75。

为什么我写.save()和.restore()? 用于重置变换并在使用后清除。

当然可以使用

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

相反

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

答案 2 :(得分:2)

这似乎是Firefox中可以追溯到2012年的一个错误,但仍然没有修复!

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

编辑: 将baseLine设置为“alphabetic”(默认值)会导致Chrome和Firefox具有相同的文本垂直位置。

编辑: 不幸的是,垂直位置并不是Firefox和Chrome之间的唯一区别。将字符串更改为“测试”清楚地表明,不仅垂直位置不同,而且字母之间的空间也略有不同 - 导致文本的宽度不同。

如果你真的必须有像素完美的位置和文字大小,你可以使用Bitmap fonts

答案 3 :(得分:2)

如其他答案中所述,它是一些bug的王者(或者可能只是一个不同的实现)。 textBaseline bottom和Y位置可以修复它。

&#13;
&#13;
<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>
&#13;
&#13;
&#13;

一般情况下:使用基线底部并将字体大小增加Y位置