我想在画布上以背景的反色绘制文本(以确保文本无论背景颜色是否可读)。我相信oldskool bitblt-ing,这是一个XOR操作。
怎么做?
答案 0 :(得分:8)
更新:大多数较新的浏览器现在支持混合模式“差异”,可以达到相同的效果。
context.globalCompositeOperation = "difference";
<强> Updated demo 强>
旧回答:
有人应该认为合成的XOR模式可以做到这一点,但不幸的是,画布'XOR只对异位进行异或。
通过应用以下代码,我们可以收到如下结果:
您可以像这样对画布进行扩展:
CanvasRenderingContext2D.prototype.fillInversedText =
function(txt, x, y) {
//code - see below
}
现在你可以在上下文中调用它作为普通的fillText,但稍有改动:
ctx.fillInversedText(txt, x, y);
为此,我们首先执行以下操作 - 测量文本。目前我们只能计算文本的宽度然后假定高度。这可能会或可能不会很好,因为字体可能非常高等等。幸运的是,这将在未来发生变化,但现在:
var tw = this.measureText(txt).width;
var th = parseInt(ctx.font, '10');
th = (th === 0) ? 10 : th; //assume default if no font and size is set
接下来我们要做的是设置一个离屏画布来绘制我们想要反转的文本:
var co = document.createElement('canvas');
co.width = tw;
co.height = th;
然后绘制实际文本。颜色无关紧要,因为我们只对这个画布的alpha通道感兴趣:
var octx = co.getContext('2d');
octx.font = this.font;
octx.textBaseline = 'top';
octx.fillText(txt, 0, 0);
然后我们提取我们想要绘制反转文本的区域的像素缓冲区以及现在包含我们文本的屏幕外画布的所有像素:
var ddata = this.getImageData(x, y, tw, th);
var sdata = octx.getImageData(0, 0, tw, th);
var dd = ddata.data; //cache for increased speed
var ds = sdata.data;
var len = ds.length;
然后我们反转像素的alpha通道大于0的每个像素。
for (var i = 0; i < len; i += 4) {
if (ds[i + 3] > 0) {
dd[i] = 255 - dd[i];
dd[i + 1] = 255 - dd[i + 1];
dd[i + 2] = 255 - dd[i + 2];
}
}
最后放回倒像:
this.putImageData(ddata, x, y);
这可能看起来像很多操作,但速度相当快。
Demo (警告您是否对闪烁敏感)
(迷幻背景只是有一些变化,因为小提琴需要外部图像,当我们使用像素操作时,大多数都被CORS阻止。)
答案 1 :(得分:0)
我删除了我的旧答案,因为它没有解决问题。截至最近,有新的globalCompositeOperation
可以做各种各样的好事。我创建了an example,展示了如何获取反向文本。如果链接断开,该方法基本上是这样的:
ctx.globalCompositeOperation = "difference";
ctx.fillStyle = "white";
//draw inverted things here
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation