4

我似乎无法让fabric.js 的色调过滤器功能正常工作,或者找不到任何使用它的示例。我努力了:

img.filters[0] = new f.Tint({
    color:'green'
});

我也试过#00ff00代替green,但他们都只是把图像变黑。

我有许多只是黑色和透明的png(例如基本形状),我希望能够改变它们的颜色,我不知道这是否可能,但我认为色调听起来很有希望,我就是无法让它工作。

我也在照片上尝试过,只是变黑了,我在代码的同一位置使用了其他过滤器(如反转),效果很好。

任何帮助,将不胜感激。

更新: 使用了完整的 JS,图片三只是显示为一个黑盒子。

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

fabric.Image.fromURL('img/picture3.jpg', function(img) {
  img.set({
    left: 100,
    top: 120,
    angle: 0
  });
  img.filters[0] = new f.Tint({
      color:'00FF00'
  });
  img.applyFilters(canvas.renderAll.bind(canvas));
  canvas.add(img);
});
4

5 回答 5

4

我写了那个过滤器,我在我们的一个项目中大量使用它,到目前为止效果很好。但是我缺少的是对 applyFilters 的调用-也许您可以发布更多代码?

此外,我认为我总是应用以下颜色:

img.filters[0] = new f.Tint({
    color:'FF0000'
});

表示没有颜色名称,前面没有哈希。我知道那里的颜色解析器应该更健壮一些。还要确保此过滤器仅适用于具有 alpha 通道的图像 - 表示半透明 png 文件。

于 2012-10-12T08:05:00.007 回答
3

我分析了 Tint filter 的原始类,我发现这条线

var rgb = parseInt(this.color, 10).toString(16);

应该这样调整

var rgb = this.color;

使其按预期工作。当然,那么 rgb 变量也没用,直接改成 this.color就可以了,不过我个人更喜欢单行改。

我不确定将十六进制转换为整数然后再转换为字符串的最初目的是什么,因为这对我来说毫无意义。

您可能不想修改 fabric.js 源,所以我建议您创建自定义过滤器类,如本教程中过滤器部分所述:http: //fabricjs.com/fabric-intro-part-2/

于 2013-01-24T08:53:03.037 回答
1

对于 JPEG 图像或 PNG 图像(具有透明背景),我遇到了同样的问题。

我发现 Tint Class 不能正常工作,所以我稍微改变了它。您可以在 Google 网上论坛上找到该主题:https ://groups.google.com/forum/#!msg/fabricjs/DPN0WuRtc-o/ZGgIQK5F9xAJ

