HTML5 Canvas API - formatting individual words with italics

前端 未结 2 1234
走了就别回头了
走了就别回头了 2020-12-11 08:53

I have a small problem using Canvas API in HTML5. I have a text that I have to show on a canvas in an html page.

The text example can be "This is an Italic word&

相关标签:
2条回答
  • 2020-12-11 09:28

    To achieve some kind of flexibility, you have to decide of a convention inside your text that will tell that the style changed.
    And also, you'll have to use measureText to be able to fillText separate 'runs' of the text, each run using the right style, measureText(thisRun).width will give you the size in pixels of the current run.
    Then what you need is to draw separate text runs, each in its own style, then move on the 'cursor' based on the return value of measureText.

    For a quick example, i took as styling convention "§r" = regular text, "§i" = italic, "§b" = bold, "§l" = lighter, so the string :

    var text = "This is an §iItalic§r, a §bbold§r, and a §llighter§r text";
    

    will output as :

    enter image description here

    fiddle is here :

    http://jsfiddle.net/gamealchemist/32QXk/6/

    The code is :

    var canvas = document.getElementById('myCanvas');
    var context = canvas.getContext('2d');
    
    // marker used in the text to mention style change
    var styleMarker = '§';
    
    // table code style --> font style
    var styleCodeToStyle = {
        r: '',
        i: 'italic',
        b: 'bold',
        l: 'lighter'
    };
    
    // example text
    var text = "This is an §iItalic§r, a §bbold§r, and a §llighter§r text";
    
    // example draw
    drawStyledText(text, 20, 20, 'Sans-Serif', 20);
    
    // example text 2 : 
    
    var text2 = "This is a text that has separate styling data";
    var boldedWords = [ 3, 5, 8 ];
    var italicWords = [ 2, 4 , 7];
    
    var words = text2.split(" ");
    var newText ='';
    
    for (var i=0; i<words.length; i++) {
      var thisWord = words[i];
      if (boldedWords.indexOf(i)!=-1) 
          newText += '§b' + thisWord + '§r ';
       else if (italicWords.indexOf(i)!=-1) 
          newText += '§i' + thisWord + '§r ';
        else 
           newText += thisWord + ' ';
    }
    
    drawStyledText(newText, 20, 60, 'Sans-Serif', 20);
    
    
    function drawStyledText(text, x, y, font, fontSize) {
        // start with regular style
        var fontCodeStyle = 'r';
        do {
            // set context font
            context.font = buildFont(font, fontSize, fontCodeStyle);
            // find longest run of text for current style
            var ind = text.indexOf(styleMarker);
            // take all text if no more marker
            if (ind == -1) ind = text.length;
            // fillText current run
            var run = text.substring(0, ind);
            context.fillText(run, x, y);
            // return if ended
            if (ind == text.length) return;
            // move forward
            x += context.measureText(run).width;
            // update current style
            fontCodeStyle = text[ind + 1];
            // keep only remaining part of text
            text = text.substring(ind + 2);
        } while (text.length > 0)
    }
    
    
    function buildFont(font, fontSize, fontCodeStyle) {
        var style = styleCodeToStyle[fontCodeStyle];
        return style + ' ' + fontSize + 'px' + ' ' + font;
    }
    

    enter image description here

    0 讨论(0)
  • 2020-12-11 09:30

    Canvas can measure the width of text in the current font using context.measureText

    A Demo: http://jsfiddle.net/m1erickson/S99Zv/

    enter image description here

    So you can create a function that draws your text and returns the length of text it just drew:

    function drawText(text,style,x,y){
    
        if(ctx.font!==style){ctx.font=style;}
    
        ctx.fillText(text,x,y);
    
        return(ctx.measureText(text).width);
    
    }
    

    Then just accumulate the return values to know the x,y of your next block of text:

    var style1="20px Sans-Serif";
    var style2="italic 20px Sans-Serif";
    
    var accumWidth=30;
    
    accumWidth+=drawText("This is an ",style1,accumWidth,50);
    accumWidth+=drawText("italic ",style2,accumWidth,50);
    accumWidth+=drawText("word",style1,accumWidth,50);
    
    0 讨论(0)
提交回复
热议问题