Search code examples
javascriptvue.jsfabricjs

Updating FabricJS objects from Vue method


I am trying to update a Fabricjs canvas through Vue controls. I am initializing the canvas through 'mounted()', but do not know how to access the canvas in a function without passing the canvas as an argument.

Here is a demonstration of my predicament. I'd like the button to resize the circle.

HTML:

<div id="app">
  <a href="#" @click="resize()">RESIZE</>
  <canvas id="c"></canvas>
</div>

JS:

 new Vue({
  el: "#app",
  data: {
    title: "Default title",
    message: null,
    canvas: null
  },
  mounted() {
    const canvas = new fabric.Canvas("c", {
      width: 500,
      height: 500
    });
    this.canvas = canvas;
    this.loadCir(canvas);
  },
  methods: {
    loadCir(canvas) {
      const cir = new fabric.Circle({
        fill: "red",
        radius: 50,
        top: 10,
        left: 10
      });
      cir.name = "circle";
      canvas.add(cir);
    },
    resize() {
      this.canvas.getObjects().forEach(function (targ) {
        if (targ.name == "circle") {
          targ.radius = 100;
        }
      });
    }
  }
});

https://codepen.io/shnlmn/pen/JjbrKNL

The result of this script is:

TypeError: Cannot read property 'getObjects' of undefined

I feel like storing the canvas into data is not a great idea, but I am not sure how to make it accessible to the rest of the app.

What is the best way to make Fabricjs objects accessible from functions such as this?


Solution

  • Looks like the next resizing part of your code isn't working. But to help you get past your issue with the canvas.getObjects() returning undefined.

    What you need to do is to when using data properties you need to just make sure everything is referencing the data property. You were creating variables and saving them to the data property which is unneeded, you can just do all your work on this.canvas

    new Vue({
      el: "#app",
      data: {
        title: "Default title",
        message: null,
        canvas: null
      },
      mounted() {
        this.canvas = new fabric.Canvas("c", {
          width: 500,
          height: 500
        });
        this.canvas.getContext('2d');
        this.loadCir();
      },
      methods: {
        loadCir() {
          const cir = new fabric.Circle({
            fill: "red",
            radius: 50,
            top: 10,
            left: 10
          });
          cir.name = "circle";
          this.canvas.add(cir);
        },
        resize() {
          this.canvas.getObjects().forEach(function (targ) {
            if (targ.name == "circle") {
              targ.height = 100;
            }
          });
        }
      }
    });
    

    Once you reference this.canvas everywhere and actually do the work On your data property, then your getObjects is defined. However your resizing isn't working so you just need to get over that hump and you're away!

    #note: i was attempting to change the height of your circle, and not the radius