HTML5 canvas ctx.fillText won't do line breaks?

前端 未结 17 1038
甜味超标
甜味超标 2020-11-28 01:37

I can\'t seem to be able to add text to a canvas if the text includes \"\\n\". I mean, the line breaks do not show/work.

ctxPaint.fillText(\"s  ome \\n \\\\n         


        
相关标签:
17条回答
  • 2020-11-28 02:27

    Split the text into lines, and draw each separately:

    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;
      }
    }
    
    0 讨论(0)
  • 2020-11-28 02:27

    Using javascript I developed a solution. It isn't beautiful but it worked for me:


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

    Hope that helps!

    0 讨论(0)
  • 2020-11-28 02:28

    I'm afraid it is a limitation of Canvas' fillText. There is no multi-line support. Whats worse, there's no built-in way to measure line height, only width, making doing it yourself even harder!

    A lot of people have written their own multi-line support, perhaps the most notable project that has is Mozilla Skywriter.

    The gist of what you'll need to do is multiple fillText calls while adding the height of the text to the y value each time. (measuring the width of M is what the skywriter people do to approximate text, I believe.)

    0 讨论(0)
  • 2020-11-28 02:28

    I happened across this due to having the same problem. I'm working with variable font size, so this takes that into account:

    var texts=($(this).find('.noteContent').html()).split("<br>");
    for (var k in texts) {
        ctx.fillText(texts[k], left, (top+((parseInt(ctx.font)+2)*k)));
    }
    

    where .noteContent is the contenteditable div the user edited (this is nested in a jQuery each function), and ctx.font is "14px Arial" (notice that the pixel size comes first)

    0 讨论(0)
  • 2020-11-28 02:30

    Here's a version of Colin's wrapText() that also supports vertically centered text with context.textBaseline = 'middle':

    var wrapText = function (context, text, x, y, maxWidth, lineHeight) {
        var paragraphs = text.split("\n");
        var textLines = [];
    
        // Loop through paragraphs
        for (var p = 0; p < paragraphs.length; p++) {
            var line = "";
            var words = paragraphs[p].split(" ");
            // Loop through words
            for (var w = 0; w < words.length; w++) {
                var testLine = line + words[w] + " ";
                var metrics = context.measureText(testLine);
                var testWidth = metrics.width;
                // Make a line break if line is too long
                if (testWidth > maxWidth) {
                    textLines.push(line.trim());
                    line = words[w] + " ";
                }
                else {
                    line = testLine;
                }
            }
            textLines.push(line.trim());
        }
    
        // Move text up if centered vertically
        if (context.textBaseline === 'middle')
            y = y - ((textLines.length-1) * lineHeight) / 2;
    
        // Render text on canvas
        for (var tl = 0; tl < textLines.length; tl++) {
            context.fillText(textLines[tl], x, y);
            y += lineHeight;
        }
    };
    
    0 讨论(0)
提交回复
热议问题