简体   繁体   English

Fabric.js - 色调过滤器

[英]Fabric.js - Tint filter

I can't seem to get the tint filter feature of fabric.js to work, or find any example of it being used. 我似乎无法使fabric.js的色调过滤器功能工作,或找到它正在使用的任何示例。 I have tried: 我试过了:

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

I've also tried #00ff00 instead of green , but both of them just turn the image black. 我也试过#00ff00而不是green ,但两者都只是把图像变成黑色。

I have a number of png's that are just only black and transparent (eg basic shapes), and I want to be able to change the colour of them, I don't know if this is possible or not, but I figured tint sounded promising, I just can't get it to work. 我有一些只是黑色和透明的png(例如基本形状),我希望能够改变它们的颜色,我不知道这是否可能,但我认为它听起来很有希望,我只是无法让它工作。

I've also tried it on photos, just turns black, and I've used other filters (like invert) in the same place in the code and it worked fine. 我也尝试过照片,只是变黑了,我在代码中的同一个地方使用了其他过滤器(如反转)并且工作正常。

Any help would be appreciated. 任何帮助,将不胜感激。

UPDATE: Full JS used, picture three just appears as a black box. 更新:使用完整的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);
});

I wrote that filter and I'm using it heavily in one of our projects and it worked good so far. 我写了那个过滤器,我在我们的一个项目中大量使用它,到目前为止它运行良好。 But what I'm missing there is the call to applyFilters - maybe you could post a little more code? 但我缺少的是对applyFilters的调用 - 也许你可以发布一些代码?

Also I think I always applied the colors like: 另外我觉得我总是应用以下颜色:

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

Means no color names, no hash in front. 意味着没有颜色名称,前面没有哈希。 I know that the parser for the colors should be a little more robust there. 我知道颜色的解析器在那里应该更加健壮。 Also be sure that this filter will only work for images that have an alpha channel - means semi transparent png files. 另外请确保此过滤器仅适用于具有Alpha通道的图像 - 表示半透明png文件。

I analysed the original class for Tint filter and I have found that this line 我分析了Tint过滤器的原始类,我发现了这一行

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

should be adjusted like this 应该像这样调整

var rgb = this.color;

to make it work as expected. 使其按预期工作。 Of course, then rgb variable is useless and you can change it to this.color directly, but I personally prefer single line changes. 当然,然后rgb变量是无用的,你可以直接将它改为this.color ,但我个人更喜欢单行更改。

I'm not sure what was the original purpose of converting hex to integer and then to string as it makes no sense to me. 我不确定将十六进制转换为整数然后转换为字符串的最初目的是什么,因为它对我没有意义。

You would propably not want to modify the fabric.js source, so I suggest you to create custom filter class as mentioned in this tutorial under Filters section: http://fabricjs.com/fabric-intro-part-2/ 您可能不希望修改fabric.js源代码,因此我建议您创建自定义过滤器类,如本教程中“过滤器”部分所述: http//fabricjs.com/fabric-intro-part-2/

I had the same problem with either a JPEG image or PNG image (with transparent background). 我对JPEG图像或PNG图像(透明背景)也有同样的问题。

I found out that the Tint Class wasn't working properly for that matter so I slightly changed it. 我发现Tint Class在这个问题上没有正常工作,所以我稍微改了一下。 You can find the thread on Google Groups : https://groups.google.com/forum/#!msg/fabricjs/DPN0WuRtc-o/ZGgIQK5F9xAJ 您可以在Google网上论坛中找到该主题: https//groups.google.com/forum/#! msg / fabricjs / DPN0WuRtc- o / ZGgIQK5F9xAJ

Here's my workaround class (which works by using a full hexadecimal value, but you could easily adapt it to your needs) : 这是我的解决方法类(通过使用完整的十六进制值来工作,但您可以轻松地根据您的需要调整它):

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

})` })`

I use it this way tho : 我这样使用它:

//$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));

Hope that helps someone. 希望能帮助别人。

L. L.

EDIT 编辑

Some changes have been done inside the Tint Filter Class (Github : https://github.com/kangax/fabric.js/pull/862 ). 在Tint过滤器类中进行了一些更改(Github: https//github.com/kangax/fabric.js/pull/862 )。

I tested it again with still no luck so I slightly changed it again. 我再次测试它仍然没有运气所以我稍微改变了一下。 You can find source code + explanation on Google Groups ( https://groups.google.com/forum/#!topic/fabricjs/DPN0WuRtc-o ) 您可以在Google网上论坛找到源代码+说明( https://groups.google.com/forum/#!topic/fabricjs/DPN0WuRtc-o

EDIT #2 编辑#2

Ok so Kienz made a JSFiddle ( http://jsfiddle.net/Kienz/4wGzk/ ) that uses the Tint Filter Class with the bugfix and he got it working. 好吧Kienz制作了一个JSFiddle( http://jsfiddle.net/Kienz/4wGzk/ ),它使用带有错误修正的Tint过滤器类,并让它运行起来。 I'd recommend to implement it the way he did. 我建议按照他的方式实施它。

I was having the same problem. 我遇到了同样的问题。 It turned out to be the version of fabric js I was using. 它原来是我正在使用的结构js的版本。 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
      });
    }
  });

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM