我想说,最好的方法是使用图像过滤器。幸运的是,Fabric 提供了一个具有非常相似功能的图像过滤器 - RemoveColor (http://fabricjs.com/docs/fabric.js.html#line23120)。我们可以采用该实现,稍微调整一下以替换为可配置的颜色而不是删除,这样就可以了。
我们对RemoveColor 类进行了三个主要更改以创建我们的ReplaceColor 类:
- 添加一个
replacementColor 字段,该字段采用 4 个宽数组替换颜色
- 修改 webGL 以获取替换颜色的额外参数:
fragmentSource: 'precision highp float;\n' +
'uniform sampler2D uTexture;\n' +
'uniform vec4 uLow;\n' +
'uniform vec4 uHigh;\n' +
'uniform vec4 uRep;\n' + // New variable for replacement color
'varying vec2 vTexCoord;\n' +
'void main() {\n' +
'gl_FragColor = texture2D(uTexture, vTexCoord);\n' +
'if(all(greaterThan(gl_FragColor.rgb,uLow.rgb)) && all(greaterThan(uHigh.rgb,gl_FragColor.rgb))) {\n' +
'gl_FragColor.rgb = uRep.rgb;\n' + // Here we set the color instead of 0-ing out the alpha
'gl_FragColor.a = uRep.a;\n' +
'}\n' +
'}',
applyTo2d: function (options) {
var imageData = options.imageData,
data = imageData.data, i,
distance = this.distance * 255,
r, g, b,
source = new fabric.Color(this.color).getSource(),
lowC = [
source[0] - distance,
source[1] - distance,
source[2] - distance,
],
highC = [
source[0] + distance,
source[1] + distance,
source[2] + distance,
];
for (i = 0; i < data.length; i += 4) {
r = data[i];
g = data[i + 1];
b = data[i + 2];
if (r > lowC[0] &&
g > lowC[1] &&
b > lowC[2] &&
r < highC[0] &&
g < highC[1] &&
b < highC[2]) {
data[i] = this.replacementColor[0]; // Here we also modify the color directly instead of 0-ing out the alpha
data[i + 1] = this.replacementColor[1];
data[i + 2] = this.replacementColor[2];
data[i + 3] = this.replacementColor[3];
}
}
}
JSFiddle:https://jsfiddle.net/8coka6yv/
请注意,我在 JSFiddle 上调高了距离场,所以这是一个相当大的修改。默认值通常为0.02。