Solución:
Si solo desea ocuparse de los caracteres de nueva línea en el texto, puede simularlo dividiendo el texto en las líneas nuevas y llamando varias veces al fillText()
Algo como http://jsfiddle.net/BaG4J/1/
var c = document.getElementById('c').getContext('2d');
c.font="11px Courier";
console.log(c);
var txt="line 1nline 2nthird line..";
var x = 30;
var y = 30;
var lineheight = 15;
var lines = txt.split('n');
for (var i = 0; i<lines.length; i++)
c.fillText(lines[i], x, y + (i*lineheight) );
canvas{background-color:#ccc;}
<canvas id="c" width="150" height="150"></canvas>
Acabo de hacer una prueba de concepto envolvente (envoltura absoluta en el ancho especificado. Sin manejar las palabras que se rompen, todavía)
ejemplo en http://jsfiddle.net/BaG4J/2/
var c = document.getElementById('c').getContext('2d');
c.font="11px Courier";
var txt="this is a very long text to print";
printAt(c, txt, 10, 20, 15, 90 );
function printAt( context , text, x, y, lineHeight, fitWidth)
{
fitWidth = fitWidth || 0;
if (fitWidth <= 0)
{
context.fillText( text, x, y );
return;
}
for (var idx = 1; idx <= text.length; idx++)
{
var str = text.substr(0, idx);
console.log(str, context.measureText(str).width, fitWidth);
if (context.measureText(str).width > fitWidth)
{
context.fillText( text.substr(0, idx-1), x, y );
printAt(context, text.substr(idx-1), x, y + lineHeight, lineHeight, fitWidth);
return;
}
}
context.fillText( text, x, y );
}
canvas{background-color:#ccc;}
<canvas id="c" width="150" height="150"></canvas>
Y un envoltorio de palabras (rompiendo en los espacios) prueba de concepto.
ejemplo en http://jsfiddle.net/BaG4J/5/
var c = document.getElementById('c').getContext('2d');
c.font="11px Courier";
var txt="this is a very long text. Some more to print!";
printAtWordWrap(c, txt, 10, 20, 15, 90 );
function printAtWordWrap( context , text, x, y, lineHeight, fitWidth)
{
fitWidth = fitWidth || 0;
if (fitWidth <= 0)
{
context.fillText( text, x, y );
return;
}
var words = text.split(' ');
var currentLine = 0;
var idx = 1;
while (words.length > 0 && idx <= words.length)
{
var str = words.slice(0,idx).join(' ');
var w = context.measureText(str).width;
if ( w > fitWidth )
{
if (idx==1)
{
idx=2;
}
context.fillText( words.slice(0,idx-1).join(' '), x, y + (lineHeight*currentLine) );
currentLine++;
words = words.splice(idx-1);
idx = 1;
}
else
{idx++;}
}
if (idx > 0)
context.fillText( words.join(' '), x, y + (lineHeight*currentLine) );
}
canvas{background-color:#ccc;}
<canvas id="c" width="150" height="150"></canvas>
En el segundo y tercer ejemplo estoy usando el measureText()
método que muestra cuánto tiempo (en pixeles) aparecerá una cadena cuando se imprima.
Me temo que es una limitación de Canvas ‘ fillText
. No hay soporte multilínea. Lo que es peor, no hay una forma incorporada de medir la altura de la línea, solo el ancho, ¡lo que hace que hacerlo usted mismo sea aún más difícil!
Mucha gente ha escrito su propio soporte multilínea, quizás el proyecto más notable que tiene es Mozilla Skywriter.
La esencia de lo que tendrá que hacer es múltiple fillText
llamadas mientras se agrega la altura del texto al valor y cada vez. (Creo que medir el ancho de M es lo que hacen las personas que escriben en el cielo para aproximar el texto).
Quizás llegar un poco tarde a esta fiesta, pero el siguiente tutorial para envolver texto en un lienzo me pareció perfecto.
A partir de eso, pude pensar en hacer funcionar varias líneas (lo siento Ramírez, ¡la tuya no funcionó para mí!). Mi código completo para envolver texto en un lienzo es el siguiente:
<script type="text/javascript">
// http: //www.html5canvastutorials.com/tutorials/html5-canvas-wrap-text-tutorial/
function wrapText(context, text, x, y, maxWidth, lineHeight) {
var cars = text.split("n");
for (var ii = 0; ii < cars.length; ii++) {
var line = "";
var words = cars[ii].split(" ");
for (var n = 0; n < words.length; n++) {
var testLine = line + words[n] + " ";
var metrics = context.measureText(testLine);
var testWidth = metrics.width;
if (testWidth > maxWidth) {
context.fillText(line, x, y);
line = words[n] + " ";
y += lineHeight;
}
else {
line = testLine;
}
}
context.fillText(line, x, y);
y += lineHeight;
}
}
function DrawText() {
var canvas = document.getElementById("c");
var context = canvas.getContext("2d");
context.clearRect(0, 0, 500, 600);
var maxWidth = 400;
var lineHeight = 60;
var x = 20; // (canvas.width - maxWidth) / 2;
var y = 58;
var text = document.getElementById("text").value.toUpperCase();
context.fillStyle = "rgba(255, 0, 0, 1)";
context.fillRect(0, 0, 600, 500);
context.font = "51px 'LeagueGothicRegular'";
context.fillStyle = "#333";
wrapText(context, text, x, y, maxWidth, lineHeight);
}
$(document).ready(function () {
$("#text").keyup(function () {
DrawText();
});
});
</script>
Dónde c
es el ID de mi lienzo y text
es el ID de mi cuadro de texto.
Como probablemente pueda ver, estoy usando una fuente no estándar. Puede usar @ font-face siempre que haya usado la fuente en algún texto ANTES de manipular el lienzo; de lo contrario, el lienzo no recogerá la fuente.
Espero que esto ayude a alguien.