How transform works?

In Bluescape, each element has a boundingBox

boundingBox {
  x
  y
  width
  height
}

and we have a transform object to move, rotate and scale the element.
By inspecting the behaviour of Bluescape, I couldn’t understand how it works.

Can you please explain how final position of an element be calculated?

It seems final x is not boundingBox.x+transform.x if we ignore scaling and rotation. When I inspect the Bluescape response most of the time boundingBox.x and transform.x are equal and sometime they are different! I don’t understand why they are equal most of the time?

How final width calculated? when I scale something in workspace all of width, height, scaleX, scaleY` change

I have had some other deep experiences. As I understand Bluescape hides the actual width and height of elements and assumes that x and y are 0. Then applies transformations to elements and return bounding box of transformered elements.

I need to reverse transformations to get the original width and height. Am I right?

Let me explain my use case, I need to subscribe to elements updates and detect overlap of updated element and some other elements existing in the workspace

To to this, boundingBox is a nice way to calculate overlap percentage. But unfortunately it seems I cannot track bounding box changes and I have to convert bounding box to the original width and height of elements by reversing transformations and reapply new transformations comes from subscriptions to recalculate boundingBox

If I am right, Is it possible to make this complex problem simpler by providing boundingBox in the subscriptions?

If I’m wrong let me know how transformation works?

Hi @Amerehei,

I know the difference between boundingBox and transform can be a little confusing, but I will explain.

You can also check out the article for changing the display size of of elements.

Simple definitions:

  • transform: used to SET the width/height, x/y, scale and rotation of an element in mutations, but are also returned from query
  • boundingBox: used to QUERY width/height and location x/y of an element on screen, you can only change the element’s boundingBox by using transform to change width/height, scale, or rotation

If scale is 1 and there is no rotation of an element, the boundingBox and transform should always be the same. If scale is used, or if you change to origin point, transform x/y will not be the same as boundingBox x/y. If you have seen any times the boundingBox and transform x/y are not the same without rotation or changing origin, please let me know.

Why is boundingBox x/y not always equal to transform x/y or element width/height?

  1. rotation has been applied to an element.
  • when rotation is applied to an element, it is rotated on the rotation origin, and the transform x/y is the location of the origin (by default anchor is top-left)
  • boundingBox x/y is the top-left most area of the rotated shape, and width/height is the number of pixels used to display the rotated shape

For example

The query of this this rotated shape element with transfer.origin top-left and x/y = 0 and bounding box is the area around the rotated shape (the orange box in the diagram):

{
    "data": {
        "elements": [
            {
                "__typename": "Shape",
                "id": "651d624ad588d86e98d1ec73",
                "transform": {
                    "x": 0,
                    "y": 0,
                    "rotateZ": -45,
                    "scaleX": 1,
                    "scaleY": 1,
                    "origin": {
                        "anchor": "TopLeft",
                        "point": null
                    }
                },
                "boundingBox": {
                    "x": -106.06601717798213,
                    "y": -1.7798214457798167e-7,
                    "width": 212.13203435596427,
                    "height": 212.13203435596427
                },
                "shapeText": "rotation",
                "style": {
                    "width": 150,
                    "height": 150
                }
            }
        ]
    }
}
  1. When an image has been scaled, the boundingBox width/height will not match the image.width/height. The image.height and image.width are the actual dimensions of the shape, and do not change. If scale=1, the image width/height will match the boundingBox width/height. If scale is applied, then boundingBox width/height is calculated by multiplying image width/heigh times scale.

For example

  • image without scale applied - note image width/heigh and boundingBox width/height are both 1024:
{
    "data": {
        "elements": [
            {
                "__typename": "Image",
                "id": "651d40fec91b8fe35b0e168d",
                "transform": {
                    "x": -1882.9389970541738,
                    "y": 576.1680572349469,
                    "rotateZ": 0,
                    "scaleX": 1,
                    "scaleY": 1,
                    "origin": {
                        "anchor": "TopLeft",
                        "point": null
                    }
                },
                "boundingBox": {
                    "x": -1882.9389970541738,
                    "y": 576.1680572349469,
                    "width": 1024,
                    "height": 1024
                },
                "width": 1024,
                "height": 1024
            }
        ]
    }
}
  • image with scale applied - not the difference between image width/height and boundingBox width/height with boundingBox width/height = scaleX * image width/height:
{
    "data": {
        "elements": [
            {
                "__typename": "Image",
                "id": "651d40eec91b8fe35b0e168b",
                "transform": {
                    "x": -1321,
                    "y": -77.30120652174469,
                    "rotateZ": 0,
                    "scaleX": 0.48828125,
                    "scaleY": 0.48828125,
                    "origin": {
                        "anchor": "TopLeft",
                        "point": null
                    }
                },
                "boundingBox": {
                    "x": -1321,
                    "y": -77.30120652174469,
                    "width": 500,
                    "height": 500
                },
                "width": 1024,
                "height": 1024
            }
        ]
    }
}
2 Likes

Oh! I was unaware of style.width and style.height. Thanks for letting me know
Now it’s clear to me how transform works and how can I utilize it

2 Likes

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.