从一组中选择对象的问题

Problems with selecting objects from a group

我目前正在创建自己的具有扩展群组功能的自定义群组 class。首先,我创建了一个可以选择组中对象的功能。该功能的概念是:

  1. 鼠标点击时检测鼠标点canvas。
  2. 正在根据鼠标点检测群组中的对象。
  3. 如果在组中找到对象,则激活该对象。
  4. 如果在组中找不到对象,则激活该组。
  5. 组中的活动对象为实线边框,组中为虚线边框。

在组未被修改的情况下一切正常。然而,当组在缩放、旋转和倾斜时,这些问题就来了:

  1. 组内对象选择区域不按照实际大小
  2. 实线边框仍然显示创建对象时的初始属性,不跟随组的旋转和缩放。

详情请看下图:

problem and expected result

这是组自定义class:

/**
 * 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",

  /**
   * 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();
    this._selectedObject &&
      this._selectedObject._renderControls(this.canvas.contextTop, {
        hasControls: false,
      });
  },

  /**
   * 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,
    });
  },

  /**
   * Get selected object based on mouse point.
   * Return detected object or
   * most top of objects if more than one object detected in mouse point or
   * null if mouse point refer to empty area in group.
   * @param {Object} point object with "x" and "y" number values
   * @return {fabric.Object} selected object
   */
  getSelectedObjectInGroup: function (point) {
    // reset last known selected object
    this._selectedObject = null;
    this._removeSelectedBorder();

    this.forEachObject(
      function (obj) {
        var matrixPoint = obj.calcTransformMatrix();

        var center = {
          x: matrixPoint[4],
          y: matrixPoint[5],
        };

        var thisPos = {
          xStart: center.x - obj.width / 2,
          xEnd: center.x + obj.width / 2,
          yStart: center.y - obj.height / 2,
          yEnd: center.y + obj.height / 2,
        };

        if (point.x >= thisPos.xStart && point.x <= thisPos.xEnd) {
          if (point.y >= thisPos.yStart && point.y <= thisPos.yEnd) {
            this._selectedObject = obj;
            this._showSelectedBorder();
          }
        }
      }.bind(this)
    );

    return this._selectedObject;
  },
});

Link 到 jsfiddle:https://jsfiddle.net/clngkusnd/pa5dzLm2/

问题是为什么创建对象时选中对象的选择区域保持不变

fabricJS中的选择区域代码没有考虑分组转换,即使fabricJS目前没有理由支持分组选择,也许这个可以修复。 请注意,您可以在不编写自定义代码来查找内部对象的情况下完成您所取得的成就:

https://jsfiddle.net/asturur/wg0mkjv2/3/

fabricJS 支持开箱即用的目标在组内查找,启用 subTargetCheck 布尔值 属性 到 true