Fabric.js - 色调过滤器

时间:2012-10-11 11:52:38

标签: javascript html5 canvas fabricjs

我似乎无法使fabric.js的色调过滤器功能起作用,或者找到它正在使用的任何示例。我试过了:

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

我也尝试过#00ff00而不是green,但两者都只是将图片变为黑色。

我有一些png只是黑色和透明(例如基本形状),我希望能够改变它们的颜色,我不知道这是否可能,但我想色彩听起来很有希望,我只是无法让它发挥作用。

我也在照片上尝试过,只是变黑了,我在代码中的同一个地方使用了其他过滤器(如反转)并且工作正常。

任何帮助将不胜感激。

更新 使用完整的JS,图片3只显示为黑盒子。

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);
});

5 个答案:

答案 0 :(得分:4)

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

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

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

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

答案 1 :(得分:3)

我分析了Tint过滤器的原始类,我发现了这一行

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

应该像这样调整

var rgb = this.color;

使其按预期工作。当然,那么rgb变量是无用的,您可以直接将其更改为 this.color ,但我个人更喜欢单行更改。

我不确定将十六进制转换为整数然后转换为字符串的最初目的是什么。因为它对我没用。

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

答案 2 :(得分: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过滤器类(Github:https://github.com/kangax/fabric.js/pull/862)内部进行了一些更改。

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

编辑#2

好的,所以Kienz制作了一个JSFiddle(http://jsfiddle.net/Kienz/4wGzk/),它使用带有错误修正的Tint过滤器类,并让它运行起来。我建议按照他的方式实施它。

答案 3 :(得分:0)

我遇到了同样的问题。它原来是我正在使用的结构js的版本。在没有抓住最新产品的情况下,由于害怕破坏其他东西,我只抓住了我需要的东西并将其用作覆盖当前色调实现的自定义过滤器。

这是我使用的:

/**
   * 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
      });
    }
  });

答案 4 :(得分:0)

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