[BACK_INCOMPAT] Split fabric.Object.centerTransform and fabric.Canvas.centerTransform into the properties centeredScaling and centeredRotation

centeredScaling: Define if object scaling should be centered (true). Default = false.
centeredRotation: Define if object rotates around center (true) or around origin (originX/originY) point (false).  Default = false.
Pressed altKey negates the behavior.
This commit is contained in:
Kienz 2013-09-26 18:19:17 +02:00
parent 365b2dc0a9
commit 5f9edecd18
3 changed files with 120 additions and 56 deletions

View file

@ -48,11 +48,22 @@
uniScaleTransform: false,
/**
* When true, objects use center point as the origin of transformation
* When true, objects use center point as the origin of scale transformation.
* <b>Backwards incompatibility note:</b> This property replaces "centerTransform" (Boolean).
* @since 1.3.4
* @type Boolean
* @default
*/
centerTransform: false,
centeredScaling: false,
/**
* When true, objects use center point as the origin of rotate transformation.
* <b>Backwards incompatibility note:</b> This property replaces "centerTransform" (Boolean).
* @since 1.3.4
* @type Boolean
* @default
*/
centeredRotation: false,
/**
* Indicates that canvas is interactive. This property should not be changed.
@ -80,7 +91,7 @@
* If not empty the selection border is dashed
* @type Array
*/
selectionDashArray: [ ],
selectionDashArray: [ ],
/**
* Color of the border of selection (usually slightly darker than color of selection itself)
@ -136,7 +147,7 @@
* @type String
* @default
*/
containerClass: 'canvas-container',
containerClass: 'canvas-container',
/**
* When true, object detection happens on per-pixel basis rather than on per-bounding-box
@ -157,7 +168,7 @@
* @type Boolean
* @default
*/
skipTargetFind: false,
skipTargetFind: false,
/**
* @private
@ -182,31 +193,38 @@
_resetCurrentTransform: function(e) {
var t = this._currentTransform;
t.target.set('scaleX', t.original.scaleX);
t.target.set('scaleY', t.original.scaleY);
t.target.set('left', t.original.left);
t.target.set('top', t.original.top);
t.target.set({
'scaleX': t.original.scaleX,
'scaleY': t.original.scaleY,
'left': t.original.left,
'top': t.original.top
});
if (e.altKey || this.centerTransform || t.target.centerTransform) {
if (t.originX !== 'center') {
if (t.originX === 'right') {
t.mouseXSign = -1;
}
else {
t.mouseXSign = 1;
}
if (this._shouldCenterTransform(e, t.target)) {
if (t.action === 'rotate') {
this._setOriginToCenter(t.target);
}
if (t.originY !== 'center') {
if (t.originY === 'bottom') {
t.mouseYSign = -1;
else {
if (t.originX !== 'center') {
if (t.originX === 'right') {
t.mouseXSign = -1;
}
else {
t.mouseXSign = 1;
}
}
else {
t.mouseYSign = 1;
if (t.originY !== 'center') {
if (t.originY === 'bottom') {
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;
@ -323,6 +341,27 @@
);
},
/**
* @private
* @param {Event} e Event object
* @param {fabric.Object} target
*/
_shouldCenterTransform: function (e, target) {
if (!target) return;
var t = this._currentTransform,
centerTransform;
if (t.action === 'scale' || t.action === 'scaleX' || t.action === 'scaleY') {
centerTransform = this.centeredScaling || target.centeredScaling;
}
else if (t.action === 'rotate') {
centerTransform = this.centeredRotation || target.centeredRotation;
}
return centerTransform ? !e.altKey : e.altKey;
},
/**
* @private
* @param {Event} e Event object
@ -346,7 +385,8 @@
: 'scale';
}
var originX = target.originX, originY = target.originY;
var originX = target.originX,
originY = target.originY;
if (corner === 'ml' || corner === 'tl' || corner === 'bl') {
originX = "right";
@ -362,12 +402,6 @@
originY = "top";
}
// if (corner === 'mtr') {
// originX = 'center';
// originY = 'center';
// }
// var center = target.getCenterPoint();
this._currentTransform = {
target: target,
action: action,

View file

@ -138,7 +138,6 @@
* @param {Event} e Event object fired on mouseup
*/
__onMouseUp: function (e) {
var target,
pointer,
render;
@ -249,7 +248,6 @@
* @param {Event} e Event object fired on mousedown
*/
__onMouseDown: function (e) {
// accept only left clicks
var isLeftClick = 'which' in e ? e.which === 1 : e.button === 1;
if (!isLeftClick && !fabric.isTouchSupported) return;
@ -308,17 +306,13 @@
this.fire('mouse:down', { target: target, e: e });
target && target.fire('mousedown', { e: e });
if (corner === 'mtr' && target.centerTransform) {
this._setOriginToCenter(target);
}
},
/**
* @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;
@ -334,6 +328,26 @@
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
@ -344,7 +358,6 @@
* @param {Event} e Event object fired on mousemove
*/
__onMouseMove: function (e) {
var target, pointer;
if (this.isDrawingMode) {
@ -394,19 +407,23 @@
var x = pointer.x,
y = pointer.y,
reset = false,
centerTransform,
transform = this._currentTransform;
target = transform.target;
target.isMoving = true;
if ((transform.action === 'scale' || transform.action === 'scaleX' || transform.action === 'scaleY') &&
// Switch from a normal resize to center-based
((e.altKey && (transform.originX !== 'center' || transform.originY !== 'center')) ||
// Switch from center-based resize to normal one
(!e.altKey && transform.originX === 'center' && transform.originY === 'center'))
) {
this._resetCurrentTransform(e);
reset = true;
if (transform.action === 'scale' || transform.action === 'scaleX' || transform.action === 'scaleY') {
centerTransform = this._shouldCenterTransform(e, target);
// Switch from a normal resize to center-based
if ((centerTransform && (transform.originX !== 'center' || transform.originY !== 'center')) ||
// Switch from center-based resize to normal one
(!centerTransform && transform.originX === 'center' && transform.originY === 'center')
) {
this._resetCurrentTransform(e);
reset = true;
}
}
if (transform.action === 'rotate') {
@ -425,7 +442,7 @@
else {
// Switch from a normal resize to proportional
if (!reset && transform.currentAction === 'scale') {
this._resetCurrentTransform(e);
this._resetCurrentTransform(e, target);
}
transform.currentAction = 'scaleEqually';

View file

@ -154,10 +154,23 @@
/**
* When true, this object will use center point as the origin of transformation
* when being resized via the controls
* when being scaled via the controls.
* <b>Backwards incompatibility note:</b> This property replaces "centerTransform" (Boolean).
* @since 1.3.4
* @type Boolean
* @default
*/
centerTransform: false,
centeredScaling: false,
/**
* When true, this object will use center point as the origin of transformation
* when being rotated via the controls.
* <b>Backwards incompatibility note:</b> This property replaces "centerTransform" (Boolean).
* @since 1.3.4
* @type Boolean
* @default
*/
centeredRotation: false,
/**
* Color of object's fill
@ -264,7 +277,7 @@
selectable: true,
/**
* When set to `false`, an object can not be a target of events. All events propagate through it. Introduced in v1.3.4
* When set to `false`, an object can not be a target of events. All events propagate through it.
* @type Boolean
* @default
*/
@ -872,10 +885,10 @@
* @param {String} [options.format=png] The format of the output image. Either "jpeg" or "png"
* @param {Number} [options.quality=1] Quality level (0..1). Only used for jpeg.
* @param {Number} [options.multiplier=1] Multiplier to scale by
* @param {Number} [options.left] Cropping left offset. Introduced in v1.2.14
* @param {Number} [options.top] Cropping top offset. Introduced in v1.2.14
* @param {Number} [options.width] Cropping width. Introduced in v1.2.14
* @param {Number} [options.height] Cropping height. Introduced in v1.2.14
* @param {Number} [options.left] Cropping left offset
* @param {Number} [options.top] Cropping top offset
* @param {Number} [options.width] Cropping width
* @param {Number} [options.height] Cropping height
* @return {String} Returns a data: URL containing a representation of the object in the format specified by options.format
*/
toDataURL: function(options) {