Page 1 of 2
Now available as a paperback or ebook from Amazon.
- Getting Started With Canvas
- Drawing Paths
Extract: Basic Paths
Extract: Bezier Curves
- Stroke and Fill
Extract: Stroke Properties
Extract: Text, Typography & SVG
Extract: Unicode **NEW!
- Clipping, Compositing and Effects
Extract: Clipping & Basic Compositing
- Generating Bitmaps
Extract: Introduction To Bitmaps
- WebWorkers & OffscreenCanvas
- Typed Arrays
- Files, blobs, URLs & Fetch
Extract: Blobs & Files
- Image Processing
- 3D WebGL
- 2D WebGL
Extract: WebGL Convolutions
In chapter but not in extract:
Typographic Positioning - textBaseline and textAlign
The meaning of the x,y in the positioning of text is more complicated than you might think. If you accept the defaults then it more or less corresponds to the bottom left corner of the text's bounding box.
You can change the horizontal positioning relative to the x value specified by setting textAlign property to one of:
start or left The text is drawn just after the x position.
center The center of the text is located at the x position.
end or right The end of the text is located the x position.
You can use these values to left or right justify or center text. For example:
ctx.font="normal normal 20px arial";
ctx.fillText("line of text followed by",200,60);
ctx.fillText("A shorter line of text",200,60+20*115/100);
The textBaseline property determines how y alters the vertical position of the text relative to the horizontal line, the baseline. It can be set to one of:
alphabetic Bottom of vertically oriented glyphs (default)
ideographic Bottom of horizontally oriented glyphs
top Text is aligned based on the top of the tallest glyph
bottom Text is aligned based on bottom of the glyph
middle Text is aligned according to the middle of the text
hanging Used by Tibetan and other indic scripts
You can see the essential details in this chart from the WHATWG specification:
Notice that the bounding box is the maximum area a font can use and not all glyphs fill it. In some fonts the majority of glyphs use a much smaller area of the total allowed to them. The key measurement is the em square. This is a square with sides equal to the current point size of the font.
When you render text onto the canvas you simply specify x,y and perhaps a maximum width. The x value gives the horizontal alignment and the y value sets the baseline - so what is the bounding box?
The answer is that the bounding box depends on the font in use and you can use the measureText() method to return a TextMetrics object which contains all of the information on the layout of a particular string in the current font as read only properties. The only problem at the moment is that this is only fully supported on Safari and on Chrome but only if you enable Experimental Web Platform Features using chrome://flags. All browsers support the TextMetrics object and at least the width property:
calculated width of the text. This is not the width of the bounding box but the number of pixels needed to the end of the text. That is, it is the y distance in pixels you need to move to continue the text in the same font.
distance from x,y to the left and right edge of the bounding box. Notice that these depend on the alignment used.
distance from x,y to the top and bottom of the bounding rectangle. The actual version of the properties gives you the top and bottom of the bounding rectangle for the actual text used in the call and the other two properties give the value for the font. This means the "actual" versions give a bounding box for the current text and the other two give a bounding box that includes any text in the font.
the distance from x,y to the top and bottom of the em square in the line box, in pixels. This gives you the font's "point" size measured in pixels.
the distance from x,y given baseline in pixels.
For example, suppose you want the actual bounding box for a specific piece of text:
ctx.font="normal normal 40px arial";
text="Hello Text World";
Where boxL,boxT is the top left corner of the bounding box and boxR,boxB is the bottom right corner. This produces a tight bounding box for the text you specify:
If you change the program to read:
then you will get a bounding box that will contain any text from the font:
That is, there are characters in the font that will use the apparently extra space in the bounding box.
Note these programs currently only work on Chrome or Safari.
It is likely that support for typographic metrics will improve and it is worth checking the current state before making use of any of these properties. There are font libraries that can extract typographic metrics from font files and this might be the only way to perform accurate layout until browsers implement the full textMetric object.
There is also the direction property which can be set to one of:
ltr left to right
rtl right to left