diff --git a/src/canvas.class.js b/src/canvas.class.js index 8cd60d0bc9d..ba425fa4ed1 100644 --- a/src/canvas.class.js +++ b/src/canvas.class.js @@ -425,30 +425,25 @@ }); if (this._shouldCenterTransform(t.target)) { - if (t.action === 'rotate') { - this._setOriginToCenter(t.target); + if (t.originX !== 'center') { + if (t.originX === 'right') { + t.mouseXSign = -1; + } + else { + t.mouseXSign = 1; + } } - else { - if (t.originX !== 'center') { - if (t.originX === 'right') { - t.mouseXSign = -1; - } - else { - t.mouseXSign = 1; - } + if (t.originY !== 'center') { + if (t.originY === 'bottom') { + t.mouseYSign = -1; } - if (t.originY !== 'center') { - if (t.originY === 'bottom') { - t.mouseYSign = -1; - } - else { - t.mouseYSign = 1; - } + else { + t.mouseYSign = 1; } - - t.originX = 'center'; - t.originY = 'center'; } + + t.originX = 'center'; + t.originY = 'center'; } else { t.originX = t.original.originX; @@ -571,6 +566,8 @@ }, /** + * centeredScaling from object can't override centeredScaling from canvas. + * this should be fixed, since object setting should take precedence over canvas. * @private * @param {fabric.Object} target */ @@ -663,6 +660,7 @@ 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, @@ -671,9 +669,11 @@ ey: pointer.y, lastX: pointer.x, lastY: pointer.y, - left: target.left, - top: target.top, + // unsure they are usefull anymore. + // left: target.left, + // top: target.top, theta: degreesToRadians(target.angle), + // end of unsure width: target.width * target.scaleX, mouseXSign: 1, mouseYSign: 1, @@ -843,9 +843,9 @@ _scaleObject: function (x, y, by) { var t = this._currentTransform, target = t.target, - lockScalingX = target.get('lockScalingX'), - lockScalingY = target.get('lockScalingY'), - lockScalingFlip = target.get('lockScalingFlip'); + lockScalingX = target.lockScalingX, + lockScalingY = target.lockScalingY, + lockScalingFlip = target.lockScalingFlip; if (lockScalingX && lockScalingY) { return false; @@ -1015,20 +1015,22 @@ */ _rotateObject: function (x, y) { - var t = this._currentTransform; + var t = this._currentTransform, + target = t.target, constraintPosition, + constraintPosition = target.translateToOriginPoint(target.getCenterPoint(), t.originX, t.originY); - if (t.target.get('lockRotation')) { + if (target.lockRotation) { return false; } - var lastAngle = atan2(t.ey - t.top, t.ex - t.left), - curAngle = atan2(y - t.top, x - t.left), + var lastAngle = atan2(t.ey - constraintPosition.y, t.ex - constraintPosition.x), + curAngle = atan2(y - constraintPosition.y, x - constraintPosition.x), angle = radiansToDegrees(curAngle - lastAngle + t.theta), hasRotated = true; - if (t.target.snapAngle > 0) { - var snapAngle = t.target.snapAngle, - snapThreshold = t.target.snapThreshold || snapAngle, + if (target.snapAngle > 0) { + var snapAngle = target.snapAngle, + snapThreshold = target.snapThreshold || snapAngle, rightAngleLocked = Math.ceil(angle / snapAngle) * snapAngle, leftAngleLocked = Math.floor(angle / snapAngle) * snapAngle; @@ -1046,11 +1048,14 @@ } angle %= 360; - if (t.target.angle === angle) { + if (target.angle === angle) { hasRotated = false; } else { - t.target.angle = angle; + // rotation only happen here + target.angle = angle; + // Make sure the constraints apply + target.setPositionByOrigin(constraintPosition, t.originX, t.originY); } return hasRotated; diff --git a/src/mixins/canvas_events.mixin.js b/src/mixins/canvas_events.mixin.js index 3d55fcdfe14..0c9c222d145 100644 --- a/src/mixins/canvas_events.mixin.js +++ b/src/mixins/canvas_events.mixin.js @@ -467,7 +467,6 @@ } target.setCoords(); - this._restoreOriginXY(target); if (transform.actionPerformed || (this.stateful && target.hasStateChanged())) { this.fire('object:modified', { target: target, e: e }); @@ -475,29 +474,6 @@ } }, - /** - * @private - * @param {Object} target Object to restore - */ - _restoreOriginXY: function(target) { - if (this._previousOriginX && this._previousOriginY) { - - var originPoint = target.translateToOriginPoint( - target.getCenterPoint(), - this._previousOriginX, - this._previousOriginY); - - target.originX = this._previousOriginX; - target.originY = this._previousOriginY; - - target.left = originPoint.x; - target.top = originPoint.y; - - this._previousOriginX = null; - this._previousOriginY = null; - } - }, - /** * @private * @param {Event} e Event object fired on mousedown @@ -628,46 +604,6 @@ }, - /** - * @private - * @param {Object} target Object for that origin is set to center - */ - _setOriginToCenter: function(target) { - this._previousOriginX = this._currentTransform.target.originX; - this._previousOriginY = this._currentTransform.target.originY; - - var center = target.getCenterPoint(); - - target.originX = 'center'; - target.originY = 'center'; - - target.left = center.x; - target.top = center.y; - - this._currentTransform.left = target.left; - this._currentTransform.top = target.top; - }, - - /** - * @private - * @param {Object} target Object for that center is set to origin - */ - _setCenterToOrigin: function(target) { - var originPoint = target.translateToOriginPoint( - target.getCenterPoint(), - this._previousOriginX, - this._previousOriginY); - - target.originX = this._previousOriginX; - target.originY = this._previousOriginY; - - target.left = originPoint.x; - target.top = originPoint.y; - - this._previousOriginX = null; - this._previousOriginY = null; - }, - /** * Method that defines the actions when mouse is hovering the canvas. * The currentTransform parameter will definde whether the user is rotating/scaling/translating diff --git a/src/mixins/canvas_gestures.mixin.js b/src/mixins/canvas_gestures.mixin.js index 961bd297e9e..47c0fe81e98 100644 --- a/src/mixins/canvas_gestures.mixin.js +++ b/src/mixins/canvas_gestures.mixin.js @@ -53,7 +53,6 @@ t.action = 'scale'; t.originX = t.originY = 'center'; - this._setOriginToCenter(t.target); this._scaleObjectBy(self.scale, e); @@ -62,8 +61,6 @@ this._rotateObjectByAngle(self.rotation, e); } - this._setCenterToOrigin(t.target); - this.requestRenderAll(); t.action = 'drag'; }, @@ -155,7 +152,7 @@ if (t.target.get('lockRotation')) { return; } - t.target.angle = radiansToDegrees(degreesToRadians(curAngle) + t.theta); + t.target.rotate(radiansToDegrees(degreesToRadians(curAngle) + t.theta)); this._fire('rotating', t.target, e); } }); diff --git a/test/unit/canvas.js b/test/unit/canvas.js index 2fe145ccd5a..3401bd40e83 100644 --- a/test/unit/canvas.js +++ b/test/unit/canvas.js @@ -1980,9 +1980,45 @@ assert.equal(t.target, rect, 'should have rect as a target'); assert.equal(t.action, 'rotate', 'should target a corner and setup rotate'); assert.equal(t.corner, 'mtr', 'mtr selected'); + assert.equal(t.originX, 'center', 'origin in center'); + assert.equal(t.originY, 'center', 'origin in center'); canvas._currentTransform = false; }); + QUnit.test('_rotateObject', function(assert) { + assert.ok(typeof canvas._rotateObject === 'function'); + var rect = new fabric.Rect({ left: 75, top: 75, width: 50, height: 50 }); + canvas.add(rect); + var canvasEl = canvas.getElement(), + canvasOffset = fabric.util.getElementOffset(canvasEl); + var eventStub = { + clientX: canvasOffset.left + rect.oCoords.mtr.x, + clientY: canvasOffset.top + rect.oCoords.mtr.y, + target: rect, + }; + canvas._setupCurrentTransform(eventStub, rect); + var rotated = canvas._rotateObject(30, 30, 'equally'); + assert.equal(rotated, true, 'return true if a rotation happened'); + rotated = canvas._rotateObject(30, 30); + assert.equal(rotated, false, 'return true if no rotation happened'); + }); + + QUnit.test('_rotateObject do not change origins', function(assert) { + assert.ok(typeof canvas._rotateObject === 'function'); + var rect = new fabric.Rect({ left: 75, top: 75, width: 50, height: 50, originX: 'right', originY: 'bottom' }); + canvas.add(rect); + var canvasEl = canvas.getElement(), + canvasOffset = fabric.util.getElementOffset(canvasEl); + var eventStub = { + clientX: canvasOffset.left + rect.oCoords.mtr.x, + clientY: canvasOffset.top + rect.oCoords.mtr.y, + target: rect, + }; + canvas._setupCurrentTransform(eventStub, rect); + assert.equal(rect.originX, 'right'); + assert.equal(rect.originY, 'bottom'); + }); + QUnit.test('_scaleObject', function(assert) { assert.ok(typeof canvas._scaleObject === 'function'); var rect = new fabric.Rect({ left: 75, top: 75, width: 50, height: 50 });