0

I have a simple class in Javascript and ran into a stupid issue. Am I missing something fundamental in JS?

In the below class, the constructor, initialize and setImage functions all work perfectly. Both "initialize" and "setImage" use the "this" variable to access properties on the class.

In all the little "onChangeXXX" functions at the bottom, I get an error, stating that "this" is null and therefore it can't find the properties like "filters".

When I use this class I can also bind from a Vue app (from outside the class) to the "SliderValues" and they change appropriately and the outside code can call the onChange methods.

The only issue at the moment seems to be that the this variable in the onChange methods is null - but I can't understand why this is the case.

import { fabric } from "fabric";

export default class FabricSvc {

  constructor( ref ) {

      this.imageRef= ref ,
      this.canvas= new fabric.Canvas(ref),
      this.image= null,
      
      this.filters= {
        brightness: new fabric.Image.filters.Brightness(),
        saturation: new fabric.Image.filters.Saturation(),
        contrast: new fabric.Image.filters.Contrast(),
        hue: new fabric.Image.filters.HueRotation(),
      };

      this.sliderValues= {
        brightness: 0,
        saturation: 0,
        contrast: 0,
        hue: 0,
      };

  }

  initialize() {
    var rect = new fabric.Rect({ fill: "red", width: 20, height: 20 });
    this.canvas.add(rect);
  }

  setImage(base64Image) {
    var imageUrl = "data:image/gif;base64," + base64Image;
    var that = this;

    fabric.Image.fromURL(imageUrl, function(oImg) {
     
      that.image = oImg;
      that.image.filters.push(that.filters.brightness);
      that.image.filters.push(that.filters.saturation);
      that.image.filters.push(that.filters.hue);
      that.image.filters.push(that.contrast);
      that.canvas.add(oImg).renderAll();
      that.canvas.setActiveObject(that.image);
    });

  }

  onChangeBrightness() {
    var that = this;
    that.filters.brightness.brightness.value = that.sliderValues.brightness;
    that.image.ApplyFilters();
  }

  onChangeSaturation() {
    this.filters.saturation.saturation.value = this.sliderValues.saturation;
    this.image.ApplyFilters();
  }

  onChangeHue() {
    this.filters.hue.hue.value = this.sliderValues.hue;
    this.image.ApplyFilters();
  }

  onChangeContrast() {
    this.filters.contrast.contrast.value = this.sliderValues.contrast;
    this.image.ApplyFilters();
  }
}

If it makes a difference, I'm calling this from VueJs (Vue2) with this:

  <input type="range" min="-1" max="1" step="0.01" v-model="fabricSvc.sliderValues.contrast"  @change="fabricSvc.onChangeBrightness" />

I doubt that the Vue side has anything to do with the problem though.

  • onChange prefix suggests that it's event handler, i.e a callback. This is confirmed by that you pass it as @change event handler – Estus Flask Apr 01 '22 at 06:43
  • For future reference, this question isn't exactly the same as the one linked to - since mine uses the Ecmascript class syntax - which is different from the linked question. This question explained it nicely though: https://stackoverflow.com/questions/38613150/scope-within-es6-classes – Mulciber Coder Apr 01 '22 at 07:37

0 Answers0