Skip to content

Commit

Permalink
fix(Group): 🛠️ layout, angle and origin ⚡ (#8004)
Browse files Browse the repository at this point in the history
* reactive visual tests

* fix(Group Layout): origin + angle

* Update group.class.js

* add layout + skewing tests

* fix tests size

* fix setting `initialTransform`

* goldens (binaries)

* resize goldens
  • Loading branch information
ShaMan123 authored Jun 15, 2022
1 parent d5107f5 commit d57f350
Show file tree
Hide file tree
Showing 112 changed files with 64 additions and 35 deletions.
31 changes: 11 additions & 20 deletions src/shapes/group.class.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,8 @@
this.__objectSelectionTracker = this.__objectSelectionMonitor.bind(this, true);
this.__objectSelectionDisposer = this.__objectSelectionMonitor.bind(this, false);
this._firstLayoutDone = false;
this.callSuper('initialize', options);
// setting angle, skewX, skewY must occur after initial layout
this.callSuper('initialize', Object.assign({}, options, { angle: 0, skewX: 0, skewY: 0 }));
this.forEachObject(function (object) {
this.enterGroup(object, false);
}, this);
Expand Down Expand Up @@ -501,6 +502,12 @@
// reject layout requests before initialization layout
return;
}
var options = isFirstLayout && context.options;
var initialTransform = options && {
angle: options.angle || 0,
skewX: options.skewX || 0,
skewY: options.skewY || 0,
};
var center = this.getRelativeCenterPoint();
var result = this.getLayoutStrategyResult(this.layout, this._objects.concat(), context);
if (result) {
Expand All @@ -517,9 +524,10 @@
// clip path as well
!isFirstLayout && this.layout !== 'clip-path' && this.clipPath && !this.clipPath.absolutePositioned
&& this._adjustObjectPosition(this.clipPath, diff);
if (!newCenter.eq(center)) {
if (!newCenter.eq(center) || initialTransform) {
// set position
this.setPositionByOrigin(newCenter, 'center', 'center');
initialTransform && this.set(initialTransform);
this.setCoords();
}
}
Expand All @@ -531,6 +539,7 @@
width: this.width,
height: this.height,
};
initialTransform && this.set(initialTransform);
}
else {
// no `result` so we return
Expand Down Expand Up @@ -715,24 +724,6 @@
}),
rotationCorrection = new fabric.Point(0, 0);

if (this.angle) {
var rad = degreesToRadians(this.angle),
sin = Math.abs(fabric.util.sin(rad)),
cos = Math.abs(fabric.util.cos(rad));
sizeAfter.setXY(
sizeAfter.x * cos + sizeAfter.y * sin,
sizeAfter.x * sin + sizeAfter.y * cos
);
bboxSizeAfter.setXY(
bboxSizeAfter.x * cos + bboxSizeAfter.y * sin,
bboxSizeAfter.x * sin + bboxSizeAfter.y * cos
);
strokeWidthVector = fabric.util.rotateVector(strokeWidthVector, rad);
// correct center after rotating
var strokeCorrection = strokeWidthVector.multiply(origin.scalarAdd(-0.5).scalarDivide(-2));
rotationCorrection = sizeAfter.subtract(size).scalarDivide(2).add(strokeCorrection);
calculatedCenter.addEquals(rotationCorrection);
}
// calculate center and correction
var originT = origin.scalarAdd(0.5);
var originCorrection = sizeAfter.multiply(originT);
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
68 changes: 53 additions & 15 deletions test/visual/group_layout.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@
test: 'fit-content layout',
code: fitContentLayoutRelative,
golden: 'group-layout/fit-content.png',
newModule: 'Group Layout',
percentage: 0.06,
width: 400,
height: 300
Expand All @@ -118,6 +117,44 @@
height: 300
});

function fitContentLayoutWithSkewX(canvas, callback) {
var g = createGroupForLayoutTests('fit-content layout', {
backgroundColor: 'blue',
skewX: 45
});
canvas.add(g);
canvas.renderAll();
callback(canvas.lowerCanvasEl);
}

tests.push({
test: 'fit-content layout',
code: fitContentLayoutWithSkewX,
golden: 'group-layout/fit-content-skewX.png',
percentage: 0.06,
width: 400 + Math.ceil(300 / Math.SQRT2),
height: 300
});

function fitContentLayoutWithSkewY(canvas, callback) {
var g = createGroupForLayoutTests('fit-content layout', {
backgroundColor: 'blue',
skewY: 45
});
canvas.add(g);
canvas.renderAll();
callback(canvas.lowerCanvasEl);
}

tests.push({
test: 'fit-content layout',
code: fitContentLayoutWithSkewY,
golden: 'group-layout/fit-content-skewY.png',
percentage: 0.06,
width: 400,
height: 400 + Math.ceil(400 / Math.SQRT2)
});

function nestedLayout(canvas, callback) {
var rect3 = new fabric.Rect({
width: 100,
Expand Down Expand Up @@ -214,7 +251,6 @@
test: 'fit-content layout add object',
code: fitContentLayoutAdd,
golden: 'group-layout/fit-content3.png',
newModule: 'Group Layout',
percentage: 0.06,
width: 400,
height: 300
Expand Down Expand Up @@ -323,37 +359,39 @@
});

function createObjectsForOriginTests(originX, originY, options) {
var rect1 = new fabric.Rect({ top: 100, left: 150, width: 30, height: 10, strokeWidth: 0 }),
rect2 = new fabric.Rect({ top: 120, left: 200, width: 10, height: 40, strokeWidth: 0 }),
controlPoint = new fabric.Circle({ radius: 5, fill: 'blue', left: 150, top: 100, originX: 'center', originY: 'center' });
var rect1 = new fabric.Rect({ left: 150, top: 100, width: 30, height: 10, strokeWidth: 0 }),
rect2 = new fabric.Rect({ left: 200, top: 120, width: 10, height: 40, strokeWidth: 0 }),
controlPoint = new fabric.Circle({ radius: 5, fill: 'blue', left: 150, top: 100, originX: 'center', originY: 'center' }),
tlControlPoint = new fabric.Circle({ radius: 5, fill: 'red', left: 150, top: 100, strokeWidth: 0 });

var g = new fabric.Group([rect1, rect2], Object.assign({}, options, {
originX, originY, strokeWidth: 1, stroke: 'blue'
var g = new fabric.Group([rect1, rect2, tlControlPoint], Object.assign({}, options, {
originX, originY, backgroundColor: 'pink'
}));
return [controlPoint, g];
return [g, controlPoint];
}

var originX = ['left', 'center', 'right'];
var originY = ['top', 'center', 'bottom'];
/*

for (let angle = 0; angle < 360; angle += 30) {
originX.forEach(ox => {
originY.forEach(oy => {
tests.push({
test: `layout with originX=${ox}, originY=${oy} and angle=${angle} values - angle is WRONG`,
test: `layout with originX=${ox}, originY=${oy} and angle=${angle} values`,
code: function (canvas, callback) {
canvas.add(...createObjectsForOriginTests(ox, oy, { angle }));
canvas.add.apply(canvas, createObjectsForOriginTests(ox, oy, { angle }));
canvas.setViewportTransform([1, 0, 0, 1, -50, 0]);
canvas.renderAll();
callback(canvas.lowerCanvasEl);
},
golden: `group-layout/origin-${ox}-${oy}-${angle}deg.png`,
percentage: 0.06,
width: 300,
height: 300
percentage: 0.001,
width: 200,
height: 200
});
});
});
}
*/

tests.forEach(visualTestLoop(QUnit));
})();

0 comments on commit d57f350

Please sign in to comment.