【问题标题】:HTML5 Canvas API - formatting individual words with italicsHTML5 Canvas API - 用斜体格式化单个单词
【发布时间】:2014-08-01 12:39:44
【问题描述】:

我在 HTML5 中使用 Canvas API 时遇到了一个小问题。 我有一个文本,我必须在 html 页面的画布上显示。

文本示例可以是“这是一个斜体字”。 所以我要做的是显示我从数据库中获取的文本,但只从句子 Italic 中提取一个单词。所以我必须像这样显示文本:

“这是一个斜体字”

所以我的代码如下所示:

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

所以这段代码实际上并不是动态的,我有时间知道从哪里开始句子其余部分的正确像素。 有谁知道如何动态和干净地解决这个问题?

【问题讨论】:

    标签: javascript html canvas html5-canvas


    【解决方案1】:

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

    一个演示:http://jsfiddle.net/m1erickson/S99Zv/

    所以你可以创建一个函数来绘制你的文本并返回它刚刚绘制的文本长度:

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

    【讨论】:

      【解决方案2】:

      要获得某种灵活性,您必须在文本中确定一个约定,以表明样式已更改。
      此外,您必须使用 measureText 才能将文本的“运行”分开填充文本,每次运行都使用正确的样式,measureText(thisRun).width 将为您提供当前运行的像素大小。
      然后你需要绘制单独的文本运行,每个都有自己的风格,然后根据 measureText 的返回值移动“光标”。

      举个简单的例子,我把“§r” = 常规文本,“§i” = 斜体,“§b” = 粗体,“§l” = 打火机,所以字符串:

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

      将输出为:

      小提琴在这里:

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

      【讨论】:

      • 这是一个很好的解决方案。但就我而言,放置这些样式约定有点困难。因为我在数据库句子中的一个表和另一个表中的单词索引应该是粗体。所以我真的很喜欢你的解决方案,但我认为它并不完全适合我的问题。谢谢!
      • 好的,谢谢,但你没有提到这个约束。修改代码需要几秒钟,请参阅我的编辑和更新的小提琴。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-12-21
      • 2013-10-28
      • 2018-05-10
      • 1970-01-01
      • 1970-01-01
      • 2012-12-02
      • 2021-12-17
      相关资源
      最近更新 更多