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

fix(controls): fix lockScalingFlip after controls refactor #6313

Merged
merged 6 commits into from
May 3, 2020
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
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## [4.0.0-beta.12]
- fix(fabric.IText): respect value of `cursorColor` [#6300](https://github.com/fabricjs/fabric.js/pull/6300);
- fix(fabric.Textbox): Improve splitByGrapheme and charSpacing [#6298](https://github.com/fabricjs/fabric.js/pull/6298);
- feat(controls): Reintroduce flip by scaling and lockScalingFlip [#6313](https://github.com/fabricjs/fabric.js/pull/6313);

## [4.0.0-beta.11]
- fix(itext): improved style handling for new lines [#6268](https://github.com/fabricjs/fabric.js/pull/6268)
Expand Down Expand Up @@ -85,7 +86,6 @@ fix(controls): Control.getVisibility will always receive the fabric.Object argum

breaking: All your old control code override will not work
breaking: `uniScaleTransform` has been renamed in `uniformScaling`, meaning changed and the default value swapped. The behaviour is unchanged, but now the description and the name match.
breaking: LockScalingFlip with the scaling flip behaviour are missing now, maybe reimplemented later.
breaking: Object.lockUniScaling is removed. Alternatives to get the same identical functionality with less code are being evaluated.
breaking: Canvas.onBeforeScaleRotate is removed, developers need to migrate to the event `before:transform’

Expand Down
43 changes: 36 additions & 7 deletions src/controls.actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@
skewMap = ['ns', 'nesw', 'ew', 'nwse'],
controls = {},
LEFT = 'left', TOP = 'top', RIGHT = 'right', BOTTOM = 'bottom', CENTER = 'center',
radiansToDegrees = fabric.util.radiansToDegrees;
opposite = {
top: BOTTOM,
bottom: TOP,
left: RIGHT,
right: LEFT,
}, radiansToDegrees = fabric.util.radiansToDegrees,
sign = (Math.sign || function(x) { return ((x > 0) - (x < 0)) || +x; });

function findCornerQuadrant(fabricObject, corner) {
var cornerAngle = fabricObject.angle + radiansToDegrees(Math.atan2(corner.y, corner.x)) + 360;
Expand Down Expand Up @@ -115,10 +121,9 @@
function wrapWithFixedAnchor(actionHandler) {
return function(eventData, transform, x, y) {
var target = transform.target, centerPoint = target.getCenterPoint(),
anchorY = transform.originY, anchorX = transform.originX,
constraint = target.translateToOriginPoint(centerPoint, anchorX, anchorY),
constraint = target.translateToOriginPoint(centerPoint, transform.originX, transform.originY),
actionPerformed = actionHandler(eventData, transform, x, y);
target.setPositionByOrigin(constraint, anchorX, anchorY);
target.setPositionByOrigin(constraint, transform.originX, transform.originY);
return actionPerformed;
};
}
Expand Down Expand Up @@ -371,15 +376,29 @@
lockScalingX = target.lockScalingX, lockScalingY = target.lockScalingY,
by = options.by, newPoint, scaleX, scaleY, dim,
scaleProportionally = scaleIsProportional(eventData, target),
forbidScaling = scalingIsForbidden(target, by, scaleProportionally);
forbidScaling = scalingIsForbidden(target, by, scaleProportionally),
signX, signY;

if (forbidScaling) {
return false;
}

dim = target._getTransformedDimensions();
newPoint = getLocalPoint(transform, transform.originX, transform.originY, x, y);
signX = sign(newPoint.x);
signY = sign(newPoint.y);
if (!transform.signX) {
transform.signX = signX;
}
if (!transform.signY) {
transform.signY = signY;
}

if (target.lockScalingFlip &&
(transform.signX !== signX || transform.signY !== signY)
) {
return false;
}

dim = target._getTransformedDimensions();
// missing detection of flip and logic to switch the origin
if (scaleProportionally && !by) {
// uniform scaling
Expand All @@ -400,6 +419,16 @@
scaleX *= 2;
scaleY *= 2;
}
if (transform.signX !== signX) {
transform.originX = opposite[transform.originX];
scaleX *= -1;
transform.signX = signX;
}
if (transform.signY !== signY) {
transform.originY = opposite[transform.originY];
scaleY *= -1;
transform.signY = signY;
}
// minScale is taken are in the setter.
var oldScaleX = target.scaleX, oldScaleY = target.scaleY;
if (!by) {
Expand Down
51 changes: 51 additions & 0 deletions test/unit/controls_handlers.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
orginY: 'top',
target: target,
corner: 'mr',
signX: 1,
signY: 1,
};
});
hooks.afterEach(function() {
Expand Down Expand Up @@ -52,6 +54,46 @@
fabric.controlHandlers.scalingXOrSkewingY(eventData, transform, 200, 300);
assert.equal(Math.round(transform.target.scaleX), 2);
});
QUnit.test('scalingXOrSkewingY changes scaleX to flip', function(assert) {
transform.target.scaleX = 1;
transform.target.strokeWidth = 0;
var returned = fabric.controlHandlers.scalingXOrSkewingY(eventData, transform, -50, 300);
assert.equal(transform.target.scaleX, 0.5);
assert.equal(transform.target.flipX, true, 'the object flipped X');
assert.equal(returned, true, 'action was permitted');
});
QUnit.test('scalingXOrSkewingY blocks scaleX to flip', function(assert) {
transform.target.scaleX = 1;
transform.target.strokeWidth = 0;
transform.target.lockScalingFlip = true;
var returned = fabric.controlHandlers.scalingXOrSkewingY(eventData, transform, -50, 300);
assert.equal(transform.target.scaleX, 1);
assert.equal(transform.target.flipX, false, 'the object did not flip X');
assert.equal(returned, false, 'action was not permitted X');
});
QUnit.test('scalingYOrSkewingX changes scaleY', function(assert) {
transform.target.scaleY = 1;
transform.target.strokeWidth = 0;
fabric.controlHandlers.scalingYOrSkewingX(eventData, transform, 200, 300);
assert.equal(Math.round(transform.target.scaleY), 3);
});
QUnit.test('scalingYOrSkewingX changes scaleY to flip', function(assert) {
transform.target.scaleY = 1;
transform.target.strokeWidth = 0;
var returned = fabric.controlHandlers.scalingYOrSkewingX(eventData, transform, 200, -80);
assert.equal(transform.target.scaleY, 0.8);
assert.equal(transform.target.flipY, true, 'the object flipped Y');
assert.equal(returned, true, 'action was permitted Y');
});
QUnit.test('scalingYOrSkewingX blocks scaleX to flip', function(assert) {
transform.target.scaley = 1;
transform.target.strokeWidth = 0;
transform.target.lockScalingFlip = true;
var returned = fabric.controlHandlers.scalingYOrSkewingX(eventData, transform, 200, -80);
assert.equal(transform.target.scaleY, 1);
assert.equal(transform.target.flipY, false, 'the object did not flip Y');
assert.equal(returned, false, 'action was not permitted Y');
});
QUnit.test('scalingXOrSkewingY changes skewY if shift pressed', function(assert) {
transform.target.scaleX = 1;
transform.target.skewY = 0;
Expand All @@ -61,6 +103,15 @@
assert.equal(Math.round(transform.target.skewY), 79);
assert.equal(Math.round(transform.target.scaleX), 1);
});
QUnit.test('scalingYOrSkewingX changes skewX if shift pressed', function(assert) {
transform.target.scaleY = 1;
transform.target.skewX = 0;
transform.target.strokeWidth = 0;
eventData.shiftKey = true;
fabric.controlHandlers.scalingYOrSkewingX(eventData, transform, 200, 300);
assert.equal(Math.round(transform.target.skewX), 72);
assert.equal(Math.round(transform.target.scaleY), 1);
});
QUnit.test('scalingXOrSkewingY will fire events on canvas and target', function(assert) {
var done = assert.async();
transform.target.scaleX = 1;
Expand Down