130 votes

HTML5 canvas ctx.fillText de ne pas faire des sauts de ligne?

Je ne peux pas semblent être en mesure d'ajouter du texte à une toile si le texte comprend "\n". Je veux dire, les sauts de ligne ne montrent pas/travail.

ctxPaint.fillText("s  ome \n \\n <br/> thing", x, y);

Le code ci-dessus, va attirer l' "s ome \n <br/> thing", sur une seule ligne.

Est-ce une limitation de fillText ou suis-je tout faux? le "\n"; s sont là, et ne sont pas imprimés, mais ils ne fonctionnent pas non plus.

70voto

Simon Sarris Points 33799

J'ai peur que ce une limitation de la Toile fillText. Il n'y a pas de multi-support. Ce qui est pire, il n'y a pas moyen intégré pour mesurer la hauteur de ligne, seule la largeur, faisant le faisant vous-même encore plus difficile!

Beaucoup de gens ont écrit leur propre multi-support, peut-être le plus notable de ce projet qu'est Mozilla Skywriter.

Le jist de ce que vous aurez besoin de faire est de plusieurs fillText appels tout en ajoutant la hauteur du texte à l'o de la valeur à chaque fois. (mesure de la largeur de M est ce que le skywriter les gens ne rapprochant de texte, je crois.)

40voto

Colin Wiseman Points 408

Peut-être à venir à cette fête un peu en retard, mais j'ai trouvé le tutoriel suivant pour l'habillage du texte sur une toile parfaite.

http://www.html5canvastutorials.com/tutorials/html5-canvas-wrap-text-tutorial/

Depuis que j'ai été capable de penser à obtenir les lignes de travail (désolé Ramirez, le vôtre ne fonctionne pas pour moi!). Mon code complet pour placer du texte dans une toile est comme suit:

<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>

c est l'ID de ma toile, text est l'ID de ma zone de texte.

Comme vous pouvez probablement voir suis en utilisant une police non standard. Vous pouvez utiliser @font-face aussi longtemps que vous avez utilisé la police sur certains textes AVANT la manipulation de la toile, sinon la toile ne ramasse pas de la police.

Espérons que cela aide quelqu'un.

29voto

Darthenius Points 1828

Scinder le texte en lignes, et tirer chacun séparément:

function fillTextMultiLine(ctx, text, x, y) {
  var lineHeight = ctx.measureText("M").width * 1.2;
  var lines = text.split("\n");
  for (var i = 0; i < lines.length; ++i) {
    ctx.fillText(lines[i], x, y);
    y += lineHeight;
  }
}

20voto

Jake Points 2102

Voici ma solution, la modification de la populaire wrapText() fonction qui est déjà présenté ici. Je suis en utilisant le prototypage fonction de JavaScript, de sorte que vous pouvez appeler la fonction de la toile contexte.

CanvasRenderingContext2D.prototype.wrapText = function (text, x, y, maxWidth, lineHeight) {

    var lines = text.split("\n");

    for (var i = 0; i < lines.length; i++) {

        var words = lines[i].split(' ');
        var line = '';

        for (var n = 0; n < words.length; n++) {
            var testLine = line + words[n] + ' ';
            var metrics = this.measureText(testLine);
            var testWidth = metrics.width;
            if (testWidth > maxWidth && n > 0) {
                this.fillText(line, x, y);
                line = words[n] + ' ';
                y += lineHeight;
            }
            else {
                line = testLine;
            }
        }

        this.fillText(line, x, y);
        y += lineHeight;
    }
}

Utilisation de base:

var myCanvas = document.getElementById("myCanvas");
var ctx = myCanvas.getContext("2d");
ctx.fillStyle = "black";
ctx.font = "12px sans-serif";
ctx.textBaseline = "top";
ctx.wrapText("Hello\nWorld!",20,20,160,16);

Voici une démonstration, j'ai mis en place: http://jsfiddle.net/7RdbL/

8voto

Ramirez Points 69

À l'aide de javascript, j'ai développé une solution. Il n'est pas beau, mais cela a fonctionné pour moi:


function drawMultilineText(){

    // set context and formatting   
    var context = document.getElementById("canvas").getContext('2d');
    context.font = fontStyleStr;
    context.textAlign = "center";
    context.textBaseline = "top";
    context.fillStyle = "#000000";

    // prepare textarea value to be drawn as multiline text.
    var textval = document.getElementByID("textarea").value;
    var textvalArr = toMultiLine(textval);
    var linespacing = 25;
    var startX = 0;
    var startY = 0;

    // draw each line on canvas. 
    for(var i = 0; i < textvalArr.length; i++){
        context.fillText(textvalArr[i], x, y);
        y += linespacing;
    }
}

// Creates an array where the <br/> tag splits the values.
function toMultiLine(text){
   var textArr = new Array();
   text = text.replace(/\n\r?/g, '<br/>');
   textArr = text.split("<br/>");
   return textArr;
}

Espérons que ça aide!

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X