繁体   English   中英

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

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

我需要在HTML5画布上的精确位置绘制文本字符串。

这是我的测试代码

<!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顶部的边距不同: Chrome与Firefox中的文字

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

原因

正如@iftah所说:这种错误对齐是由Firefox错误引起的。

请将您的声音添加到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> 

你可以轻松修复它。

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

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

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

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

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

如果你真的必须有像素完美的位置和文本大小可能你应该使用位图字体

正如其他答案中所述,它是bug的一个王者(或者可能只是一个不同的实现)。 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> 

通常:使用基线底部并增加字体大小量的Y位置

暂无
暂无

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

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