Explain Codes LogoExplain Codes Logo

Html5 canvas ctx.fillText won't do line breaks?

html
responsive-design
performance
best-practices
Alex KataevbyAlex Kataev·Sep 8, 2024
TLDR

Create line breaks in canvas using fillText by splitting the text into lines and painting each on a different y-coordinate:

function drawText(ctx, text, x, y, lineHeight) { text.split('\n').forEach((line, i) => ctx.fillText(line, x, y + i * lineHeight)); } // Usage: const ctx = document.getElementById('canvas').getContext('2d'); drawText(ctx, 'Be water,\nmy friend.', 10, 10, 20); // Bruce Lee lives on in the canvas

Key idea: The drawText() function uses split('\n') to make \n act as line breaks, painting lines with an increasing offset by lineHeight.

Crafting a Word Wrap Function

To handle variable text lengths and different canvas sizes, consider wrapping text within a specified maxWidth. By splitting the text both by new lines and by words, you ensure that the text fits neatly within given boundaries.

Also, use the measureText() method to get the width of strings in pixels, which could help in implementing word wrap.

Styling and Appearance

To bring your own styling, modify the font property of the canvas context to define the font size and family. Using @font-face for non-standard fonts and adjusting fillStyle can add distinctive style to text rendering.

Remember, using the textBaseline property can align your text beautifully.

Line Height and Spacing

A popular way to estimate line-height is by measuring the height of the letter "M" and multiplying it by a certain factor, as fillText() doesn't natively support line spacings. After calculating, increase your y coordinate by the computed line height to get evenly spaced lines.

Advanced Text Rendering

To take your text rendering to the next level, check out Mozilla's Skywriter project or some resources on GitHub for multi-line solutions.

Visualization

Consider a situation where you are writing text on a canvas as shown below:

<canvas id="canvas"></canvas> <script> const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d'); ctx.fillText('Be water,', 10, 50); // Writes "Be water," then the pen starts daydreaming </script>

To continue writing, you need to update the pen's y-coordinate position manually.

🖊️📝: "Be water," // Line 1 🖊️⬇️: Move pen down // Let's break the line and drop it down 🖊️📝: "my friend." // Line 2

As you can see in the following code, you need to manually create line breaks:

ctx.fillText('Be water,', 10, 50); ctx.fillText("my friend.", 10, 70); // Y moves down, but the spirit of water remains high

This is how you get around fillText()'s refusal to naturally break lines.

Word Wrap and Text Overflow

Keep an eye on text overflow by calling measureText() to determine the length of the string. Insert line breaks whenever text width exceeds your maxWidth, thus preventing any potential text overflow that could ruin our hard work.

Enhancing Readability

To maintain good readability, consider tuning the y-coordinate increment according to different fonts and sizes. Use toUpperCase() to have some texts shout out and always clear your canvas before redrawing text.

Total Control: Libraries and Code Examples

For advanced usage, you might consider employing some external libraries specialized in these tasks. Remember, people before us probably faced this challenge. Platforms like CodePen can serve as a treasure trove of wisdom.