Search code examples
javascriptvue.jscanvascontrolsfabricjs

FabricJS: Object controls not working until common selection


I am creating a product configurator using Vue and FabricJS.

I have created a canvas using

this.canvas = new fabric.Canvas("canvas");
<template>
  <div id="wrapper">
    <div id="left"></div>
    <canvas id="canvas"/>
  </div>
</template>

After I add an object to the canvas (IText, Textbox, Image, using new fabric.IText(...)) and select it with mouse, I am not able to use object controls to resize, scale, skew or rotate the object. However, I can move the object on canvas. After I add another object, select both of them at once and deselect again, the controls are all of a sudden working as intended. I was not able to reproduce the issue on JsFiddle, everything works there.

Controls not working until both objects are selected

I encoutered the problem using various browsers.

Am I missing some canvas property, which enables this immediately after adding? Or is that a bug in Fabric.js?


Solution

  • After some time I used a workaround: I added an empty helper object to the canvas right after creating it and then after adding each new object I programatically select and deselect all of them. After that all object are behaving correctly. I know this is a "hack", but it works :)

    this.canvas = new fabric.Canvas("canvas", {
        ...canvasProps
    });
    
    const helperObj = new fabric.Object({});    //abstract invisible object
    helperObj.set("selectable", false);         //so the user is not able to select and modify it manually
    this.canvas.add(helperObj);
    
    this.canvas.on("object:added", () => {
      //workaround - selecting all objects to enable object controls
    
      let objects = this.canvas.getObjects();
      var selection = new fabric.ActiveSelection(objects, {
         canvas: this.canvas,
      });
      this.canvas.setActiveObject(selection);   //selecting all objects...
      this.canvas.discardActiveObject();        //...and deselecting them
      this.canvas.requestRenderAll();
    });