这是我的解决方法类(它通过使用完整的十六进制值来工作,但您可以轻松地将其调整为您的需要):

  fabric.Image.filters.Tint = fabric.util.createClass({

  type: 'Tint',

  /**
   * Constructor
   * @memberOf fabric.Image.filters.Tint.prototype
   * @param {Object} [options] Options object
   */
  //That's Different : HexColor
  initialize: function(HexColor) {
    this.color = HexColor;
  },


  /**
   * Applies filter to canvas element
   * @param {Object} canvasEl Canvas element to apply filter to
   */
  applyTo: function(canvasEl) {
    var context = canvasEl.getContext('2d'),
        imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),
        data = imageData.data;

    //That's different : computation of values
    var rUser = ((this.color).toString ()).substr(0,2);
    var gUser = ((this.color).toString ()).substr(2,2);
    var bUser = ((this.color).toString ()).substr(4,2);


    for (var i = 0, len = data.length; i < len; i += 4) {


        r = data[i];
        g = data[i + 1];
        b = data[i + 2];

        data[i] = parseInt ((r * parseInt (rUser, 16))/255);
        data[i + 1] = parseInt ((g * parseInt (gUser, 16))/255);
        data[i + 2] = parseInt ((b * parseInt (bUser, 16))/255);


    }

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

/**
 * Returns json representation of filter
 * @return {Object} json representation of filter
 */
toJSON: function() {
  return {
    type: this.type,
    color: this.color
  };
}

})`

我以这种方式使用它:

//$oCanvas is my fabric Canvas object
//data.color could be 'ff0000' but not 'f00' not anything else like fabric.Color
$img.filters[0] = new fabric.Image.filters.Tint(data.color); 
$img.applyFilters($oCanvas.renderAll.bind($oCanvas));

希望对某人有所帮助。

L.

编辑

在 Tint Filter 类中进行了一些更改(Github:https ://github.com/kangax/fabric.js/pull/862 )。

我再次测试它仍然没有运气,所以我再次稍微改变了它。您可以在 Google Groups ( https://groups.google.com/forum/#!topic/fabricjs/DPN0WuRtc-o )上找到源代码 + 说明

编辑#2

好的,所以 Kienz 制作了一个 JSFiddle ( http://jsfiddle.net/Kienz/4wGzk/ ),它使用带有错误修复的 Tint Filter 类,他让它工作了。我建议按照他的方式实施它。

于 2013-09-20T12:11:45.583 回答
0

我在做类似的事情时注意到的一件事是,在将图像本身添加到画布之前,过滤器将不起作用。

于 2015-03-21T22:06:49.467 回答
0

I was having the same problem. It turned out to be the version of fabric js I was using. Without grabbing the latest, in fear of breaking other things, I grabbed only what I needed and used it as a custom filter overriding the current tint implementation.

Here's what I used:

/**
   * Tint filter class
   * Adapted from <a href="https://github.com/mezzoblue/PaintbrushJS">https://github.com/mezzoblue/PaintbrushJS</a>
   * @class fabric.Image.filters.Tint
   * @memberOf fabric.Image.filters
   * @extends fabric.Image.filters.BaseFilter
   * @see {@link fabric.Image.filters.Tint#initialize} for constructor definition
   * @see {@link http://fabricjs.com/image-filters/|ImageFilters demo}
   * @example <caption>Tint filter with hex color and opacity</caption>
   * var filter = new fabric.Image.filters.Tint({
   *   color: '#3513B0',
   *   opacity: 0.5
   * });
   * object.filters.push(filter);
   * object.applyFilters(canvas.renderAll.bind(canvas));
   * @example <caption>Tint filter with rgba color</caption>
   * var filter = new fabric.Image.filters.Tint({
   *   color: 'rgba(53, 21, 176, 0.5)'
   * });
   * object.filters.push(filter);
   * object.applyFilters(canvas.renderAll.bind(canvas));
   */
  fabric.Image.filters.Tint = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Tint.prototype */ {

    /**
     * Filter type
     * @param {String} type
     * @default
     */
    type: 'Tint',

    /**
     * Constructor
     * @memberOf fabric.Image.filters.Tint.prototype
     * @param {Object} [options] Options object
     * @param {String} [options.color=#000000] Color to tint the image with
     * @param {Number} [options.opacity] Opacity value that controls the tint effect's transparency (0..1)
     */
    initialize: function(options) {
      options = options || { };

      this.color = options.color || '#000000';
      this.opacity = typeof options.opacity !== 'undefined'
                      ? options.opacity
                      : new fabric.Color(this.color).getAlpha();

      console.log(this.color + " " + this.opacity);                
    },

    /**
     * Applies filter to canvas element
     * @param {Object} canvasEl Canvas element to apply filter to
     */
    applyTo: function(canvasEl) {
      var context = canvasEl.getContext('2d'),
          imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),
          data = imageData.data,
          iLen = data.length, i,
          tintR, tintG, tintB,
          r, g, b, alpha1,
          source;

      source = new fabric.Color(this.color).getSource();

      tintR = source[0] * this.opacity;
      tintG = source[1] * this.opacity;
      tintB = source[2] * this.opacity;

      alpha1 = 1 - this.opacity;

      for (i = 0; i < iLen; i+=4) {
        r = data[i];
        g = data[i + 1];
        b = data[i + 2];

        // alpha compositing
        data[i] = tintR + r * alpha1;
        data[i + 1] = tintG + g * alpha1;
        data[i + 2] = tintB + b * alpha1;
      }

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

    /**
     * Returns object representation of an instance
     * @return {Object} Object representation of an instance
     */
    toObject: function() {
      return extend(this.callSuper('toObject'), {
        color: this.color,
        opacity: this.opacity
      });
    }
  });
于 2015-03-12T13:01:10.540 回答