Простая разметка холста
Вы можете определить свой собственный формат разметки, а затем отобразить текст в зависимости от правил разметки.
Например, строка "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>