Text position on canvas is different in FireFox and Chrome

I need to draw a text string in exact position on an HTML5 canvas.

Here is 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 limit at the top is different from Chrome and Firefox: Text in Chrome vs Firefox

I am going to draw other elements (like images, shapes) on the canvas, and I need to make sure that the text is displayed at the same position in all browsers. Is it possible?

+5
source share
4 answers

Cause

As @iftah reports: This misalignment is caused by a Firefox error.

Please add your vote to the Firefox error page to quickly fix it.

Bypass

(Unfortunately). The workaround is to draw the text on the second canvas and scan this pixel data to find the top and leftmost pixel of the text.

Then draw the text on the main canvas, but drag up and left the calculated pixel offsets.

Here is the annotated code and 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> 
+10
source

You can easily fix it.

you can use textBaseline = "middle"; and should use conversion to 50px top

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> 

There is another error in your code: rgba (0, 0, 0, 255 ) the fourth number in rgba should be between 0-1, for example 0.75.

Why am I writing .save () and .restore ()? to reset convert and clear after use.

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(); 
+3
source

This seems to be a 2012 Firefox bug, and is still not fixed!

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

Edit: Setting baseLine to "letter" (default) causes both Chrome and Firefox browsers to have the same vertical layout for text.

Edit: Unfortunately, vertical layout is not the only difference between Firefox and Chrome. Changing the line to "Testing" clearly shows that not only the vertical arrangement is different, but the space between the letters is slightly different - the result is a different text width.

If you really should have the perfect pixel layout and text size, you might want to use Bitmap fonts

+2
source

As another answer says, this is some kind of error king (or maybe just another implementation). textBaseline bottom and Y position to 100 can fix it.

 <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 the base bottom and increase the Y position of the font size

+2
source

Source: https://habr.com/ru/post/1244862/


All Articles