Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

activeGroup object sort is incorrect #508

Closed
Kienz opened this issue Mar 27, 2013 · 12 comments · Fixed by #2130
Closed

activeGroup object sort is incorrect #508

Kienz opened this issue Mar 27, 2013 · 12 comments · Fixed by #2130
Assignees
Labels

Comments

@Kienz
Copy link
Collaborator

Kienz commented Mar 27, 2013

The zIndex of activeGroup objects is wrong.

objects before activeGroup selection:

objects in activeGroup selection:

@kangax
Copy link
Member

kangax commented Mar 30, 2013

Fixed in 26c2590

@kangax kangax closed this as completed Mar 30, 2013
@Kienz
Copy link
Collaborator Author

Kienz commented Apr 2, 2013

If you add objects with shift key to activeGroup the bug still exists.
I think the following two code sections are the problem:

  1. Creating new activeGroup with mouseClick and shiftKey:
    var group = new fabric.Group([ this._activeObject, target ]);
    https://github.com/kangax/fabric.js/blob/master/src/canvas.class.js#L448
  2. Adding object to existing activeGroup with mouseClick and shiftKey:
    https://github.com/kangax/fabric.js/blob/master/src/canvas.class.js#L436
    https://github.com/kangax/fabric.js/blob/master/src/group.class.js#L125

In both cases the zIndex of the objects are not considered. I think if the objects are intersect we have to compare the zIndex and inserting them by that order.

@kangax kangax reopened this Apr 2, 2013
@kangax
Copy link
Member

kangax commented Jun 18, 2013

  1. should be fixed now (4d4a129)

@kangax
Copy link
Member

kangax commented Jun 18, 2013

  1. is a bit more complicated. We should first add optional 2nd argument to fabric.Group#addWithUpdate specifying index where to insert an object. Then use that index when injecting object in a group.

@kangax
Copy link
Member

kangax commented Jun 11, 2014

@Kienz is #2 still an issue?

@Kienz
Copy link
Collaborator Author

Kienz commented Jun 13, 2014

@kangax 2nd issue still exists.
See jsfiddle: http://jsfiddle.net/Kienz/EGYFX/

Select objects (with shift key) in the following direction:

  1. blue
  2. brown
  3. red
    Now you can see that red rectangle is above brown rectangle.

@asturur asturur self-assigned this Nov 7, 2014
@lukejagodzinski
Copy link

Issue still exists
fabric1
fabric2

The problem is in rendering order not placing group into canvas._objects.
Here are fixes to code that will make it work properly:

fabric.Canvas.prototype.renderAll = function(allOnTop) {
  var canvasToDrawOn = this[(allOnTop === true && this.interactive) ? 'contextTop' : 'contextContainer'],
    activeGroup = this.getActiveGroup();

  if (this.contextTop && this.selection && !this._groupSelector) {
    this.clearContext(this.contextTop);
  }

  if (!allOnTop) {
    this.clearContext(canvasToDrawOn);
  }

  this.fire('before:render');

  if (this.clipTo) {
    fabric.util.clipContext(this, canvasToDrawOn);
  }

  this._renderBackground(canvasToDrawOn);
  this._renderObjects(canvasToDrawOn, activeGroup);
  // this._renderActiveGroup(canvasToDrawOn, activeGroup);

  if (this.clipTo) {
    canvasToDrawOn.restore();
  }

  this._renderOverlay(canvasToDrawOn);

  if (this.controlsAboveOverlay && this.interactive) {
    this.drawControls(canvasToDrawOn);
  }

  this.fire('after:render');

  return this;
};

fabric.Canvas.prototype._renderObjects = function(ctx, activeGroup) {
  var i, length;

  if (!activeGroup || this.preserveObjectStacking) {
    for (i = 0, length = this._objects.length; i < length; ++i) {
      this._draw(ctx, this._objects[i]);
    }
  } else {
    for (i = 0, length = this._objects.length; i < length; ++i) {
      if (this._objects[i] && !activeGroup.contains(this._objects[i])) {
        this._draw(ctx, this._objects[i]);
      } else { // ADD THIS...
        this._renderActiveGroup(ctx, activeGroup);
      }
    }
  }
};

I've checked it and it works. Here is working example: http://jsbin.com/dejiwu/2/edit

fabric3 png

I can create pull request

lukejagodzinski added a commit to lukejagodzinski/fabric.js that referenced this issue Feb 5, 2015
@asturur
Copy link
Member

asturur commented Feb 5, 2015

The screen you capture is not really a fix, we do not want the controls to be under any object. Controls are always over.

@lukejagodzinski
Copy link

So, there is one more error because right now it looks like this
fabric-selection-error

I'm working on the fix

lukejagodzinski added a commit to lukejagodzinski/fabric.js that referenced this issue Feb 5, 2015
@lukejagodzinski
Copy link

Ok I've made another pull request #1963. Now code got much simpler.

http://jsbin.com/dejiwu/3/edit?js,output

fabric-selection-fixed

I've noticed another bug but not related with rendering controls. The error occurs when hovering mouse on the control point of the object that is behind another object. Try here selecting green circle and clicking right bottom control point.

@asturur
Copy link
Member

asturur commented Feb 5, 2015

maybe o was wrong? i will check current situation

@asturur
Copy link
Member

asturur commented Apr 19, 2015

I think main problem here is this:

https://github.com/kangax/fabric.js/blob/master/src/static_canvas.class.js#L888

    /**
     * @private
     * @param {CanvasRenderingContext2D} ctx Context to render on
     * @param {fabric.Group} activeGroup
     */
    _renderActiveGroup: function(ctx, activeGroup) {

      // delegate rendering to group selection (if one exists)
      if (activeGroup) {

        //Store objects in group preserving order, then replace
        var sortedObjects = [];
        this.forEachObject(function (object) {
          if (activeGroup.contains(object)) {
            sortedObjects.push(object);
          }
        });
-       activeGroup._set('objects', sortedObjects);
+       activeGroup._set('_objects', sortedObjects);
        this._draw(ctx, activeGroup);
      }
    },

We are ordering the activeGroup objects but then we are putting them in object array , while rendering uses just the _objects.
@kangax @Kienz, is this possible?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants