问题描述
我正在做 Spritefonts,目前在 WebGL 上为它实现了色调!
但在 canvas2d 上,我尝试通过 ctx.globalCompositeOperation
执行此操作,但显示如下
如您所见,黑色像素也被填充...
这是我的代码...
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,canvas.width,canvas.height);
ctx.restore();
}
当尝试使用“变暗”模式时,它会正确填充但也会填充背景(我不想要这个......)
我也试过 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,size);
f = ctx.getimageData(x + (spacing || 0) + (i * 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,size);
}
}
解决方法
通过对具有填充背景的黑色像素使用“变亮”模式进行修复,然后应用“变暗”模式而不是“输入源”并全部完成!
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,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,ctx.canvas.height);
ctx.restore();
}
,
我发现这是更好的方法:
- 创建尺寸符合 spritefont 图像尺寸的画布
- 在创建的画布中保存上下文状态
- 使用 spritefont 文本颜色 (Tint) 设置创建的画布上下文的
fillStyle
- 将创建的画布上下文的
globalAlpha
设置为不透明度 - 使用 spritefont 文本颜色(色调)填充创建的画布背景
- 在创建的画布上下文中应用“destination-atop”复合模式
- 将创建的画布上下文的
globalAlpha
重置为 1(默认) - 在创建的画布上绘制精灵字体图像
- 在创建的画布中恢复上下文状态
- 然后,让默认画布上下文(未创建)从 spritefont 图像中绘制字符,因此我们让它绘制我们创建的画布的一部分(注意 spritefont 图像填充了所有创建的画布)
- 完成!
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,c.canvas.width,c.canvas.height);
c.globalCompositeOperation = "destination-atop";
c.globalAlpha = 1;
c.drawImage(fonts[0].src,0);
c.restore();
if (q) ctx.drawImage(c.canvas,x + (i * (size + spacing)),size);
}