Canvas Wrap + Newlines
A nice canvas wrap text functionality plus the ability to manually set newlines
by Kikketer
HTML
<canvas id="cvs"></canvas>
<br />
<input type="text" id="input" value="Here's a\nnew line! and some other text that will do a natural line wrap." />
CSS
body {
background-color: #efefef;
}
canvas {
outline: 1px solid #000;
background-color: white;
}
JavaScript
var canvas = document.getElementById('cvs'),
ctx = canvas.getContext('2d'),
input = document.getElementById('input'),
width = +(canvas.width = 400),
height = +(canvas.height = 250),
fontFamily = "Arial",
fontSize = "24px",
fontColour = "blue";
function fragmentText(text, maxWidth) {
var words = text.split(' ');
var lines = [];
var line = '';
while (words.length > 0) {
while (ctx.measureText(words[0]).width >= maxWidth) {
forcedNewline = false;
var tmp = words[0];
words[0] = tmp.slice(0, -1);
if (words.length > 1) {
words[1] = tmp.slice(-1) + words[1];
} else {
words.push(tmp.slice(-1));
}
}
if (words[0].match(/\\n/g)) {
var twoWords = words[0].split('\\n');
// Take the first half and add it to the line
line += twoWords[0];
// Loop to create any more newlines (\n\n anyone?)
for (var i = 1; i <= twoWords.length - 2; i++) {
lines.push(line);
line = '';
}
// Take the second half and replace words[0] with it
words.splice(0, 1, twoWords[twoWords.length - 1]);
lines.push(line);
line = '';
} else if (ctx.measureText(line + words[0]).width < maxWidth) {
line += words.shift() + " ";
} else {
lines.push(line);
line = "";
}
if (words.length === 0) {
lines.push(line);
}
}
return lines;
}
function draw() {
ctx.save();
ctx.clearRect(0, 0, width, height);
ctx.font = "bold " + fontSize + " " + fontFamily;
ctx.textAlign = "left";
ctx.fillStyle = fontColour;
var lines = fragmentText(input.value, width - parseInt(fontSize, 0));
lines.forEach(function(line, i) {
ctx.fillText(line, 0, (i + 1) * parseInt(fontSize, 0));
});
ctx.restore();
}
input.onkeyup = function(e) {
draw();
};
// Initial draw
draw();