I need to draw a text string at a precise position on HTML5 canvas.
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:
I'm going to draw other elements (e.g. 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.
Please add your voice to the Firefox's bug page so they fix it soon.
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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With