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

MAJOR chore(v6): neutral prerequisites for fabric.Group rework #7726

Merged
merged 2 commits into from
Feb 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -178,6 +178,7 @@ var filesToInclude = [
'src/shapes/object.class.js',
'src/mixins/object_origin.mixin.js',
'src/mixins/object_geometry.mixin.js',
'src/mixins/object_ancestry.mixin.js',
'src/mixins/object_stacking.mixin.js',
'src/mixins/object.svg_export.js',
'src/mixins/stateful.mixin.js',
Expand Down
84 changes: 69 additions & 15 deletions src/canvas.class.js
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,13 @@
*/
_hoveredTargets: [],

/**
* hold the list of objects to render
* @type fabric.Object[]
* @private
*/
_objectsToRender: undefined,

/**
* @private
*/
Expand All @@ -369,6 +376,23 @@
this.calcOffset();
},

/**
* @private
* @param {fabric.Object} obj Object that was added
*/
_onObjectAdded: function (obj) {
this._objectsToRender = undefined;
this.callSuper('_onObjectAdded', obj);
},

/**
* @private
* @param {fabric.Object} obj Object that was removed
*/
_onObjectRemoved: function (obj) {
this._objectsToRender = undefined;
this.callSuper('_onObjectRemoved', obj);
},
/**
* Divides objects in two groups, one to render immediately
* and one to render as activeGroup.
Expand All @@ -378,7 +402,7 @@
var activeObjects = this.getActiveObjects(),
object, objsToRender, activeGroupObjects;

if (activeObjects.length > 0 && !this.preserveObjectStacking) {
if (!this.preserveObjectStacking && activeObjects.length > 1) {
objsToRender = [];
activeGroupObjects = [];
for (var i = 0, length = this._objects.length; i < length; i++) {
Expand All @@ -395,6 +419,15 @@
}
objsToRender.push.apply(objsToRender, activeGroupObjects);
}
// in case a single object is selected render it's entire above the other objects
else if (!this.preserveObjectStacking && activeObjects.length === 1) {
var target = activeObjects[0], ancestors = target.getAncestors(true);
var topAncestor = ancestors.length === 0 ? target : ancestors.pop();
objsToRender = this._objects.slice();
var index = objsToRender.indexOf(topAncestor);
index > -1 && objsToRender.splice(objsToRender.indexOf(topAncestor), 1);
objsToRender.push(topAncestor);
}
else {
objsToRender = this._objects;
}
Expand All @@ -416,7 +449,8 @@
this.hasLostContext = false;
}
var canvasToDrawOn = this.contextContainer;
this.renderCanvas(canvasToDrawOn, this._chooseObjectsToRender());
!this._objectsToRender && (this._objectsToRender = this._chooseObjectsToRender());
this.renderCanvas(canvasToDrawOn, this._objectsToRender);
return this;
},

Expand Down Expand Up @@ -622,14 +656,22 @@
if (!target) {
return;
}

var pointer = this.getPointer(e), corner = target.__corner,
var pointer = this.getPointer(e);
if (target.group) {
// transform pointer to target's containing coordinate plane
pointer = fabric.util.transformPoint(pointer, fabric.util.invertTransform(target.group.calcTransformMatrix()));
}
var corner = target.__corner,
control = target.controls[corner],
actionHandler = (alreadySelected && corner) ?
control.getActionHandler(e, target, control) : fabric.controlsUtils.dragHandler,
action = this._getActionFromCorner(alreadySelected, corner, e, target),
origin = this._getOriginFromCorner(target, corner),
altKey = e[this.centeredKey],
/**
* relative to target's containing coordinate plane
* both agree on every point
**/
transform = {
target: target,
action: action,
Expand All @@ -639,7 +681,6 @@
scaleY: target.scaleY,
skewX: target.skewX,
skewY: target.skewY,
// used by transation
offsetX: pointer.x - target.left,
offsetY: pointer.y - target.top,
originX: origin.x,
Expand All @@ -648,11 +689,7 @@
ey: pointer.y,
lastX: pointer.x,
lastY: pointer.y,
// unsure they are useful anymore.
// left: target.left,
// top: target.top,
theta: degreesToRadians(target.angle),
// end of unsure
width: target.width * target.scaleX,
shiftKey: e.shiftKey,
altKey: altKey,
Expand Down Expand Up @@ -745,11 +782,12 @@
if (shouldLookForActive && activeObject._findTargetCorner(pointer, isTouch)) {
return activeObject;
}
if (aObjects.length > 1 && !skipGroup && activeObject === this._searchPossibleTargets([activeObject], pointer)) {
if (aObjects.length > 1 && activeObject.type === 'activeSelection'
&& !skipGroup && this.searchPossibleTargets([activeObject], pointer)) {
return activeObject;
}
if (aObjects.length === 1 &&
activeObject === this._searchPossibleTargets([activeObject], pointer)) {
activeObject === this.searchPossibleTargets([activeObject], pointer)) {
if (!this.preserveObjectStacking) {
return activeObject;
}
Expand All @@ -759,7 +797,7 @@
this.targets = [];
}
}
var target = this._searchPossibleTargets(this._objects, pointer);
var target = this.searchPossibleTargets(this._objects, pointer);
if (e[this.altSelectionKey] && target && activeTarget && target !== activeTarget) {
target = activeTarget;
this.targets = activeTargetSubs;
Expand Down Expand Up @@ -796,10 +834,10 @@
},

/**
* Function used to search inside objects an object that contains pointer in bounding box or that contains pointerOnCanvas when painted
* Internal Function used to search inside objects an object that contains pointer in bounding box or that contains pointerOnCanvas when painted
* @param {Array} [objects] objects array to look into
* @param {Object} [pointer] x,y object of point coordinates we want to check.
* @return {fabric.Object} object that contains pointer
* @return {fabric.Object} **top most object from given `objects`** that contains pointer
* @private
*/
_searchPossibleTargets: function(objects, pointer) {
Expand All @@ -823,6 +861,18 @@
return target;
},

/**
* Function used to search inside objects an object that contains pointer in bounding box or that contains pointerOnCanvas when painted
* @see {@link fabric.Canvas#_searchPossibleTargets}
* @param {Array} [objects] objects array to look into
* @param {Object} [pointer] x,y object of point coordinates we want to check.
* @return {fabric.Object} **top most object on screen** that contains pointer
*/
searchPossibleTargets: function (objects, pointer) {
var target = this._searchPossibleTargets(objects, pointer);
return target;
},

/**
* Returns pointer coordinates without the effect of the viewport
* @param {Object} pointer with "x" and "y" number values
Expand Down Expand Up @@ -1065,7 +1115,7 @@
*/
_fireSelectionEvents: function(oldObjects, e) {
var somethingChanged = false, objects = this.getActiveObjects(),
added = [], removed = [];
added = [], removed = [], invalidate = false;
oldObjects.forEach(function(oldObject) {
if (objects.indexOf(oldObject) === -1) {
somethingChanged = true;
Expand All @@ -1087,24 +1137,28 @@
}
});
if (oldObjects.length > 0 && objects.length > 0) {
invalidate = true;
somethingChanged && this.fire('selection:updated', {
e: e,
selected: added,
deselected: removed,
});
}
else if (objects.length > 0) {
invalidate = true;
this.fire('selection:created', {
e: e,
selected: added,
});
}
else if (oldObjects.length > 0) {
invalidate = true;
this.fire('selection:cleared', {
e: e,
deselected: removed,
});
}
invalidate && (this._objectsToRender = undefined);
},

/**
Expand Down
10 changes: 6 additions & 4 deletions src/controls.actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@
* @return {Number} 0 - 7 a quadrant number
*/
function findCornerQuadrant(fabricObject, control) {
var cornerAngle = fabricObject.angle + radiansToDegrees(Math.atan2(control.y, control.x)) + 360;
// angle is relative to canvas plane
var angle = fabricObject.getTotalAngle();
var cornerAngle = angle + radiansToDegrees(Math.atan2(control.y, control.x)) + 360;
return Math.round((cornerAngle % 360) / 45);
}

Expand Down Expand Up @@ -193,7 +195,7 @@
*/
function wrapWithFixedAnchor(actionHandler) {
return function(eventData, transform, x, y) {
var target = transform.target, centerPoint = target.getCenterPoint(),
var target = transform.target, centerPoint = target.getRelativeCenterPoint(),
constraint = target.translateToOriginPoint(centerPoint, transform.originX, transform.originY),
actionPerformed = actionHandler(eventData, transform, x, y);
target.setPositionByOrigin(constraint, transform.originX, transform.originY);
Expand Down Expand Up @@ -231,7 +233,7 @@
control = target.controls[transform.corner],
zoom = target.canvas.getZoom(),
padding = target.padding / zoom,
localPoint = target.toLocalPoint(new fabric.Point(x, y), originX, originY);
localPoint = target.normalizePoint(new fabric.Point(x, y), originX, originY);
if (localPoint.x >= padding) {
localPoint.x -= padding;
}
Expand Down Expand Up @@ -469,7 +471,7 @@
function rotationWithSnapping(eventData, transform, x, y) {
var t = transform,
target = t.target,
pivotPoint = target.translateToOriginPoint(target.getCenterPoint(), t.originX, t.originY);
pivotPoint = target.translateToOriginPoint(target.getRelativeCenterPoint(), t.originX, t.originY);

if (target.lockRotation) {
return false;
Expand Down
4 changes: 3 additions & 1 deletion src/controls.render.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,9 @@
// this is still wrong
ctx.lineWidth = 1;
ctx.translate(left, top);
ctx.rotate(degreesToRadians(fabricObject.angle));
// angle is relative to canvas plane
var angle = fabricObject.getTotalAngle();
ctx.rotate(degreesToRadians(angle));
// this does not work, and fixed with ( && ) does not make sense.
// to have real transparent corners we need the controls on upperCanvas
// transparentCorners || ctx.clearRect(-xSizeBy2, -ySizeBy2, xSize, ySize);
Expand Down
17 changes: 17 additions & 0 deletions src/mixins/object_ancestry.mixin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prototype */ {

/**
*
* @param {boolean} [strict] returns only ancestors that are objects (without canvas)
* @returns {(fabric.Object | fabric.StaticCanvas)[]} ancestors from bottom to top
*/
getAncestors: function (strict) {
var ancestors = [];
var parent = this.group || (!strict ? this.canvas : undefined);
while (parent) {
ancestors.push(parent);
parent = parent.group || (!strict ? parent.canvas : undefined);
}
return ancestors;
}
});
2 changes: 1 addition & 1 deletion src/mixins/object_geometry.mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -536,7 +536,7 @@
* @return {Array} rotation matrix for the object
*/
_calcTranslateMatrix: function() {
var center = this.getCenterPoint();
var center = this.getRelativeCenterPoint();
return [1, 0, 0, 1, center.x, center.y];
},

Expand Down
Loading