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(Group): render selected objects #7863

Closed
wants to merge 39 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
1a191a7
apply 7744 patch (no binaries)
ShaMan123 Apr 3, 2022
26e8392
apply 7744 patch (binaries)
ShaMan123 Apr 3, 2022
7d793b3
commit #7744 review
ShaMan123 Apr 3, 2022
2708029
patch2
ShaMan123 Apr 4, 2022
02a8ffa
Update spray_brush.class.js
ShaMan123 Apr 4, 2022
0d3690f
enable text editing under group
ShaMan123 Apr 4, 2022
ff0346a
migrate back to isDescendantOf
ShaMan123 Apr 4, 2022
812f02a
render bg
ShaMan123 Apr 4, 2022
053946c
fix(): clear canvas from entire object tree
ShaMan123 Apr 4, 2022
db76c44
fix(): center object in case object is nested
ShaMan123 Apr 4, 2022
04aad5b
Update eraser_brush.mixin.js
ShaMan123 Apr 4, 2022
8c1c535
Update canvas.class.js
ShaMan123 Apr 4, 2022
3fd4af2
Update canvas_events.mixin.js
ShaMan123 Apr 4, 2022
58e9be2
lint
ShaMan123 Apr 4, 2022
c2ef2f5
safeguard from adding group to itself
ShaMan123 Apr 4, 2022
f0145b5
Update object_ancestry.mixin.js
ShaMan123 Apr 4, 2022
cb20b81
patch tests from v6!
ShaMan123 Apr 4, 2022
347f80d
Update canvas_grouping.mixin.js
ShaMan123 Apr 4, 2022
a56d55e
Update canvas.class.js
ShaMan123 Apr 4, 2022
2a426e7
Update group_layout.js
ShaMan123 Apr 4, 2022
5e3fc1f
Update group_layout.js
ShaMan123 Apr 4, 2022
2b1f680
remove redundant logic
ShaMan123 Apr 4, 2022
1ad5cc8
Update canvas_grouping.mixin.js
ShaMan123 Apr 4, 2022
11c828f
fix(): calling sendPointToPlane
ShaMan123 Apr 4, 2022
b6fa3dc
Update group.class.js
ShaMan123 Apr 4, 2022
e9afc89
refactor `enterGroup`
ShaMan123 Apr 4, 2022
d8f8251
invalidate groups after active selection change
ShaMan123 Apr 4, 2022
c58a274
_shouldSetNestedCoords
ShaMan123 Apr 4, 2022
c0f5571
perf(): refrain from `contains`
ShaMan123 Apr 4, 2022
9a223d0
Update canvas_events.mixin.js
ShaMan123 Apr 4, 2022
2d5cc75
Update canvas.class.js
ShaMan123 Apr 4, 2022
01c4a87
Update canvas.class.js
ShaMan123 Apr 4, 2022
2164161
fix(): export svg backgroundColor
ShaMan123 Apr 4, 2022
a5575bd
Update group.js
ShaMan123 Apr 4, 2022
5c56124
backport collection fix to test
ShaMan123 Apr 4, 2022
5e3aaf5
Update group.class.js
ShaMan123 Apr 4, 2022
a1fd957
lint
ShaMan123 Apr 4, 2022
d53d6b6
lint
ShaMan123 Apr 4, 2022
cad7c77
Merge branch 'v6-group-patch2' into v6-group-patch5
ShaMan123 Apr 4, 2022
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
2 changes: 1 addition & 1 deletion src/brushes/spray_brush.class.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ fabric.SprayBrush = fabric.util.createClass( fabric.BaseBrush, /** @lends fabric
rects = this._getOptimizedRects(rects);
}

var group = new fabric.Group(rects);
var group = new fabric.Group(rects, { objectCaching: true, layout: 'fixed', subTargetCheck: false });
this.shadow && group.set('shadow', new fabric.Shadow(this.shadow));
this.canvas.fire('before:path:created', { path: group });
this.canvas.add(group);
Expand Down
4 changes: 2 additions & 2 deletions src/canvas.class.js
Original file line number Diff line number Diff line change
Expand Up @@ -873,7 +873,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 All @@ -892,7 +892,7 @@
*/
searchPossibleTargets: function (objects, pointer) {
var target = this._searchPossibleTargets(objects, pointer);
return target;
return target && target.interactive && this.targets[0] ? this.targets[0] : target;
},

/**
Expand Down
8 changes: 4 additions & 4 deletions src/mixins/animation.mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati

return fabric.util.animate({
target: this,
startValue: object.left,
startValue: object.getX(),
endValue: this.getCenterPoint().x,
duration: this.FX_DURATION,
onChange: function(value) {
object.set('left', value);
object.setX(value);
_this.requestRenderAll();
onChange();
},
Expand Down Expand Up @@ -58,11 +58,11 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati

return fabric.util.animate({
target: this,
startValue: object.top,
startValue: object.getY(),
endValue: this.getCenterPoint().y,
duration: this.FX_DURATION,
onChange: function(value) {
object.set('top', value);
object.setY(value);
_this.requestRenderAll();
onChange();
},
Expand Down
11 changes: 9 additions & 2 deletions src/mixins/canvas_events.mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -712,6 +712,7 @@
}
}
}
this._objectsToRender = this._chooseObjectsToRender();
this._handleEvent(e, 'down');
// we must renderAll so that we update the visuals
(shouldRender || shouldGroup) && this.requestRenderAll();
Expand Down Expand Up @@ -900,13 +901,19 @@
*/
_transformObject: function(e) {
var pointer = this.getPointer(e),
transform = this._currentTransform;
transform = this._currentTransform,
target = transform.target,
// transform pointer to target's containing coordinate plane
// both pointer and object should agree on every point
localPointer = target.group ?
fabric.util.sendPointToPlane(pointer, null, target.group.calcTransformMatrix()) :
pointer;

transform.reset = false;
transform.shiftKey = e.shiftKey;
transform.altKey = e[this.centeredKey];

this._performTransformAction(e, transform, pointer);
this._performTransformAction(e, transform, localPointer);
transform.actionPerformed && this.requestRenderAll();
},

Expand Down
28 changes: 17 additions & 11 deletions src/mixins/canvas_grouping.mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,12 @@
*/
_shouldGroup: function(e, target) {
var activeObject = this._activeObject;
return activeObject && this._isSelectionKeyPressed(e) && target && target.selectable && this.selection &&
(activeObject !== target || activeObject.type === 'activeSelection') && !target.onSelect({ e: e });
return !!activeObject && this._isSelectionKeyPressed(e)
&& !!target && target.selectable && this.selection
&& (activeObject !== target || activeObject.type === 'activeSelection')
// make sure `activeObject` and `target` aren't ancestors of each other
&& !target.isDescendantOf(activeObject) && !activeObject.isDescendantOf(target)
&& !target.onSelect({ e: e });
},

/**
Expand Down Expand Up @@ -50,8 +54,8 @@
_updateActiveSelection: function(target, e) {
var activeSelection = this._activeObject,
currentActiveObjects = activeSelection._objects.slice(0);
if (activeSelection.contains(target)) {
activeSelection.removeWithUpdate(target);
if (target.group === activeSelection) {
activeSelection.remove(target);
this._hoveredTarget = target;
this._hoveredTargets = this.targets.concat();
if (activeSelection.size() === 1) {
Expand All @@ -60,7 +64,7 @@
}
}
else {
activeSelection.addWithUpdate(target);
activeSelection.add(target);
this._hoveredTarget = activeSelection;
this._hoveredTargets = this.targets.concat();
}
Expand All @@ -80,17 +84,19 @@
this._fireSelectionEvents(currentActives, e);
},


/**
* @private
* @param {Object} target
* @returns {fabric.ActiveSelection}
*/
_createGroup: function(target) {
var objects = this._objects,
isActiveLower = objects.indexOf(this._activeObject) < objects.indexOf(target),
groupObjects = isActiveLower
? [this._activeObject, target]
: [target, this._activeObject];
this._activeObject.isEditing && this._activeObject.exitEditing();
var activeObject = this._activeObject;
var groupObjects = target.isInFrontOf(activeObject) ?
[activeObject, target] :
[target, activeObject];
activeObject.isEditing && activeObject.exitEditing();
// handle case: target is nested
return new fabric.ActiveSelection(groupObjects, {
canvas: this
});
Expand Down
90 changes: 40 additions & 50 deletions src/mixins/collection.mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,79 +3,69 @@
*/
fabric.Collection = {

/**
* @type {fabric.Object[]}
*/
_objects: [],

/**
* Adds objects to collection, Canvas or Group, then renders canvas
* (if `renderOnAddRemove` is not `false`).
* in case of Group no changes to bounding box are made.
* Objects should be instances of (or inherit from) fabric.Object
* Use of this function is highly discouraged for groups.
* you can add a bunch of objects with the add method but then you NEED
* to run a addWithUpdate call for the Group class or position/bbox will be wrong.
* @param {...fabric.Object} object Zero or more fabric instances
* @return {Self} thisArg
* @chainable
* @private
* @param {fabric.Object[]} objects to add
* @param {(object:fabric.Object) => any} [callback]
* @returns {number} new array length
*/
add: function () {
this._objects.push.apply(this._objects, arguments);
if (this._onObjectAdded) {
for (var i = 0, length = arguments.length; i < length; i++) {
this._onObjectAdded(arguments[i]);
add: function (objects, callback) {
var size = this._objects.push.apply(this._objects, objects);
if (callback) {
for (var i = 0, length = objects.length; i < length; i++) {
callback.call(this, objects[i]);
}
}
this.renderOnAddRemove && this.requestRenderAll();
return this;
return size;
},

/**
* Inserts an object into collection at specified index, then renders canvas (if `renderOnAddRemove` is not `false`)
* An object should be an instance of (or inherit from) fabric.Object
* Use of this function is highly discouraged for groups.
* you can add a bunch of objects with the insertAt method but then you NEED
* to run a addWithUpdate call for the Group class or position/bbox will be wrong.
* @param {Object} object Object to insert
* @private
* @param {fabric.Object|fabric.Object[]} objects Object(s) to insert
* @param {Number} index Index to insert object at
* @param {Boolean} nonSplicing When `true`, no splicing (shifting) of objects occurs
* @return {Self} thisArg
* @chainable
* @param {(object:fabric.Object) => any} [callback]
*/
insertAt: function (object, index, nonSplicing) {
var objects = this._objects;
if (nonSplicing) {
objects[index] = object;
}
else {
objects.splice(index, 0, object);
insertAt: function (objects, index, callback) {
var args = [index, 0].concat(objects);
this._objects.splice.apply(this._objects, args);
if (callback) {
for (var i = 2, length = args.length; i < length; i++) {
callback.call(this, args[i]);
}
}
this._onObjectAdded && this._onObjectAdded(object);
this.renderOnAddRemove && this.requestRenderAll();
return this;
},

/**
* Removes objects from a collection, then renders canvas (if `renderOnAddRemove` is not `false`)
* @param {...fabric.Object} object Zero or more fabric instances
* @return {Self} thisArg
* @chainable
* @private
* @param {fabric.Object[]} objectsToRemove objects to remove
* @param {(object:fabric.Object) => any} [callback] function to call for each object removed
* @returns {boolean} true if objects were removed
*/
remove: function() {
remove: function(objectsToRemove, callback) {
var objects = this._objects,
index, somethingRemoved = false;

for (var i = 0, length = arguments.length; i < length; i++) {
index = objects.indexOf(arguments[i]);

for (var i = 0, length = objectsToRemove.length; i < length; i++) {
index = objects.indexOf(objectsToRemove[i]);
// only call onObjectRemoved if an object was actually removed
if (index !== -1) {
somethingRemoved = true;
objects.splice(index, 1);
this._onObjectRemoved && this._onObjectRemoved(arguments[i]);
callback && callback.call(this, objectsToRemove[i]);
}
}

this.renderOnAddRemove && somethingRemoved && this.requestRenderAll();
return this;
return somethingRemoved;
},

/**
Expand All @@ -100,17 +90,16 @@ fabric.Collection = {

/**
* Returns an array of children objects of this instance
* Type parameter introduced in 1.3.10
* since 2.3.5 this method return always a COPY of the array;
* @param {String} [type] When specified, only objects of this type are returned
* @param {...String} [types] When specified, only objects of these types are returned
* @return {Array}
*/
getObjects: function(type) {
if (typeof type === 'undefined') {
getObjects: function() {
if (arguments.length === 0) {
return this._objects.concat();
}
return this._objects.filter(function(o) {
return o.type === type;
var types = Array.from(arguments);
return this._objects.filter(function (o) {
return types.indexOf(o.type) > -1;
});
},

Expand Down Expand Up @@ -140,7 +129,8 @@ fabric.Collection = {
},

/**
* Returns true if collection contains an object
* Returns true if collection contains an object.\
* **Prefer using {@link `fabric.Object#isDescendantOf`} for performance reasons**
* @param {Object} object Object to check against
* @param {Boolean} [deep=false] `true` to check all descendants, `false` to check only `_objects`
* @return {Boolean} `true` if collection contains an object
Expand Down
28 changes: 8 additions & 20 deletions src/mixins/eraser_brush.mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,6 @@
/* _TO_SVG_END_ */
});

var __restoreObjectsState = fabric.Group.prototype._restoreObjectsState;
fabric.util.object.extend(fabric.Group.prototype, {
/**
* @private
Expand Down Expand Up @@ -181,15 +180,6 @@
});
}
});
},

/**
* Propagate the group's eraser to its objects, crucial for proper functionality of the eraser within the group and nested objects.
* @private
*/
_restoreObjectsState: function () {
this.erasable === true && this.applyEraserToObjects();
return __restoreObjectsState.call(this);
}
});

Expand Down Expand Up @@ -217,23 +207,21 @@
*/
originY: 'center',

drawObject: function (ctx) {
ctx.save();
ctx.fillStyle = 'black';
ctx.fillRect(-this.width / 2, -this.height / 2, this.width, this.height);
ctx.restore();
this.callSuper('drawObject', ctx);
},

/**
* eraser should retain size
* dimensions should not change when paths are added or removed
* handled by {@link fabric.Object#_drawClipPath}
* @override
* @private
*/
_getBounds: function () {
// noop
layout: 'fixed',

drawObject: function (ctx) {
ctx.save();
ctx.fillStyle = 'black';
ctx.fillRect(-this.width / 2, -this.height / 2, this.width, this.height);
ctx.restore();
this.callSuper('drawObject', ctx);
},

/* _TO_SVG_START_ */
Expand Down
2 changes: 1 addition & 1 deletion src/mixins/itext_click_behavior.mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot
*/
mouseUpHandler: function(options) {
this.__isMousedown = false;
if (!this.editable || this.group ||
if (!this.editable ||
(options.transform && options.transform.actionPerformed) ||
(options.e.button && options.e.button !== 1)) {
return;
Expand Down
Loading