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

[Bug]: Flip object inside group whose interactive is true got wrong behavior. #9801

Closed
7 tasks done
ritali4912 opened this issue Apr 16, 2024 · 10 comments · Fixed by #9811
Closed
7 tasks done

[Bug]: Flip object inside group whose interactive is true got wrong behavior. #9801

ritali4912 opened this issue Apr 16, 2024 · 10 comments · Fixed by #9811
Labels

Comments

@ritali4912
Copy link

CheckList

  • I agree to follow this project's Code of Conduct
  • I have read and followed the Contributing Guide
  • I have read and followed the Issue Tracker Guide
  • I have searched and referenced existing issues and discussions
  • I am filing a BUG report.
  • I have managed to reproduce the bug after upgrading to the latest version
  • I have created an accurate and minimal reproduction

Version

6.0.0-beta20

In What environments are you experiencing the problem?

Microsoft Edge

Node Version (if applicable)

None

Link To Reproduction

https://jsfiddle.net/ritali4912/x6nd5e7k/11/

Steps To Reproduce

There is a group whose subTargetCheck: true, interactive: true.
Then I flip one of its children, but got strange behavior. It seems the control after flip are wrong.
Refer to the below gif.

FlipObjectInsideGroupWithWrong

Expected Behavior

The child object inside group can scale/flip as normal.

Actual Behavior

The child object seems got wrong controls after flip.

Error Message & Stack Trace

No response

@asturur asturur added the bug label Apr 16, 2024
@asturur
Copy link
Member

asturur commented Apr 16, 2024

i ll look into this tomorrow morning

@asturur
Copy link
Member

asturur commented Apr 18, 2024

Ok i looked at this, i have some code changes that improve the situation but do not fix it entirely.
I ll look more

@asturur
Copy link
Member

asturur commented Apr 22, 2024

I made a render control function to help me debugging the issue, it seems clear to me that the controls get wrongly placed

image

But i m not entirely sure yet if is the cause of the error or just a side effect.
As you see top and bottom are inverted.
I would argue that the correct fix would be detect it and swap them back, but the issue with that is that here are a bunch of situation when you include angles, skews and more where while the controls are drawn correctly the action is still opposite

@asturur
Copy link
Member

asturur commented Apr 22, 2024

Now the same issue can be hit in different ways.
In the case of the blue one the object is not flipped but the group is flipped Y and rotated of 90. that equal as a flipX applied on the object

image

In the case of the blue rectangle only the visual representation is wrong, the actions actually work fine

@asturur
Copy link
Member

asturur commented Apr 22, 2024

This could be a reasonable change that fix the issue and is very scoped to this case.
It does not fix the arrows for now.

       positionMatrix = multiplyTransformMatrices(tMatrix, rMatrix),
       startMatrix = multiplyTransformMatrices(vpt, positionMatrix),
+      transformOptions = this.group
+        ? qrDecompose(this.calcTransformMatrix())
+        : undefined,
       finalMatrix = multiplyTransformMatrices(startMatrix, [
         1 / vpt[0],
         0,
@@ -245,14 +248,17 @@ export class InteractiveFabricObject<
         0,
         0,
       ]),
-      transformOptions = this.group
-        ? qrDecompose(this.calcTransformMatrix())
-        : undefined,
-      dim = this._calculateCurrentDimensions(transformOptions),
-      coords: Record<string, TOCoord> = {};
+      { x, y } = this._calculateCurrentDimensions(transformOptions),
+      coords: Record<string, TOCoord> = {},
+      correctedDims = new Point(Math.abs(x), Math.abs(y));

     this.forEachControl((control, key) => {
-      const position = control.positionHandler(dim, finalMatrix, this, control);
+      const position = control.positionHandler(
+        correctedDims,
+        finalMatrix,
+        this,
+        control
+      );
       // coords[key] are sometimes used as points. Those are points to which we add
       // the property corner and touchCorner from `_calcCornerCoords`.
       // don't remove this assign for an object spread.

@asturur
Copy link
Member

asturur commented Apr 22, 2024

Except this breaks with padding

@asturur
Copy link
Member

asturur commented Apr 22, 2024

Ok we have a PR for this

@ritali4912
Copy link
Author

ritali4912 commented Apr 22, 2024

@asturur Thanks so much to take time to look into this issue and fix it.
May I ask a question? How to get a fabric object's top, left, width, height in absolute coordinates when it inside a group?

E.g.:

  1. A group1 with [rectange1, rectange2] and set subTargetCheck to true.
  2. A rectangle3 on the canvas.
  3. Active Selection both rectangle3 and group1.
    All of them with originX = center, originY = center.

I want to know rectangle1 absolute position (left, top) and dimensions (width, height). is there a way I can get them without remove rect1 from group?

Does below calculation work?
var transformOpt= fabric.util.qrDecompose(rect1.calcTransformMatrix()); // I'm not sure whether the rect1.calcTransformMatrix() is enough.
var centerPoint = rect1.translateToCenterPoint(new fabric.Point(transformOpt.translateX, transformOpt.translateY), "center", "center");
var position = rect1.translateToOriginPoint(centerPoint, rect1.originX, rect1.originY);
var dim = rect1.calculateCurrentDimensions(transformOpt),

Thanks in advance.

@asturur
Copy link
Member

asturur commented Apr 23, 2024

Assuming you are not using strokeUniform, rect.getCoords() should give you all you need, taking in account for group transform

[tl, tr, br, bl] = this.getCoords();

If you are not using a rect or you want know a specific point of a shape where it is in the scene coordinates, you have to calculate where that point is located respect to the center and get that point trasnformed.

For example, the center of a shape inside any nested group, in scene coordinates is always at:

(new Point(0, 0)).transform(shape.calcTransformMatrix())

a point that is 5 unit left and 4 unit lower than the center ( usually pixels ) will be:

(new Point(-5, 4)).transform(shape.calcTransformMatrix())

calcTransforMatrix() take in account your shape scale and rotation, and the group properties.

If you have already accounted for the shape transformation and you want to know only the group transfromation you can use shape.parent.calcTransformMatrix() to get the transform done.

@ritali4912
Copy link
Author

ritali4912 commented Apr 23, 2024

@asturur Thanks so much for the detail answer. :):)
It is very helpful.

May I say, the shape.calcTransformMatrix() will consider not only its parent but also its group properties, right? (I read it from the code and the test seems like this).
Like the case above, rect1 inside group1 and the group1 in an ActiveSelection. Then rect1.calcTransformMatrix() will consider both the Group and ActiveSelection properties.

Why I continue to use this function because I want to get the scaleX, scaleY also.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
2 participants