HTML5 Canvas API – formatting individual words with italics

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

Leave a Comment