Canvas Text Wrapping

by Ben Gillbanks

HTML

<canvas></canvas>

CSS

body { background: #ddd; }
canvas { background: white; }

JavaScript

const wrapText = {

	ALIGN_TOP: 1,

	ALIGN_BOTTOM: 2,


	/**
	 * Prepare text for wrapping and display.
	 *
	 * @param {string} text The text to prepare.
	 * @param {int} maxWidth The width to wrap the text at.
	 * @return {array}
	 */
	prepare: function( ctx, text, maxWidth ) {

		const words = text.split( ' ' );
		let lines = [];
		let line = '';

		for ( const [ index, w ] of words.entries() ) {

			const testLine = line + w + ' ';
			const metrics = ctx.measureText( testLine );
			const testWidth = metrics.width;

			if ( testWidth > maxWidth && index > 0 ) {
				lines.push( line );
				line = w + ' ';
			} else {
				line = testLine;
			}

		}

		if ( line !== '' ) {
			lines.push( line );
		}

		return lines;

	},


	/**
	 * Display the wrapped text.
	 *
	 * @param {object} ctx The canvas context to draw to.
	 * @param {array} lines The lines of text to display.
	 * @param {int} x The x position to draw to.
	 * @param {int} y The y position to draw to.
	 * @param {int} lineHeight The line height for the displayed text.
	 * @param {int} align The text alignment. Defaults to drawing from top down.
	 * @return {void}
	 */
	display: function( ctx, lines, x, y, lineHeight, align = wrapText.ALIGN_TOP ) {

		y = y + Math.round( lineHeight * 0.7 );

		if ( wrapText.ALIGN_BOTTOM === align ) {
			y = y - wrapText.height( lines, lineHeight );
		}

		lines.forEach(
			( value, index ) => {
				ctx.fillText( value, x, y );
				y += lineHeight;
			}
		);

	},


	/**
	 * Calculate the height of the wrapped text.
	 *
	 * @param {array} lines The lines that will be displayed.
	 * @param {int} lineHeight The line height for the wrapped text.
	 * @return {int}
	 */
	height: function( lines, lineHeight ) {

		return lines.length * lineHeight;

	},

};



const canvas = document.querySelector('canvas');
const canvas_height = 512;
const canvas_width = 512;
canvas.width = canvas_width;
canvas.height = canvas_height;
const ctx = canvas.getContext('2d');

const text = 'Lorem ipsum...