HTML5: 在画布上反转文字颜色

6
我希望在画布上以背景的反色绘制文本(以确保文本无论背景颜色如何都可以读取)。 我相信在旧式的位块传输中,这是一种异或操作。
如何实现?

不确定它是否真的可读,但肯定不能使用灰色。 - Serge
@PauloDiogo 那是针对图像的,我需要绘制文本。 - Maestro
1
@Joshua 使用这个 http://jsperf.com/inverse-hex-colours 和 context.fillStyle = '<在此处输入十六进制代码>'; http://www.html5canvastutorials.com/tutorials/html5-canvas-text-color/ - user330606
@PauloDiogo:对于您提到的六角反相器,我给予+1的好评。但是,Joshua:自动反转颜色可能会导致一些非常“惊艳”的颜色组合和难以阅读的文本-请谨慎使用;) - markE
2个回答

11

更新:现在大多数新版浏览器都支持混合模式“差异”,可以实现相同的效果。

context.globalCompositeOperation = "difference";

更新演示

旧答案:

人们可能会认为合成的XOR模式可以做到这一点,但不幸的是,画布的XOR仅XOR alpha位。

通过应用以下代码,我们可以获得如下结果:

enter image description here

你可以像这样为画布创建一个扩展:
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);

这可能看起来像很多操作,但速度相当快。

演示(如果您对闪烁敏感,请注意警告)

(迷幻背景只是为了有一些变化,因为fiddle需要外部图像,而大多数图像在使用像素处理时都会受到CORS的限制。)


1
+1,我只是希望复合操作在这方面有更多的支持。 - nondefault
这个演示能否更新一下,以免引起癫痫发作? :P 顺便说一句,回答很棒。 - aug

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接