Это можно сделать двумя способами.
За кадром
Создать закадровый холст, визуализировать текст на этом холсте и затем использовать ctx.globalCompositeOperation = "color"
* 1007.* (обновить мой плохой, который должен быть ctx.globalCompositeOperation = "destination-in"
) сначала нарисуйте цвет, затем нарисуйте текст поверх цвета.(см. пример)
Пример вышеуказанного метода
canvas.width = 430;
canvas.height = 16;
const ctx = canvas.getContext("2d");
// off screen canvas
const text = document.createElement("canvas");
text.width = 512;
text.height = 16;
text.ctx = text.getContext("2d");
const font = new Image;
font.src = "https://i.stack.imgur.com/VXaVG.png"
font.addEventListener("load", () => {
drawColorString("000Black text#F00 Red text#FF0 Yellow#0F0 Green#0FF Cyan#00F Blue#F0F Magenta", 10, 4);
});
const grad = ctx.createLinearGradient(0, 0, canvas.width, canvas.height);
grad.addColorStop(0,"#FFF");
grad.addColorStop(1,"#000");
ctx.fillStyle = grad;
ctx.fillRect(0, 0, canvas.width, canvas.height);
function drawColorString(str, xpos, ypos) {
const parts = str.split("#");
var x = 0;
for (const part of parts) {
const color = part.slice(0,3);
const chars = part.slice(3);
for (const char of chars) {
drawChar(char, color, x);
x += 8;
}
}
colorText();
ctx.drawImage(text, xpos, ypos);
}
function colorText() {
text.ctx.globalCompositeOperation = "destination-in";
text.ctx.drawImage(text, 0, 8, text.width, 8, 0, 0, text.width, 8);
text.ctx.globalCompositeOperation = "source-over";
}
function drawChar(char, color, xpos) {
const c = char.charCodeAt(0);
const x = (c % 32) * 8;
const y = (c / 32 | 0) * 8;
text.ctx.fillStyle = "#" + color;
text.ctx.fillRect(xpos, 0, 8, 8);
text.ctx.drawImage(font, x, y, 8, 8, xpos, 8, 8, 8);
}
canvas {
border:1px solid black;
}
<canvas id="canvas"></canvas>
Используется изображение шрифта
Добавка
Второй способ - изменить исходное изображение, чтобы получить маскированную версию текста в черном, красном, зеленом, синем цветах.Чтобы отобразить цвет, нарисуйте черный текст, затем наложите, используя ctx.globalCompositeOperation = "lighter"
, чтобы добавить необходимые значения r, g, b.
Пример аддитивного метода
canvas.width = 430;
canvas.height = 16;
const ctx = canvas.getContext("2d");
const font = new Image;
font.src = "https://i.stack.imgur.com/FfGjd.png"
font.addEventListener("load", () => {
drawColorString("000Black text#F00 Red text#FF0 Yellow#0F0 Green#0FF Cyan#00F Blue#F0F Magenta", 10, 4);
});
const grad = ctx.createLinearGradient(0, 0, canvas.width, canvas.height);
grad.addColorStop(0,"#FFF");
grad.addColorStop(1,"#000");
ctx.fillStyle = grad;
ctx.fillRect(0, 0, canvas.width, canvas.height);
function drawColorString(str, x, y) {
const parts = str.split("#");
for (const part of parts) {
const color = part.slice(0,3);
const chars = part.slice(3);
for (const char of chars) {
drawChar(char, color, x, y);
x += 8;
}
}
}
function drawChar(char, color, xpos, ypos) {
const addLayer = (channel, amount) => {
if (amount) {
ctx.globalAlpha = amount;
ctx.drawImage(font, x, y + 64 * (channel + 1), 8, 8, xpos, ypos, 8, 8);
}
}
const red = parseInt(color[0] + color[0], 16) / 255;
const green = parseInt(color[1] + color[1], 16) / 255;
const blue = parseInt(color[2] + color[2], 16) / 255;
const c = char.charCodeAt(0);
const x = (c % 32) * 8;
const y = (c / 32 | 0) * 8;
ctx.globalAlpha = 1;
ctx.drawImage(font, x, y, 8, 8, xpos, ypos, 8, 8);
ctx.globalCompositeOperation = "lighter";
addLayer(0, red);
addLayer(1, green);
addLayer(2, blue);
ctx.globalCompositeOperation = "source-over"; // default
ctx.globalAlpha = 1;
}
canvas {
border:1px solid black;
}
<canvas id="canvas"></canvas>
Пример изображения, использованного в приведенном выше фрагменте.
Или вы можете объединить два метода и использовать аддитивный метод для рендеринга цветного текста на экранном холсте, а затем нарисовать этот холст на холсте дисплея.Это означает, что вам нужно рисовать только текст, когда он изменяется, а не каждый кадр, если он анимирован.