Use sendToBack, bringToFront, bringForward, sendBackwards for multiple selections (#2908)

Use sendToBack, bringToFront, bringForward, sendBackwards for activeGroups.
Visually there is no effect if preserveObjectStacking is set to false.
This commit is contained in:
Andrea Bogazzi 2016-04-28 11:21:48 +02:00
parent c335cb558e
commit 940db388a8
2 changed files with 172 additions and 26 deletions

View file

@ -1347,47 +1347,97 @@
/* _TO_SVG_END_ */
/**
* Moves an object to the bottom of the stack of drawn objects
* 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
* @return {fabric.Canvas} thisArg
* @chainable
*/
sendToBack: function (object) {
removeFromArray(this._objects, object);
this._objects.unshift(object);
if (!object) {
return this;
}
var activeGroup = this.getActiveGroup ? this.getActiveGroup() : null,
i, obj, objs;
if (object === activeGroup) {
objs = activeGroup._objects;
for (i = objs.length; i--;) {
obj = objs[i];
removeFromArray(this._objects, obj);
this._objects.unshift(obj);
}
}
else {
removeFromArray(this._objects, object);
this._objects.unshift(object);
}
return this.renderAll && this.renderAll();
},
/**
* Moves an object to the top of the stack of drawn objects
* 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
* @return {fabric.Canvas} thisArg
* @chainable
*/
bringToFront: function (object) {
removeFromArray(this._objects, object);
this._objects.push(object);
if (!object) {
return this;
}
var activeGroup = this.getActiveGroup ? this.getActiveGroup() : null,
i, obj, objs;
if (object === activeGroup) {
objs = activeGroup._objects;
for (i = 0; i < objs.length; i++) {
obj = objs[i];
removeFromArray(this._objects, obj);
this._objects.push(obj);
}
}
else {
removeFromArray(this._objects, object);
this._objects.push(object);
}
return this.renderAll && this.renderAll();
},
/**
* Moves an object down in stack of drawn objects
* Moves an object or a selection down in stack of drawn objects
* @param {fabric.Object} object Object to send
* @param {Boolean} [intersecting] If `true`, send object behind next lower intersecting object
* @return {fabric.Canvas} thisArg
* @chainable
*/
sendBackwards: function (object, intersecting) {
var idx = this._objects.indexOf(object);
// if object is not on the bottom of stack
if (idx !== 0) {
var newIdx = this._findNewLowerIndex(object, idx, intersecting);
removeFromArray(this._objects, object);
this._objects.splice(newIdx, 0, object);
this.renderAll && this.renderAll();
if (!object) {
return this;
}
var activeGroup = this.getActiveGroup ? this.getActiveGroup() : null,
i, obj, idx, newIdx, objs;
if (object === activeGroup) {
objs = activeGroup._objects;
for (i = 0; i < objs.length; i++) {
obj = objs[i];
idx = this._objects.indexOf(obj);
if (idx !== 0) {
newIdx = idx - 1;
removeFromArray(this._objects, obj);
this._objects.splice(newIdx, 0, obj);
}
}
}
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.renderAll && this.renderAll();
return this;
},
@ -1421,23 +1471,41 @@
},
/**
* Moves an object up in stack of drawn objects
* Moves an object or a selection up in stack of drawn objects
* @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) {
var idx = this._objects.indexOf(object);
// if object is not on top of stack (last item in an array)
if (idx !== this._objects.length - 1) {
var newIdx = this._findNewUpperIndex(object, idx, intersecting);
removeFromArray(this._objects, object);
this._objects.splice(newIdx, 0, object);
this.renderAll && this.renderAll();
if (!object) {
return this;
}
var activeGroup = this.getActiveGroup ? this.getActiveGroup() : null,
i, obj, idx, newIdx, objs;
if (object === activeGroup) {
objs = activeGroup._objects;
for (i = objs.length; i--;) {
obj = objs[i];
idx = this._objects.indexOf(obj);
if (idx !== this._objects.length - 1) {
newIdx = idx + 1;
removeFromArray(this._objects, obj);
this._objects.splice(newIdx, 0, obj);
}
}
}
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.renderAll && this.renderAll();
return this;
},

View file

@ -271,6 +271,84 @@
//TODO: make it work with perPixelTargetFind
});
test('activeGroup sendToBack', function() {
var rect1 = makeRect(),
rect2 = makeRect(),
rect3 = makeRect(),
rect4 = makeRect();
canvas.add(rect1, rect2, rect3, rect4);
var group = new fabric.Group([ rect3, rect4 ]);
canvas.setActiveGroup(group);
equal(canvas._objects[0], rect1, 'rect1 should be last');
equal(canvas._objects[1], rect2, 'rect2 should be second');
canvas.sendToBack(group);
equal(canvas._objects[0], rect3, 'rect3 should be the new last');
equal(canvas._objects[1], rect4, 'rect3 should be the new second');
equal(canvas._objects[2], rect1, 'rect1 should be the third object');
equal(canvas._objects[3], rect2, 'rect2 should be on top now');
});
test('activeGroup bringToFront', function() {
var rect1 = makeRect(),
rect2 = makeRect(),
rect3 = makeRect(),
rect4 = makeRect();
canvas.add(rect1, rect2, rect3, rect4);
var group = new fabric.Group([ rect1, rect2 ]);
canvas.setActiveGroup(group);
equal(canvas._objects[0], rect1, 'rect1 should be last');
equal(canvas._objects[1], rect2, 'rect2 should be second');
canvas.bringToFront(group);
equal(canvas._objects[0], rect3, 'rect3 should be the new last');
equal(canvas._objects[1], rect4, 'rect3 should be the new second');
equal(canvas._objects[2], rect1, 'rect1 should be the third object');
equal(canvas._objects[3], rect2, 'rect2 should be on top now');
});
test('activeGroup bringForward', function() {
var rect1 = makeRect(),
rect2 = makeRect(),
rect3 = makeRect(),
rect4 = makeRect();
canvas.add(rect1, rect2, rect3, rect4);
var group = new fabric.Group([ rect1, rect2 ]);
canvas.setActiveGroup(group);
equal(canvas._objects[0], rect1, 'rect1 should be last');
equal(canvas._objects[1], rect2, 'rect2 should be second');
canvas.bringForward(group);
equal(canvas._objects[0], rect3, 'rect3 should be the new last');
equal(canvas._objects[1], rect1, 'rect1 should be the new second');
equal(canvas._objects[2], rect2, 'rect2 should be the third object');
equal(canvas._objects[3], rect4, 'rect4 did not move');
});
test('activeGroup sendBackwards', function() {
var rect1 = makeRect(),
rect2 = makeRect(),
rect3 = makeRect(),
rect4 = makeRect();
canvas.add(rect1, rect2, rect3, rect4);
var group = new fabric.Group([ rect3, rect4 ]);
canvas.setActiveGroup(group);
equal(canvas._objects[0], rect1, 'rect1 should be last');
equal(canvas._objects[1], rect2, 'rect2 should be second');
canvas.sendBackwards(group);
equal(canvas._objects[0], rect1, 'rect1 is still last');
equal(canvas._objects[1], rect3, 'rect3 should be shifted down by 1');
equal(canvas._objects[2], rect4, 'rect4 should be shifted down by 1');
equal(canvas._objects[3], rect2, 'rect2 is the new top');
});
test('toDataURL', function() {
ok(typeof canvas.toDataURL == 'function');