Skip to content

Instantly share code, notes, and snippets.

@jimivdw
Created October 9, 2013 13:38
Show Gist options
  • Save jimivdw/6901448 to your computer and use it in GitHub Desktop.
Save jimivdw/6901448 to your computer and use it in GitHub Desktop.
An extension to the CanvasRenderingContext2D's fillText method that supports line breaks and automatically fits the text into a specified bounding box.
<!DOCTYPE html>
<html>
<body>
<canvas id="canvas" width="800" height="400" style="border: 1px solid #333;"></canvas>
<script type="text/javascript">
// Based on:
// http://www.html5canvastutorials.com/tutorials/html5-canvas-wrap-text-tutorial
CanvasRenderingContext2D.prototype.textLines = function(x, y, w, h, text,
hard_wrap) {
var ctx = this;
var lines = Array();
var hard_lines = text.trim().split("\n");
hard_lines.forEach(function(hard_line) {
if(ctx.measureText(hard_line).width > w) {
var line = "";
var words = hard_line.split(" ");
words.forEach(function(word) {
var nline = line + word + " ";
if(ctx.measureText(nline).width > w) {
lines.push(line);
if(ctx.measureText(word).width > w && hard_wrap) {
line = "";
var chars = word.split("");
chars.forEach(function(char) {
var nline = line + char;
if(ctx.measureText(nline).width > w) {
lines.push(line);
line = char;
} else {
line = nline;
}
});
line += " ";
} else {
line = word + " ";
}
} else {
line = nline;
}
});
lines.push(line);
} else {
lines.push(hard_line);
}
});
return lines;
};
CanvasRenderingContext2D.prototype.boxedFillText = function(x, y, w, h, text,
hard_wrap) {
var ctx = this;
var lines = ctx.textLines(x, y, w, h, text, hard_wrap);
var lineHeight = parseInt(ctx.font.split("px")[0]) * 1.2;
var min_y = y;
var max_y = y + h;
var ll = lines.length - 1;
switch(ctx.textBaseline.toLowerCase()) {
case "bottom":
min_y = y - h + lineHeight;
max_y = y;
y -= ll * lineHeight;
if(y < min_y)
y = min_y;
break;
case "middle":
min_y = y - h / 2 + lineHeight / 2;
max_y = y + h / 2 - lineHeight / 2;
y -= (ll / 2) * lineHeight;
if(y < min_y)
y = min_y;
break;
default:
break;
}
console.log(ctx.textBaseline);
lines.forEach(function(line) {
if(y <= max_y) {
ctx.fillText(line, x, y);
}
y += lineHeight;
});
};
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.fillStyle = "#0F0";
ctx.fillRect(20, 20, 200, 150);
ctx.fillRect(20, 220, 200, 150);
ctx.font = "20px Arial";
ctx.fillStyle = "#000";
ctx.textBaseline = "middle";
var text = "This is\nsome nice text WithAVeryLongWordInItThatIsTooLong..";
ctx.boxedFillText(20, 95, 200, 150, text);
ctx.boxedFillText(20, 295, 200, 150, text, true);
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment