Skip to content

Commit

Permalink
chore(): move object stacking logic to collection
Browse files Browse the repository at this point in the history
  • Loading branch information
ShaMan123 committed Apr 14, 2022
1 parent 887a745 commit f5a4f89
Show file tree
Hide file tree
Showing 3 changed files with 163 additions and 110 deletions.
148 changes: 147 additions & 1 deletion src/mixins/collection.mixin.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
var removeFromArray = fabric.util.removeFromArray;

/**
* @namespace fabric.Collection
*/
Expand Down Expand Up @@ -156,5 +158,149 @@ fabric.Collection = {
memo += current.complexity ? current.complexity() : 0;
return memo;
}, 0);
}
},


/**
* Moves an object or the objects of a multiple selection
* to the bottom of the stack of drawn objects
* @param {fabric.Object} object Object to send to back
*/
sendToBack: function (object) {
if (!object) {
return;
}
removeFromArray(this._objects, object);
this._objects.unshift(object);
},

/**
* Moves an object or the objects of a multiple selection
* to the top of the stack of drawn objects
* @param {fabric.Object} object Object to send
*/
bringToFront: function (object) {
if (!object) {
return;
}
removeFromArray(this._objects, object);
this._objects.push(object);
},

/**
* Moves an object or a selection down in stack of drawn objects
* An optional parameter, `intersecting` allows to move the object in behind
* the first intersecting object. Where intersection is calculated with
* bounding box. If no intersection is found, there will not be change in the
* stack.
* @param {fabric.Object} object Object to send
* @param {Boolean} [intersecting] If `true`, send object behind next lower intersecting object
*/
sendBackwards: function (object, intersecting) {
if (!object) {
return this;
}
var idx = this._objects.indexOf(object);
if (idx !== 0) {
// if object is not on the bottom of stack
var newIdx = this._findNewLowerIndex(object, idx, intersecting);
removeFromArray(this._objects, object);
this._objects.splice(newIdx, 0, object);
}
},

/**
* Moves an object or a selection up in stack of drawn objects
* An optional parameter, intersecting allows to move the object in front
* of the first intersecting object. Where intersection is calculated with
* bounding box. If no intersection is found, there will not be change in the
* stack.
* @param {fabric.Object} object Object to send
* @param {Boolean} [intersecting] If `true`, send object in front of next upper intersecting object
* @return {fabric.Canvas} thisArg
* @chainable
*/
bringForward: function (object, intersecting) {
if (!object) {
return this;
}
var idx = this._objects.indexOf(object);
if (idx !== this._objects.length - 1) {
// if object is not on top of stack (last item in an array)
var newIdx = this._findNewUpperIndex(object, idx, intersecting);
removeFromArray(this._objects, object);
this._objects.splice(newIdx, 0, object);
}
},

/**
* Moves an object to specified level in stack of drawn objects
* @param {fabric.Object} object Object to send
* @param {Number} index Position to move to
* @return {fabric.Canvas} thisArg
* @chainable
*/
moveTo: function (object, index) {
removeFromArray(this._objects, object);
this._objects.splice(index, 0, object);
},

/**
* @private
*/
_findNewLowerIndex: function (object, idx, intersecting) {
var newIdx, i;

if (intersecting) {
newIdx = idx;

// traverse down the stack looking for the nearest intersecting object
for (i = idx - 1; i >= 0; --i) {

var isIntersecting = object.intersectsWithObject(this._objects[i]) ||
object.isContainedWithinObject(this._objects[i]) ||
this._objects[i].isContainedWithinObject(object);

if (isIntersecting) {
newIdx = i;
break;
}
}
}
else {
newIdx = idx - 1;
}

return newIdx;
},

