HTML5画布API - 使用斜体格式化单独的单词

3

我在使用HTML5中的Canvas API时遇到了一些小问题。 我有一个文本需要在网页Canvas上显示。

文本示例可以是“这是一个斜体单词”。 因此,我需要从数据库中取出这些文本并将句子中的一个单词变成斜体。因此,我需要以以下方式显示文本:

"这是一个斜体单词"

因此,我的代码如下:

var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');

//text
context.fillStyle  = "#000000";
context.font = "20px Sans-Serif";
context.textBaseline = "top";
context.fillText  ("This is an ", 195, 80 );

context.font = "italic 20px Sans-Serif";
context.fillText  ("Italic", 285, 80 );
context.font = "20px Sans-Serif";
context.fillText  ("text", 330, 80 );

所以这段代码并不是真正的动态代码,我有足够的时间去知道其余句子的正确像素起点。有人有想法如何以动态和清晰的方式解决这个问题吗?

2个回答

5
为了实现某种灵活性,您必须在文本中决定一种约定,以表示样式已更改。
并且,您还需要使用measureText来能够填充文本的独立“运行”(即每个运行使用正确的样式),measureText(thisRun)。width将给出当前运行的像素大小。
然后,您需要绘制单独的文本运行,每个都有自己的样式,然后根据measureText的返回值移动“光标”。

作为一个快速的例子,我采用了“§r”=常规文本,“§i”=斜体,“§b”=粗体,“§l”=轻字体作为样式约定,因此字符串:

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

将输出为:

enter image description here

fiddle 在这里:

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

代码如下:

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


这是一个不错的解决方案。但在我的情况下,将这些样式约定放置起来有点困难。因为我在数据库中有一张表格包含句子,另一张表格包含应该加粗的单词索引。所以我非常喜欢你的解决方案,但我认为它并不完全适合我的问题。谢谢! - The user without number
好的,谢谢,但是你没有提到这个限制。花了几秒钟来调整代码,看看我的编辑和更新后的fiddle。 - GameAlchemist

0

Canvas可以使用context.measureText测量当前字体的文本宽度。

演示链接:http://jsfiddle.net/m1erickson/S99Zv/

enter image description here

因此,您可以创建一个绘制文本并返回其刚刚绘制的文本长度的函数:

function drawText(text,style,x,y){

    if(ctx.font!==style){ctx.font=style;}

    ctx.fillText(text,x,y);

    return(ctx.measureText(text).width);

}

然后只需累加返回值,即可知道下一个文本块的x、y:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接