【问题标题】:Canvas Text with two different font size in the same sentence同一句子中具有两种不同字体大小的画布文本
【发布时间】:2020-10-30 04:46:54
【问题描述】:

同一句子中两种不同字体大小的画布文本并排 有什么办法可以实现吗?

   ctx.textAlign = left;
   ctx.font = "bold 20px ";
   ctx.fillStyle = '#ccc';
   ctx.fillText("Normal Small", 100, 300);

【问题讨论】:

  • 您想在某处使用measureText。你试过这个吗?
  • 你必须使用两个不同的填充文本
  • @user4642212 我是画布新手,有没有可以借鉴的例子?
  • @Kudlas 我不确定它是否像 html 一样有效。可以的话请举个例子。

标签: javascript html css canvas html5-canvas


【解决方案1】:

简单的画布标记

您可以定义自己的标记格式,然后根据标记规则呈现文本。

例如一个字符串"This is normal, <b>this is bold</b> and back to normal."

标签<b></b> 定义文本粗体部分的开始和结束。

然后根据标签的位置迭代将字符串分成几部分。我将手动搜索并使用堆栈来跟踪嵌套样式,而不是使用 RegExp。

要定义样式,您只需创建一个通过单个字符映射样式的对象

const styles = {
    default: { font: "16px arial", fillStyle: "black", },
    b: { font: "16px arial black", fillStyle: "black", },
    w: { fillStyle: "white" },
};

样式使用Object.assign(ctx, styles["b"])设置

示例

函数canvasMarkupText(ctx, str, x, y, styles) 使用简单的标记和方案styles 呈现文本。

  • 它创建一个堆栈,其中包含一个包含字符串位置和规则名称的内容对象,

  • 渲染函数,将渲染内容对象中的细节,

  • 一个简单的迭代器(while 循环),用于控制何时从堆栈中添加和删除内容,以及何时呈现内容。

  • 在退出之前,它会检查堆栈是否有内容并呈现剩余的文本。

  • 函数返回渲染文本的宽度。

注意没有验证标记。

注意样式级联向下但不向上。

注意此示例仅适用于单字符标签。

注意 示例中使用"<" 作为标记分隔符意味着函数无法呈现该字符。为此,您需要添加某种形式的转义序列。例如 double "<<" 可以代表那个字符。

这只是一个示例,并不意味着作为解决方案。将其用作构建您自己的指南。

ctx = canvas.getContext("2d");

const styles = {
    default: {font: "14px arial", fillStyle: "black",},
    b: {font: "14px arial black", fillStyle: "black",},
    w: {fillStyle: "white"},
};

canvasMarkupText(ctx, "Testing <b>testing BOLD <w>bold white</w></b> and testing with default <w>and white</w>", 10, 14, styles)

function canvasMarkupText(ctx, str, x, y, styles) {
    const content = (start, end, rule) => ({start, end, rule});
    const render = content => {
        Object.assign(ctx, styles[content.rule] ? styles[content.rule] : {});
        const s = str.slice(content.start, content.end)
        ctx.fillText(s, x, y);
        x += ctx.measureText(s).width;
    };

    const stack = [], xx = x;
    var pos = 0, current = content(pos, pos, "default");
    stack.push(current);
    while (pos < str.length) {
        const c = str[pos++];
        if (c === "<") {
           if (str[pos] === "/") {
               render(stack.pop());
               current = stack[stack.length - 1];
               current.start = current.end = (pos += 3);
           } else {
               render(current);
               pos += 2;
               stack.push(current = content(pos, pos, str[pos - 2]));
           }
        } else { current.end = pos }
    }
    stack.length && render(current);
    return x - xx;
}
canvas {background: #59D}
&lt;canvas id="canvas" width="500" height="20"&gt;&lt;/canvas&gt;

【讨论】:

    【解决方案2】:

    我也尝试了@BlindMan67 的建议 并这样做了:

               ctx.textAlign = align;
               ctx.font = "bold 20px " + this.fontStyle;
               ctx.fillStyle = this.rewardsTextColor;
    
               var ctxTextYPlacement = (this.gaugeCenterY - coord.y) - 5;
               var ctxTextXPlacement = this.gaugeCenterX - coord.x - 12;
    
               ctx.fillText(earningValue, ctxTextXPlacement, ctxTextYPlacement);
    
               var measure = ctx.measureText(earningValue);
               var measureWidth = measure.width - 30;
    
               ctx.font = "bold 10px " + this.fontStyle;
               ctx.fillText('mi.', (ctxTextXPlacement + measureWidth), ctxTextYPlacement);
    

    【讨论】:

      猜你喜欢
      • 2013-08-24
      • 2019-04-03
      • 2011-11-16
      • 1970-01-01
      • 1970-01-01
      • 2011-12-31
      • 2021-09-20
      • 1970-01-01
      • 2013-10-25
      相关资源
      最近更新 更多