我可以在 fabricjs 中使用图像过滤器在单个图像上应用两种阴影颜色吗?

Can I apply two shaded color on single image with image filter in fabricjs?

我有两种像这样的阴影颜色:

我想用 fabric js 图像过滤器在单个图像上应用渐变颜色。

基本上我为颜色添加了两个调色板。我需要的是当我从调色板更改颜色时,两种颜色都适用于单个图像,如上图。这可能吗?

我正在设计如下的 T 恤:

我想将这两种颜色应用到 T 恤的大灰色图像上。目前不同的颜色图像在 fabric js 中作为单独的图像和单独的对象工作,我想将这些颜色应用于单个灰色图像部分。

有什么方法可以实现吗?

由于 FabricJs 本身不提供将渐变应用于 Image 的可能性,您可以使用以下代码片段中包含的 ImageFilter 来完成您的任务。

(function(global) {

      'use strict';

      var fabric = global.fabric || (global.fabric = {}),
        extend = fabric.util.object.extend;

      fabric.Image.filters.GradientEffect = fabric.util.createClass(fabric.Image.filters.BaseFilter, {

        type: 'GradientEffect',

        initialize: function (options) {
          options = options || {};
          this.gradient = options.gradient || {};
          this.img = options.img;
        },

        applyTo: function(canvasEl) {
          var gr = this.gradient;
          var w = this.img._element.naturalWidth;
          var h = this.img._element.naturalHeight;
          var hc = document.createElement('canvas');

          hc.setAttribute('width', w);
          hc.setAttribute('height', h);

          var fhc = new fabric.Canvas(hc);
          var rect = new fabric.Rect({
            fill: 'transparent',
            width: w,
            height: h
          });

          rect.setGradient('fill', gr);

          fhc.add(rect);
          fhc.renderAll();

          var ifhcContext = fhc.getContext('2d');
          var fhcImageData = ifhcContext.getImageData(0, 0, fhc.width, fhc.height);
          var fhcData = fhcImageData.data;

          var context = canvasEl.getContext('2d'),
            imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),
            data = imageData.data;

          for (var i = 0, n = data.length; i < n; i += 4) {
            if(data[i] != 0 && data[i+1] != 0 && data[i+2] != 0) {
              data[i] += fhcData[i];
              data[i + 1] += fhcData[i + 1];
              data[i + 2] += fhcData[i + 2];

            }
          }

          context.putImageData(imageData, 0, 0);
        },

        toObject: function() {
          return extend(this.callSuper('toObject'), {
            gradient: this.gradient

          });
        }
      });

      fabric.Image.filters.GradientEffect.fromObject = function(object) {
        return new fabric.Image.filters.GradientEffect(object);
      };

    })(typeof exports !== 'undefined' ? exports : this);


var canvas = new fabric.Canvas('c');

fabric.Image.fromURL('http://i.imgur.com/bkMw5mx.png', function(img) {
  var gr = {
    x1: 0,
    y1: 0,
    x2: 0,
    y2: img.height,
    colorStops: {
      0: "red",
      1: "blue",
    }
  };
  img.filters.push(new fabric.Image.filters.GradientEffect({
    gradient: gr,
    img: img,
    
  }));
  img.applyFilters(canvas.renderAll.bind(canvas));
  canvas.add(img.set({
    width: 150,
    height: 150,

  }));
}, {
  crossOrigin: ''
});
.floatLeft {
  display: inline-block;
  border: 2px solid #ccc;
}
.placeholder {
  margin-left: 10px;
}
<script src="//cdnjs.cloudflare.com/ajax/libs/fabric.js/1.5.0/fabric.min.js"></script>
<img class='image floatLeft' src='http://i.imgur.com/bkMw5mx.png' width='200' height='200'>
<div class='placeholder floatLeft'>
  <canvas id='c' width='300' height='300'></canvas>
  <div>


这项工作是通过 applyTo 函数完成的,我即时创建了一个新的 Canvas 并在其上放置了一个填充了参数渐变的矩形,然后逐个像素地应用了选择的相对颜色从梯度。 唯一的问题是您的图像无法即时调整大小,因为图像的 imageData 和渐变的 imageData 应该具有相同的长度:

applyTo: function(canvasEl) {
          var gr = this.gradient;
          var w = this.img._element.naturalWidth;
          var h = this.img._element.naturalHeight;
          var hc = document.createElement('canvas');

          hc.setAttribute('width', w);
          hc.setAttribute('height', h);

          var fhc = new fabric.Canvas(hc);
          var rect = new fabric.Rect({
            fill: 'transparent',
            width: w,
            height: h
          });

          rect.setGradient('fill', gr);

          fhc.add(rect);
          fhc.renderAll();

          var ifhcContext = fhc.getContext('2d');
          var fhcImageData = ifhcContext.getImageData(0, 0, fhc.width, fhc.height);
          var fhcData = fhcImageData.data;

          var context = canvasEl.getContext('2d'),
            imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),
            data = imageData.data;

          for (var i = 0, n = data.length; i < n; i += 4) {
            if(data[i] != 0 && data[i+1] != 0 && data[i+2] != 0) {
              data[i] += fhcData[i];
              data[i + 1] += fhcData[i + 1];
              data[i + 2] += fhcData[i + 2];

            }
          }

          context.putImageData(imageData, 0, 0);
        }