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

feat(Layer): Group Rewrite #7449

Closed
wants to merge 52 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
a7d43a1
Create layer.class.js
ShaMan123 Oct 23, 2021
17c0714
Update build.js
ShaMan123 Oct 23, 2021
2118c3f
Update layer.class.js
ShaMan123 Oct 23, 2021
c92c71a
stable
ShaMan123 Oct 23, 2021
d338831
Update layer.class.js
ShaMan123 Oct 23, 2021
3f22b51
add/remove objects
ShaMan123 Oct 23, 2021
62ffc4c
Update layer.class.js
ShaMan123 Oct 23, 2021
4c40190
svg
ShaMan123 Oct 23, 2021
924e7d2
typo
ShaMan123 Oct 23, 2021
8ff6a08
Update layer.class.js
ShaMan123 Oct 23, 2021
3fa5430
fix(): remove + layout
ShaMan123 Oct 23, 2021
44e1679
fix(): layout
ShaMan123 Oct 23, 2021
1433f56
svg
ShaMan123 Oct 23, 2021
629f213
Update layer.class.js
ShaMan123 Oct 23, 2021
827d9df
Update layer.class.js
ShaMan123 Oct 23, 2021
fb11265
lint
ShaMan123 Oct 23, 2021
8d9f903
Update canvas.class.js
ShaMan123 Oct 23, 2021
c80c753
Update layer.class.js
ShaMan123 Oct 23, 2021
d3c196e
Revert "svg"
ShaMan123 Oct 27, 2021
0d2af25
perf(): `SprayBrush` case
ShaMan123 Oct 28, 2021
8ef519a
parent property
ShaMan123 Oct 28, 2021
d8b4413
Update layer.class.js
ShaMan123 Oct 28, 2021
3de8cd8
Update layer.class.js
ShaMan123 Oct 29, 2021
3216157
feat(Object#onSelect): support returning a descendant of object
ShaMan123 Oct 30, 2021
12e577c
_applyLayoutStrategy: add context + call on object change
ShaMan123 Oct 30, 2021
14da526
fix(_setActiveObject): handle nested selection if object is already s…
ShaMan123 Oct 30, 2021
d4decf9
fix(): call setCoords, getObjectsBoundingBox
ShaMan123 Oct 30, 2021
dbe57e7
Update canvas.class.js
ShaMan123 Oct 30, 2021
e742bfd
ci(): lint
ShaMan123 Oct 30, 2021
025a76f
Update canvas_events.mixin.js
ShaMan123 Oct 30, 2021
9e8aa41
better `getObjectsBoundingBox`
ShaMan123 Oct 30, 2021
13ea7e1
Revert "Update canvas_events.mixin.js"
ShaMan123 Oct 30, 2021
0c9771b
Update canvas.class.js
ShaMan123 Oct 31, 2021
c6b140e
Update layer.class.js
ShaMan123 Oct 31, 2021
aea95fe
Update canvas_events.mixin.js
ShaMan123 Oct 31, 2021
28fbc1b
Update canvas_events.mixin.js
ShaMan123 Oct 31, 2021
646f9eb
Update layer.class.js
ShaMan123 Oct 31, 2021
858657c
Update layer.class.js
ShaMan123 Oct 31, 2021
3a71e19
Update object_stacking.mixin.js
ShaMan123 Oct 31, 2021
7eaa92d
Update active_selection.class.js
ShaMan123 Oct 31, 2021
17c4f57
Update layer.class.js
ShaMan123 Oct 31, 2021
4f5e775
Update layer.class.js
ShaMan123 Oct 31, 2021
429a7ff
Update layer.class.js
ShaMan123 Oct 31, 2021
86caf8c
Update layer.class.js
ShaMan123 Nov 1, 2021
683c640
fix(): render selected on top
ShaMan123 Nov 1, 2021
45b62bd
lint
ShaMan123 Nov 1, 2021
271d4a1
Update layer.class.js
ShaMan123 Nov 1, 2021
4b81311
fix(): nested selection
ShaMan123 Nov 1, 2021
b66a4fd
Update layer.class.js
ShaMan123 Nov 1, 2021
d1a8b57
fix(): selection stack order
ShaMan123 Nov 1, 2021
d60903f
Update layer.class.js
ShaMan123 Nov 1, 2021
879f359
fix(): caching
ShaMan123 Nov 1, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions build.js
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ var filesToInclude = [
'src/shapes/polygon.class.js',
'src/shapes/path.class.js',
'src/shapes/group.class.js',
'src/shapes/layer.class.js',
ifSpecifiedInclude('interaction', 'src/shapes/active_selection.class.js'),
'src/shapes/image.class.js',

Expand Down
41 changes: 33 additions & 8 deletions src/canvas.class.js
Original file line number Diff line number Diff line change
Expand Up @@ -386,15 +386,21 @@
* @return {Array} objects to render immediately and pushes the other in the activeGroup.
*/
_chooseObjectsToRender: function() {
var activeObjects = this.getActiveObjects(),
var activeObjects = this.getActiveObjects(), objects = this._objects,
object, objsToRender, activeGroupObjects;

if (activeObjects.length > 0 && !this.preserveObjectStacking) {
objsToRender = [];
activeGroupObjects = [];
var ancestors = activeObjects.map(function (obj) {
while (obj && objects.indexOf(obj) === -1) {
obj = obj.parent || obj.group;
}
return obj;
});
for (var i = 0, length = this._objects.length; i < length; i++) {
object = this._objects[i];
if (activeObjects.indexOf(object) === -1 ) {
if (activeObjects.indexOf(object) === -1 && ancestors.indexOf(object) === -1) {
objsToRender.push(object);
}
else {
Expand All @@ -404,6 +410,9 @@
if (activeObjects.length > 1) {
this._activeObject._objects = activeGroupObjects;
}
else if (activeObjects[0].parent) {
activeGroupObjects.push(activeObjects[0]);
}
objsToRender.push.apply(objsToRender, activeGroupObjects);
}
else {
Expand Down Expand Up @@ -823,7 +832,7 @@
this._normalizePointer(objToCheck.group, pointer) : pointer;
if (this._checkTarget(pointerToUse, objToCheck, pointer)) {
target = objects[i];
if (target.subTargetCheck && target instanceof fabric.Group) {
if (target.subTargetCheck && Array.isArray(target._objects)) {
subTarget = this._searchPossibleTargets(target._objects, pointer);
subTarget && this.targets.push(subTarget);
}
Expand Down Expand Up @@ -1138,18 +1147,34 @@
* @param {Event} [e] Event (passed along when firing "object:selected")
* @return {Boolean} true if the selection happened
*/
_setActiveObject: function(object, e) {
if (this._activeObject === object) {
_setActiveObject: function (object, e) {
var result, isCollection = Array.isArray(object._objects), activeObject = this._activeObject;
if (this._activeObject === object && !isCollection) {
return false;
}
// return if active object doesn't allow to be deselected
if (!this._discardActiveObject(e, object)) {
return false;
}
if (object.onSelect({ e: e })) {
result = object.onSelect({
e: e,
object: activeObject,
subTargets: isCollection ? this.targets.concat() : undefined
});
if (result === true) {
return false;
}
this._activeObject = object;
return true;
else if (result && result instanceof fabric.Object) {
// prepare `subTargets` and re-run
this._searchPossibleTargets([result], this.getPointer(e, true));
this._setActiveObject(result, e);
return true;
}
else {
var current = this._activeObject;
this._activeObject = object;
return current !== this._activeObject;
}
},

/**
Expand Down
12 changes: 10 additions & 2 deletions src/mixins/canvas_events.mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -450,9 +450,12 @@
);
}
}
var actualTarget = target;
if (target) {
if (target.selectable && target !== this._activeObject && target.activeOn === 'up') {
this.setActiveObject(target, e);
// reassign in case a different object was selected
actualTarget = this._activeObject;
shouldRender = true;
}
else {
Expand All @@ -469,7 +472,7 @@
}
target.isMoving = false;
}
this._setCursorFromEvent(e, target);
this._setCursorFromEvent(e, actualTarget);
this._handleEvent(e, 'up', LEFT_CLICK, isClick);
this._groupSelector = null;
this._currentTransform = null;
Expand Down Expand Up @@ -720,10 +723,15 @@
}

if (target) {
var alreadySelected = target === this._activeObject;
if (target.selectable && target.activeOn === 'down') {
this.setActiveObject(target, e);
// reassign in case a different object was selected
if (target !== this._activeObject) {
shouldRender = true;
target = this._target = this._activeObject;
}
}
var alreadySelected = target === this._activeObject;
var corner = target._findTargetCorner(
this.getPointer(e, true),
fabric.util.isTouchEvent(e)
Expand Down
6 changes: 5 additions & 1 deletion src/mixins/object_interactivity.mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,7 @@
* try to to deselect this object. If the function returns true, the process is cancelled
* @param {Object} [options] options sent from the upper functions
* @param {Event} [options.e] event if the process is generated by an event
* @param {fabric.Object} [options.object] the object that is about to be selected if the process finishes
*/
onDeselect: function() {
// implemented by sub-classes, as needed.
Expand All @@ -306,9 +307,12 @@
* try to to select this object. If the function returns true, the process is cancelled
* @param {Object} [options] options sent from the upper functions
* @param {Event} [options.e] event if the process is generated by an event
* @param {fabric.Object} [options.object] the object that was deselected
*/
onSelect: function() {
onSelect: function (opt) {
// implemented by sub-classes, as needed.
if (opt.object && opt.object.parent && opt.object.parent !== this.parent
&& opt.object.parent !== this && opt.object !== this) {return opt.object.parent;}
}
});
})();
44 changes: 12 additions & 32 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 stack = this.parent || this.group || this.canvas;
stack && fabric.StaticCanvas.prototype.sendToBack.call(stack, 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 stack = this.parent || this.group || this.canvas;
stack && fabric.StaticCanvas.prototype.bringToFront.call(stack, 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 stack = this.parent || this.group || this.canvas;
stack && fabric.StaticCanvas.prototype.sendBackwards.call(stack, this, intersecting);
return this;
},

Expand All @@ -52,13 +40,9 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
* @return {fabric.Object} thisArg
* @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);
}
bringForward: function (intersecting) {
var stack = this.parent || this.group || this.canvas;
stack && fabric.StaticCanvas.prototype.bringForward.call(stack, 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 stack = this.parent || this.group || this.canvas;
stack && fabric.StaticCanvas.prototype.moveTo.call(stack, this, index);
return this;
}
});
75 changes: 4 additions & 71 deletions src/shapes/active_selection.class.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
* @tutorial {@link http://fabricjs.com/fabric-intro-part-3#groups}
* @see {@link fabric.ActiveSelection#initialize} for constructor definition
*/
fabric.ActiveSelection = fabric.util.createClass(fabric.Group, /** @lends fabric.ActiveSelection.prototype */ {
fabric.ActiveSelection = fabric.util.createClass(fabric.Layer, /** @lends fabric.ActiveSelection.prototype */ {

/**
* Type of an object
Expand All @@ -24,70 +24,11 @@
*/
type: 'activeSelection',

/**
* Constructor
* @param {Object} objects ActiveSelection objects
* @param {Object} [options] Options object
* @return {Object} thisArg
*/
initialize: function(objects, options) {
options = options || {};
this._objects = objects || [];
for (var i = this._objects.length; i--; ) {
this._objects[i].group = this;
}

if (options.originX) {
this.originX = options.originX;
}
if (options.originY) {
this.originY = options.originY;
}
this._calcBounds();
this._updateObjectsCoords();
fabric.Object.prototype.initialize.call(this, options);
initialize: function (objects, options) {
this.callSuper('initialize', objects, options);
this.setCoords();
},

/**
* Change te activeSelection to a normal group,
* High level function that automatically adds it to canvas as
* active object. no events fired.
* @since 2.0.0
* @return {fabric.Group}
*/
toGroup: function() {
var objects = this._objects.concat();
this._objects = [];
var options = fabric.Object.prototype.toObject.call(this);
var newGroup = new fabric.Group([]);
delete options.type;
newGroup.set(options);
objects.forEach(function(object) {
object.canvas.remove(object);
object.group = newGroup;
});
newGroup._objects = objects;
if (!this.canvas) {
return newGroup;
}
var canvas = this.canvas;
canvas.add(newGroup);
canvas._activeObject = newGroup;
newGroup.setCoords();
return newGroup;
},

/**
* If returns true, deselection is cancelled.
* @since 2.0.0
* @return {Boolean} [cancel]
*/
onDeselect: function() {
this.destroy();
return false;
},

/**
* Returns string representation of a group
* @return {String}
Expand All @@ -108,14 +49,6 @@
return false;
},

/**
* Check if this group or its parent group are caching, recursively up
* @return {Boolean}
*/
isOnACache: function() {
return false;
},

/**
* Renders controls and borders for the object
* @param {CanvasRenderingContext2D} ctx Context to render on
Expand Down Expand Up @@ -148,7 +81,7 @@
fabric.ActiveSelection.fromObject = function(object, callback) {
fabric.util.enlivenObjects(object.objects, function(enlivenedObjects) {
delete object.objects;
callback && callback(new fabric.ActiveSelection(enlivenedObjects, object, true));
callback && callback(new fabric.ActiveSelection(enlivenedObjects, object));
});
};

Expand Down
Loading