Текст на холсте с двумя разными размерами шрифта в одном предложении - PullRequest
0 голосов
/ 09 июля 2020

Текст на холсте с двумя разными размерами шрифта в одном предложении рядом. Есть ли способ добиться этого?

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

введите описание изображения здесь

Ответы [ 2 ]

3 голосов
/ 09 июля 2020

Простая разметка холста

Вы можете определить свой собственный формат разметки, а затем отобразить текст в зависимости от правил разметки.

Например, строка "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.

  • Он создает стек, содержащий объект содержимого, содержащий позицию строки и имя правила,

  • Функция визуализации, которая будет отображать детали в объекте содержимого,

  • Простой итератор (в то время как l oop), который контролирует, когда контент добавляется и удаляется из стека, а также когда визуализировать контент.

  • Перед выходом из него проверяет, есть ли в стеке содержимое и отображает оставшийся текст.

  • Функция возвращает ширину визуализированного текста.

Примечание Проверка разметки не проводится.

Примечание * 105 3 * Стили располагаются каскадом вниз, но не вверх.

Примечание Этот пример будет работать только с односимвольными тегами.

Примечание Использование "<" в примере в качестве разделителя разметки означает, что функция не может отобразить этот символ. Для этого вам нужно будет добавить некоторую форму escape-последовательности. например, двойной "<<" может представлять этот символ.

Это ТОЛЬКО пример и не рассматривается как решение. Используйте его как руководство для создания своего собственного.

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}
<canvas id="canvas" width="500" height="20"></canvas>
0 голосов
/ 09 июля 2020

Я тоже пробовал предложение @ 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);
...