Skip to content

Commit

Permalink
Switch to different coordinates for groups (#3420)
Browse files Browse the repository at this point in the history
* rework coords for groups
* fixes typo
* separate set coords from calculation
* add options to bounding rect
  • Loading branch information
asturur authored Nov 14, 2016
2 parents 9422fd3 + 11dc62c commit 525cae5
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 45 deletions.
6 changes: 2 additions & 4 deletions src/canvas.class.js
Original file line number Diff line number Diff line change
Expand Up @@ -449,10 +449,8 @@
_normalizePointer: function (object, pointer) {
var m = object.calcTransformMatrix(),
invertedM = fabric.util.invertTransform(m),
vpt = this.viewportTransform,
vptPointer = this.restorePointerVpt(pointer),
p = fabric.util.transformPoint(vptPointer, invertedM);
return fabric.util.transformPoint(p, vpt);
vptPointer = this.restorePointerVpt(pointer);
return fabric.util.transformPoint(vptPointer, invertedM);
},

/**
Expand Down
54 changes: 29 additions & 25 deletions src/mixins/object_geometry.mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -198,15 +198,17 @@

/**
* Returns coordinates of object's bounding rectangle (left, top, width, height)
* the box is intented as aligned to axis of canvas.
* @param {Boolean} ignoreVpt bounding box will not be affected by viewportTransform
* @return {Object} Object with left, top, width, height properties
*/
getBoundingRect: function() {
this.oCoords || this.setCoords();
getBoundingRect: function(ignoreVpt) {
var coords = this.calcCoords(ignoreVpt);
return fabric.util.makeBoundingBoxFromPoints([
this.oCoords.tl,
this.oCoords.tr,
this.oCoords.br,
this.oCoords.bl
coords.tl,
coords.tr,
coords.br,
coords.bl
]);
},

Expand Down Expand Up @@ -262,8 +264,7 @@

this.scaleX = value;
this.scaleY = value;
this.setCoords();
return this;
return this.setCoords();
},

/**
Expand Down Expand Up @@ -291,31 +292,24 @@
},

/**
* Sets corner position coordinates based on current angle, width and height
* See https://github.com/kangax/fabric.js/wiki/When-to-call-setCoords
* @return {fabric.Object} thisArg
* Calculate and returns the .coords of an object.
* @return {Object} Object with tl, tr, br, bl ....
* @chainable
*/
setCoords: function() {
calcCoords: function(ignoreVpt) {
var theta = degreesToRadians(this.angle),
vpt = this.getViewportTransform(),
dim = this._calculateCurrentDimensions(),
currentWidth = dim.x, currentHeight = dim.y;

// If width is negative, make postive. Fixes path selection issue
if (currentWidth < 0) {
currentWidth = Math.abs(currentWidth);
}

var sinTh = Math.sin(theta),
dim = ignoreVpt ? this._getTransformedDimensions() : this._calculateCurrentDimensions(),
currentWidth = dim.x, currentHeight = dim.y,
sinTh = Math.sin(theta),
cosTh = Math.cos(theta),
_angle = currentWidth > 0 ? Math.atan(currentHeight / currentWidth) : 0,
_hypotenuse = (currentWidth / Math.cos(_angle)) / 2,
offsetX = Math.cos(_angle + theta) * _hypotenuse,
offsetY = Math.sin(_angle + theta) * _hypotenuse,

center = this.getCenterPoint(),
// offset added for rotate and scale actions
coords = fabric.util.transformPoint(this.getCenterPoint(), vpt),
coords = ignoreVpt ? center : fabric.util.transformPoint(center, vpt),
tl = new fabric.Point(coords.x - offsetX, coords.y - offsetY),
tr = new fabric.Point(tl.x + (currentWidth * cosTh), tl.y + (currentWidth * sinTh)),
bl = new fabric.Point(tl.x - (currentHeight * sinTh), tl.y + (currentHeight * cosTh)),
Expand All @@ -340,17 +334,27 @@
canvas.contextTop.fillRect(mtr.x, mtr.y, 3, 3);
}, 50); */

this.oCoords = {
return {
// corners
tl: tl, tr: tr, br: br, bl: bl,
// middle
ml: ml, mt: mt, mr: mr, mb: mb,
// rotating point
mtr: mtr
};
},

/**
* Sets corner position coordinates based on current angle, width and height
* See https://github.com/kangax/fabric.js/wiki/When-to-call-setCoords
* @return {fabric.Object} thisArg
* @chainable
*/
setCoords: function(ignoreZoom) {
this.oCoords = this.calcCoords(ignoreZoom);

// set coordinates of the draggable boxes in the corners used to scale/rotate the image
this._setCornerCoords && this._setCornerCoords();
ignoreZoom || this._setCornerCoords && this._setCornerCoords();

return this;
},
Expand Down
7 changes: 3 additions & 4 deletions src/mixins/object_interactivity.mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,7 @@
_calculateCurrentDimensions: function() {
var vpt = this.getViewportTransform(),
dim = this._getTransformedDimensions(),
w = dim.x, h = dim.y,
p = fabric.util.transformPoint(new fabric.Point(w, h), vpt, true);
p = fabric.util.transformPoint(dim, vpt, true);

return p.scalarAdd(2 * this.padding);
},
Expand Down Expand Up @@ -254,8 +253,8 @@
matrix = fabric.util.customTransformMatrix(options.scaleX, options.scaleY, options.skewX),
wh = fabric.util.transformPoint(p, matrix),
strokeWidth = 1 / this.borderScaleFactor,
width = wh.x + strokeWidth + 2 * this.padding,
height = wh.y + strokeWidth + 2 * this.padding;
width = wh.x + strokeWidth,
height = wh.y + strokeWidth;

ctx.save();
this._setLineDash(ctx, this.borderDashArray, null);
Expand Down
26 changes: 16 additions & 10 deletions src/shapes/group.class.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,17 +106,19 @@
* @param {Boolean} [skipCoordsChange] if true, coordinates of objects enclosed in a group do not change
*/
_updateObjectsCoords: function(skipCoordsChange) {
var center = this.getCenterPoint();
for (var i = this._objects.length; i--; ){
this._updateObjectCoords(this._objects[i], skipCoordsChange);
this._updateObjectCoords(this._objects[i], center, skipCoordsChange);
}
},

/**
* @private
* @param {Object} object
* @param {fabric.Point} center, current center of group.
* @param {Boolean} [skipCoordsChange] if true, coordinates of object dose not change
*/
_updateObjectCoords: function(object, skipCoordsChange) {
_updateObjectCoords: function(object, center, skipCoordsChange) {
// do not display corners of objects enclosed in a group
object.__origHasControls = object.hasControls;
object.hasControls = false;
Expand All @@ -127,15 +129,15 @@

var objectLeft = object.getLeft(),
objectTop = object.getTop(),
center = this.getCenterPoint();
ignoreZoom = true;

object.set({
originalLeft: objectLeft,
originalTop: objectTop,
left: objectLeft - center.x,
top: objectTop - center.y
});
object.setCoords();
object.setCoords(ignoreZoom);
},

/**
Expand Down Expand Up @@ -309,10 +311,13 @@
* @param {Boolean} [noTransform] When true, context is not transformed
*/
_renderControls: function(ctx, noTransform) {
ctx.save();
ctx.globalAlpha = this.isMoving ? this.borderOpacityWhenMoving : 1;
this.callSuper('_renderControls', ctx, noTransform);
for (var i = 0, len = this._objects.length; i < len; i++) {
this._objects[i]._renderControls(ctx);
}
ctx.restore();
},

/**
Expand Down Expand Up @@ -417,8 +422,9 @@
* @chainable
*/
setObjectsCoords: function() {
var ignoreZoom = true;
this.forEachObject(function(object) {
object.setCoords();
object.setCoords(ignoreZoom);
});
return this;
},
Expand All @@ -432,11 +438,12 @@
o, prop,
props = ['tr', 'br', 'bl', 'tl'],
i = 0, iLen = this._objects.length,
j, jLen = props.length;
j, jLen = props.length,
ignoreZoom = true;

for ( ; i < iLen; ++i) {
o = this._objects[i];
o.setCoords();
o.setCoords(ignoreZoom);
for (j = 0; j < jLen; j++) {
prop = props[j];
aX.push(o.oCoords[prop].x);
Expand All @@ -451,9 +458,8 @@
* @private
*/
_getBounds: function(aX, aY, onlyWidthHeight) {
var ivt = fabric.util.invertTransform(this.getViewportTransform()),
minXY = fabric.util.transformPoint(new fabric.Point(min(aX), min(aY)), ivt),
maxXY = fabric.util.transformPoint(new fabric.Point(max(aX), max(aY)), ivt),
var minXY = new fabric.Point(min(aX), min(aY)),
maxXY = new fabric.Point(max(aX), max(aY)),
obj = {
width: (maxXY.x - minXY.x) || 0,
height: (maxXY.y - minXY.y) || 0
Expand Down
5 changes: 3 additions & 2 deletions src/shapes/object.class.js
Original file line number Diff line number Diff line change
Expand Up @@ -1343,8 +1343,9 @@
ctx.save();
ctx.translate(options.translateX, options.translateY);
ctx.lineWidth = 1 * this.borderScaleFactor;
ctx.globalAlpha = this.isMoving ? this.borderOpacityWhenMoving : 1;

if (!this.group) {
ctx.globalAlpha = this.isMoving ? this.borderOpacityWhenMoving : 1;
}
if (this.group && this.group === this.canvas.getActiveGroup()) {
ctx.rotate(degreesToRadians(options.angle));
this.drawBordersInGroup(ctx, options);
Expand Down

0 comments on commit 525cae5

Please sign in to comment.