Fabric.js Group

Select an object in a group.

by Andrea Bogazzi

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/4.0.0-beta.12/fabric.min.js"></script>
<canvas id="canvas" height="480" width="320"></canvas>

CSS

html,
body {
  align-items: center;
  justify-content: center;
  background-color: #1f2227;
  display: flex;
  height: 100%;
  margin: 0;
  padding: 0;
  width: 100%;
}

.canvas-container {
  background-color: #121212;
  border-radius: 4px;
  overflow: hidden;
}

JavaScript

/**
 * GroupExtended class
 * @extends fabric.Group
 * @todo preserve object stacking
 * @todo fix bug object coords on group scaling
 */
var GroupExtended = fabric.util.createClass(fabric.Group, {
  /**
   * Type of an object
   * @type String
   * @default
   */
  type: "group-extended",
  
  subTargetCheck: true,

  /**
   * When set to `false`, object's controlling borders are not rendered
   * @type Boolean
   * @default
   */
  hasBorders: true,

  /**
   * Array specifying dash pattern of an object's borders (hasBorder must be true)
   * @type Array
   * @default
   */
  borderDashArray: [5, 5],

  /**
   * Selected object
   * @type fabric.Object
   */
  _selectedObject: null,

  /**
   * Remove solid border from selected object
   */
  _removeSelectedBorder: function () {
    this.canvas.clearContext(this.canvas.contextTop);
  },

  /**
   * Show solid border from selected object
   */
  _showSelectedBorder: function () {
    this._removeSelectedBorder();
    if (this._selectedObject) {
    	var ctx = this.canvas.contextTop;
      var m = this.calcTransformMatrix();
      ctx.save();
      this._selectedObject._renderControls(ctx, {
        hasControls: false,
      });
      ctx.restore();
    }
  },

  /**
   * Constructor
   * @param {Object} objects Group objects
   * @param {Object} [options] Options object
   * @param {Boolean} [isAlreadyGrouped] if true, objects have been grouped already.
   * @return {Object} thisArg
   */
  initialize: function (objects, options, isAlreadyGrouped) {
    this.callSuper("initialize", objects, options, isAlreadyGrouped);

    this.on({
      moving: this._showSelectedBorder,
      deselected: this._removeSelectedBorder,
    });
  },
});


// sample
var canvas = new fabric.Canvas("canvas");
var sampleGroup = new GroupExtended([
  new fabric.Circle({
    radius: 50,
    fill: "#f30070",
  }),
  new fabric.Rect({
    width: 100,
    height: 100,
    left: 50,
    top: 50,
    fill: "#f5f200",
 ...