【问题标题】:How to draw a monochrome image onto a canvas, but use a different color?如何在画布上绘制单色图像,但使用不同的颜色?
【发布时间】:2020-01-24 08:50:53
【问题描述】:

我有一张黑白图像。如有必要,我可以将其转换为透明和白色。

如何将此图像绘制到画布上,用任意颜色替换白色?

我希望能够使用如下字体在画布上绘制文本,使用不同的颜色。我不想拥有图像的多个副本。

【问题讨论】:

  • 我认为使用白色背景/透明前景形式,您可以先在要写入的位置后面绘制一个矩形,然后在其上应用图像

标签: javascript html html5-canvas


【解决方案1】:

有两种方法可以做到这一点。

离屏

创建一个屏幕外画布, 将文本渲染到该画布,然后使用ctx.globalCompositeOperation = "color"(更新我的错误应该是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>

上面sn-p中使用的图像示例。

或者您可以结合这两种方法并使用additive 方法将彩色文本渲染到屏幕外画布,然后将该画布绘制到显示画布上。这意味着您只需要在文本发生变化时绘制文本,而不是动画时的每一帧。

【讨论】:

  • 善用globalCompositeOperation,太棒了!
  • 为我工作!非常感谢。
【解决方案2】:
  • 执行此操作的最简单方法是将图像中的白色替换为您想要颜色的透明“孔”,然后使用.fillstyle 更改画布的背景。
  • 将图像另存为 png,打开一些照片编辑软件,然后在图像中您希望着色的位置擦出一个洞,以便您看到方格透明背景。
  • 将此文件移动到项目中存储图像的任何位置。
  • 将图像添加到您的画布元素中,确保它填满整个画布。使用以下代码更改画布的背景:

let canvas = document.getElementByID("colourthis") let ctx = canvas.getContext("2D") ctx.fillstyle = 'red'

  • 图像的透明部分现在将变为红色。
  • 您可以使用某种随机发生器来获得其他颜色。
  • 使用ctx.fillStyle = "transparent" 获取透明背景。

这就是我在 vanilla JS 中执行此操作的方式,没有 JQuery 或任何东西。还有其他方法,但从您使用的标签来看,我怀疑您是否使用任何插件来处理此类事情。

【讨论】:

    猜你喜欢
    • 2023-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-10
    • 2012-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多