Earlier this week, I took a have a look at rendering textual content to <canvas>
utilizing an adjusted X,Y offset for cross-browser consistency. In that demo, I used to be utilizing a textBaseline
of high
, which is inherently completely different from browser to browser. After I posted that, Jan Sedivy – creator of InVision Freehand – informed me that whereas high
could also be inconsistent, a textBaseline
of alphabetic
is rendered completely throughout all browsers. And, in actual fact, additionally matches the baseline
rendering of the browser’s native textual content (outdoors of Canvas). As such, I needed to carry out a fast-follow demo to have a look at how the alphabetic
baseline renders in Chrome, Firefox, and Safari.
Run this demo in my JavaScript Demos venture on GitHub.
View this code in my JavaScript Demos venture on GitHub.
Simply as with my earlier demo, I’ll first render a grid of strains to the Canvas factor in order that we will clearly see the place textual content is being rendered. Then, I’ll render pattern textual content at numerous pixel-sizes in order that we will see the connection between the font-sizes and the rendering:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta identify="viewport" content material="width=device-width, initial-scale=1" />
<title>
Canvas "alphabetic" textBaseline Is Constant Throughout Browsers
</title>
<hyperlink rel="preconnect" href="https://fonts.googleapis.com" />
<hyperlink rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<hyperlink rel="stylesheet" href="https://fonts.googleapis.com/css2?household=Roboto:wght@500&show=swap" />
<model sort="textual content/css">
physique {
font-family: "Roboto", sans-serif ;
}
canvas {
box-shadow: 0px 0px 0px 2px #000000 ;
}
</model>
</head>
<physique>
<h1>
Canvas "alphabetic" textBaseline Is Constant Throughout Browsers
</h1>
<canvas id="demo" width="400" peak="400"></canvas>
<script sort="textual content/javascript">
var canvas = doc.querySelector( "#demo" );
var canvasWidth = 400;
var canvasHeight = 400;
var context = canvas.getContext( "second" );
// Now we have to offer the FONT time to load in order that we will apply it to the canvas.
window.addEventListener(
"load",
() => {
drawGridLines();
drawText( "No one places child in a nook!" );
}
);
// --------------------------------------------------------------------------- //
// --------------------------------------------------------------------------- //
/**
* I draw the pattern textual content to canvas at numerous sizes.
*/
perform drawText( textValue ) {
var pairings = [
{ fontSize: 10, y: 50 },
{ fontSize: 20, y: 100 },
{ fontSize: 30, y: 150 },
{ fontSize: 40, y: 200 },
{ fontSize: 50, y: 250 },
{ fontSize: 60, y: 300 },
{ fontSize: 70, y: 350 }
];
context.fillStyle = "#000000";
context.textBaseline = "alphabetic";
for ( var pairing of pairings ) {
context.font = `500 ${ pairing.fontSize }px Roboto`;
context.fillText( textValue, 50, pairing.y );
}
}
/**
* I draw the horizontal and vertical grid strains on the canvas in order that we will extra
* simply see the place the textual content is aligned on completely different browsers.
*/
perform drawGridLines() {
var step = 10;
var bounce = 50;
context.lineWidth = 1;
context.strokeStyle = "#cccccc";
// Draw GREY horizontal grid strains.
for ( var i = step ; i < canvasHeight ; i += step ) {
context.beginPath();
context.moveTo( 0, ( i - 0.5 ) );
context.lineTo( canvasWidth, ( i - 0.5 ) );
context.stroke();
}
// Draw GREY vertical grid strains.
for ( var i = step ; i < canvasWidth ; i += step ) {
context.beginPath();
context.moveTo( ( i - 0.5 ), 0 );
context.lineTo( ( i - 0.5 ), canvasHeight );
context.stroke();
}
context.strokeStyle = "#ff3333";
// Draw RED horizontal grid strains.
for ( var i = bounce ; i < canvasHeight ; i += bounce ) {
context.beginPath();
context.moveTo( 0, ( i - 0.5 ) );
context.lineTo( canvasWidth, ( i - 0.5 ) );
context.stroke();
}
// Draw RED vertical grid strains.
for ( var i = bounce ; i < canvasWidth ; i += bounce ) {
context.beginPath();
context.moveTo( ( i - 0.5 ), 0 );
context.lineTo( ( i - 0.5 ), canvasHeight );
context.stroke();
}
}
</script>
</physique>
</html>
And, when run that is Chrome, Firefox, and Safari, we get the next output:
As you may see, utilizing a textBaseline
of alphabetic
appears more-or-less precisely the identical in every browser. However, the large distinction, rendering-wise, between this demo and the earlier demo is that the textual content is being rendered above the purple strains versus under the purple strains. With the intention to account for that, we might have to regulate the situation of the y
coordinate within the .fillText()
invocation – however that is a put up for an additional day.
Wish to use code from this put up?
Try the license.