/**
* @private
*/
_findNewUpperIndex: function (object, idx, intersecting) {
var newIdx, i, len;

if (intersecting) {
newIdx = idx;

// traverse up the stack looking for the nearest intersecting object
for (i = idx + 1, len = this._objects.length; i < len; ++i) {

var isIntersecting = object.intersectsWithObject(this._objects[i]) ||
object.isContainedWithinObject(this._objects[i]) ||
this._objects[i].isContainedWithinObject(object);

if (isIntersecting) {
newIdx = i;
break;
}
}
}
else {
newIdx = idx + 1;
}

return newIdx;
},

};
42 changes: 11 additions & 31 deletions src/mixins/object_stacking.mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,9 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
* @return {fabric.Object} thisArg
* @chainable
*/
sendToBack: function() {
if (this.group) {
fabric.StaticCanvas.prototype.sendToBack.call(this.group, this);
}
else if (this.canvas) {
this.canvas.sendToBack(this);
}
sendToBack: function () {
var parent = this.group || this.canvas;
parent && parent.sendToBack(this);
return this;
},

Expand All @@ -21,12 +17,8 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
* @chainable
*/
bringToFront: function() {
if (this.group) {
fabric.StaticCanvas.prototype.bringToFront.call(this.group, this);
}
else if (this.canvas) {
this.canvas.bringToFront(this);
}
var parent = this.group || this.canvas;
parent && parent.bringToFront(this);
return this;
},

Expand All @@ -37,12 +29,8 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
* @chainable
*/
sendBackwards: function(intersecting) {
if (this.group) {
fabric.StaticCanvas.prototype.sendBackwards.call(this.group, this, intersecting);
}
else if (this.canvas) {
this.canvas.sendBackwards(this, intersecting);
}
var parent = this.group || this.canvas;
parent && parent.sendBackwards(this, intersecting);
return this;
},

Expand All @@ -53,12 +41,8 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
* @chainable
*/
bringForward: function(intersecting) {
if (this.group) {
fabric.StaticCanvas.prototype.bringForward.call(this.group, this, intersecting);
}
else if (this.canvas) {
this.canvas.bringForward(this, intersecting);
}
var parent = this.group || this.canvas;
parent && parent.bringForward(this, intersecting);
return this;
},

Expand All @@ -69,12 +53,8 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
* @chainable
*/
moveTo: function(index) {
if (this.group && this.group.type !== 'activeSelection') {
fabric.StaticCanvas.prototype.moveTo.call(this.group, this, index);
}
else if (this.canvas) {
this.canvas.moveTo(this, index);
}
var parent = this.group || this.canvas;
parent && parent.moveTo(this, index);
return this;
}
});
83 changes: 5 additions & 78 deletions src/static_canvas.class.js
Original file line number Diff line number Diff line change
Expand Up @@ -1399,8 +1399,7 @@
}
}
else {
removeFromArray(this._objects, object);
this._objects.unshift(object);
this.callSuper('sendToBack', object);
}
this.renderOnAddRemove && this.requestRenderAll();
return this;
Expand Down Expand Up @@ -1428,8 +1427,7 @@
}
}
else {
removeFromArray(this._objects, object);
this._objects.push(object);
this.callSuper('bringToFront', object);
}
this.renderOnAddRemove && this.requestRenderAll();
return this;
Expand Down Expand Up @@ -1467,47 +1465,12 @@
}
}
else {
idx = this._objects.indexOf(object);
if (idx !== 0) {
// if object is not on the bottom of stack
newIdx = this._findNewLowerIndex(object, idx, intersecting);
removeFromArray(this._objects, object);
this._objects.splice(newIdx, 0, object);
}
this.callSuper('sendBackwards', object, intersecting);
}
this.renderOnAddRemove && this.requestRenderAll();
return this;
},

/**
* @private
*/
_findNewLowerIndex: function(object, idx, intersecting) {
var newIdx, i;

if (intersecting) {
newIdx = idx;

// traverse down the stack looking for the nearest intersecting object
for (i = idx - 1; i >= 0; --i) {

var isIntersecting = object.intersectsWithObject(this._objects[i]) ||
object.isContainedWithinObject(this._objects[i]) ||
this._objects[i].isContainedWithinObject(object);

if (isIntersecting) {
newIdx = i;
break;
}
}
}
else {
newIdx = idx - 1;
}

return newIdx;
},

/**
* Moves an object or a selection up in stack of drawn objects
* An optional parameter, intersecting allows to move the object in front
Expand Down Expand Up @@ -1540,47 +1503,12 @@
}
}
else {
idx = this._objects.indexOf(object);
if (idx !== this._objects.length - 1) {
// if object is not on top of stack (last item in an array)
newIdx = this._findNewUpperIndex(object, idx, intersecting);
removeFromArray(this._objects, object);
this._objects.splice(newIdx, 0, object);
}
this.callSuper('bringForward', object, intersecting);
}
this.renderOnAddRemove && this.requestRenderAll();
return this;
},

/**
* @private
*/
_findNewUpperIndex: function(object, idx, intersecting) {
var newIdx, i, len;

if (intersecting) {
newIdx = idx;

// traverse up the stack looking for the nearest intersecting object
for (i = idx + 1, len = this._objects.length; i < len; ++i) {

var isIntersecting = object.intersectsWithObject(this._objects[i]) ||
object.isContainedWithinObject(this._objects[i]) ||
this._objects[i].isContainedWithinObject(object);

if (isIntersecting) {
newIdx = i;
break;
}
}
}
else {
newIdx = idx + 1;
}

return newIdx;
},

/**
* Moves an object to specified level in stack of drawn objects
* @param {fabric.Object} object Object to send
Expand All @@ -1589,8 +1517,7 @@
* @chainable
*/
moveTo: function (object, index) {
removeFromArray(this._objects, object);
this._objects.splice(index, 0, object);
this.callSuper('moveTo', object, index);
return this.renderOnAddRemove && this.requestRenderAll();
},

Expand Down

0 comments on commit f5a4f89

Please sign in to comment.