0

我正在做 Spritefonts,目前在 WebGL 上为它实现了色调!

WebGL spritefont 色调

但是在canvas2d上我试图通过ctx.globalCompositeOperation但它显示以下

canvas2d spritefont 色调问题

如您所见,黑色像素也被填充...

这是我的代码...

var size = 32;
var x = 200;
var y = 200;
var spacing = 0;
for (var i = 0; i < txt.length; i++) {
    var q = fonts[0].info[txt[i]];
    ctx.save();
    if (q) ctx.drawImage(fonts[0].src, q.x, q.y, q.w, q.h, x + (spacing || 0) + (i * size), y, size, size);
    ctx.globalCompositeOperation = "source-in";
    ctx.fillStyle = "green";
    ctx.fillRect(0, 0, canvas.width, canvas.height);
    ctx.restore();
}

当尝试使用“变暗”模式时,它会正确填充但也会填充背景(我不想要这个......)

使用时的canvas2d图像色调

我也试过了ctx.getImageData()ctx.putImageData()但没有显示字母

var size = 32;
var x = 200;
var y = 200;
var spacing = 0;
for (var i = 0; i < txt.length; i++) {
    var q = fonts[0].info[txt[i]];
    if (q) {
        ctx.drawImage(fonts[0].src, q.x, q.y, q.w, q.h, x + (spacing || 0) + (i * size), y, size, size);
        f = ctx.getImageData(x + (spacing || 0) + (i * size), y, size, size);
        for (var i = 0; i < f.data.length; i += 4) {
            f.data[i + 0] = 100;
            f.data[i + 1] = 100;
            f.data[i + 2] = 255;
            f.data[i + 3] = 255;
        }
        ctx.putImageData(f, x + (spacing || 0) + (i * size), y, 0, 0, size, size);
    }
}               

我使用的图像来自这里

4

2 回答 2

0

通过对填充背景的黑色像素使用“变亮”模式进行修复,然后应用“变暗”模式而不是“源输入”,一切都完成了!

var size = 32;
var x = 200;
var y = 200;
var spacing = 0;
for (var i = 0; i < txt.length; i++) {
    var q = fonts[0].info[txt[i]];
    ctx.save();
    ctx.globalCompositeOperation = "lighten";
    ctx.fillStyle = ctx.canvas.style.backgroundColor;
    ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
    if (q) ctx.drawImage(fonts[0].src, q.x, q.y, q.w, q.h, x + (spacing || 0) + (i * size), y, size, size);
    ctx.globalCompositeOperation = "darken";
    ctx.fillStyle = "green";
    ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
    ctx.restore();
}
于 2020-12-23T18:28:17.337 回答
0

这是我发现的更好的方法:

  1. 创建尺寸符合 spritefont 图像尺寸的画布
  2. 在创建的画布中保存上下文状态
  3. 使用spritefontfillStyle文本颜色 (Tint) 创建的画布上下文集
  4. globalAlpha创建的画布上下文设置为不透明度
  5. 使用 spritefont 文本颜色(Tint)填充创建的画布背景
  6. 在创建的画布上下文中应用“destination-atop”复合模式
  7. 将创建的画布上下文重置globalAlpha为 1(默认)
  8. 在创建的画布上绘制 spritefont 图像
  9. 在创建的画布中恢复上下文状态
  10. 然后,让默认画布上下文(未创建一个)从 spritefont 图像中绘制字符,所以我们让它绘制我们创建的部分画布(注意 spritefont 图像填充所有创建的画布)
  11. 完毕!
var size = 32;
var x = 200;
var y = 200;
var spacing = 0;
var opacity = 0.8;
var color = "green";
for (var i = 0; i < txt.length; i++) {
    var q = fonts[0].info[txt[i]];
    var c = document.createElement("canvas").getContext("2d");
    c.canvas.width = fonts[0].src.width;
    c.canvas.height = fonts[0].src.height;
    c.save();
    c.fillStyle = color;
    c.globalAlpha = opacity || 0.8;
    c.fillRect(0, 0, c.canvas.width, c.canvas.height);
    c.globalCompositeOperation = "destination-atop";
    c.globalAlpha = 1;
    c.drawImage(fonts[0].src, 0, 0);
    c.restore();
    if (q) ctx.drawImage(c.canvas, q.x, q.y, q.w, q.h, x + (i * (size + spacing)), y, size, size);
}
于 2020-12-25T13:46:21.567 回答