【问题标题】:Text position on canvas is different in FireFox and Chrome画布上的文本位置在 FireFox 和 Chrome 中不同
【发布时间】:2016-06-26 04:49:48
【问题描述】:

我需要在 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 中是不同的:

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

【问题讨论】:

  • 可能问题出在我更改时的文本大小,尽管我尝试在下面使用它,但它可以正常工作 ctx.font = "50px Verdana"; ctx.fillStyle = 'rgba(0, 0, 0, 255)'; ctx.fillText("测试", 10, 50);
  • @cracker 我尝试按照您的建议更改字体,但相对于画布顶部的文本位置在 Chrome 和 Firefox 中仍然不同
  • 我尝试过使用 ctx.textBaseline = "alphabetic"; ctx.fillText('测试', 10, 100);您需要手动设置参数的地方。它可能会对您有所帮助!

标签: javascript html google-chrome firefox html5-canvas


【解决方案1】:

原因

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

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

解决方法

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

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

这是带注释的代码和演示:

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

【讨论】:

  • 虽然我创建了 chrome 页面的大图像并使用图像映射加载它会做很多工作......
  • @ThrowingDwarf。是的,浏览器兼容===好,(浏览器不兼容||浏览器故障)===PITA。 :-)
  • 一些关于这个的更新,(错误报告终于复活了:-)):实际上可能是其他浏览器中的错误bugzilla.mozilla.org/show_bug.cgi?id=737852#c20
【解决方案2】:

您可以轻松修复它。

你可以使用 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();

【讨论】:

    【解决方案3】:

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

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

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

    编辑: 不幸的是,垂直位置并不是 Firefox 和 Chrome 之间的唯一区别。将字符串更改为“Testing”可以清楚地看出,不仅垂直位置不同,而且字母之间的间距也略有不同——导致文本宽度不同。

    如果你真的必须有像素完美的位置和文本大小,也许你应该使用Bitmap fonts

    【讨论】:

      【解决方案4】:

      正如其他答案中所述,它是一些错误之王(或者可能只是不同的实现)。 textBaseline底部和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>

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-02-28
        • 2014-01-26
        • 1970-01-01
        • 1970-01-01
        • 2021-06-23
        • 2012-03-26
        • 1970-01-01
        • 2012-12-10
        相关资源
        最近更新 更多