View Transformations

View transformation enables a wide range of visual effects by manipulating views through translation, rotation, scaling, and skewing. These transformations are essential for creating dynamic, interactive designs, enhancing user experience with engaging visual content.

Below are the frequently used properties that participate in view transformation.

Property Type Description
"transform" TransformProperty Auxiliary property which maintain view translation, rotation, scale, and skew
"transform-origin-x" SizeUnit The X-coordinate of the point around which a view transformation is applied
"transform-origin-y" SizeUnit The Y-coordinate of the point around which a view transformation is applied
"transform-origin-z" SizeUnit The Z-coordinate of the point around which a view transformation is applied
"perspective" SizeUnit Distance between the z-plane and the user in order to give a 3D-positioned view some perspective
"perspective-origin-x" SizeUnit The vanishing point of the "perspective" property
"perspective-origin-y" SizeUnit The vanishing point of the "perspective" property
"backface-visibility" bool Controls whether the back face of a view is visible when turned towards the user

Besides these properties, there are others, but for simplicity, we'll cover them later on this page since they are just a shorthand to the "transform" property.

The "transform" property is a generic one and holds the value of the TransformProperty interface. An instance of that interface can be created using the global rui.NewTransformProperty() function:

Go

func NewTransformProperty(params rui.Params) rui.TransformProperty

where rui.Params is a map which can contain the following properties:

Property Type Description
"perspective" SizeUnit Distance between the z-plane and the user in order to give a view some perspective transformation
"rotate" AngleUnit The angle of the view rotation around specified axis by "rotate-x", "rotate-y", and "rotate-z" properties
"rotate-x" float The X-coordinate of the vector denoting the axis of rotation in range 0 to 1
"rotate-y" float The Y-coordinate of the vector denoting the axis of rotation in range 0 to 1
"rotate-z" float The Z-coordinate of the vector denoting the axis of rotation in range 0 to 1
"scale-x" float The X-axis scaling factor
"scale-y" float The Y-axis scaling factor
"scale-z" float The Z-axis scaling factor
"skew-x" AngleUnit The angle to use to distort the view along the X-axis
"skew-y" AngleUnit The angle to use to distort the view along the Y-axis
"translate-x" SizeUnit Translation of the view along X-axis
"translate-y" SizeUnit Translation of the view along Y-axis
"translate-z" SizeUnit Translation of the view along Z-axis

As most of other properties of the view, "transform" can be set during the view creation process.

Go

view := rui.NewGridLayout(session, rui.Params{
    rui.Width:  rui.Percent(100),
    rui.Height: rui.Percent(100),
    // Center content on the screen
    rui.CellHorizontalAlign: rui.CenterAlign,
    rui.CellVerticalAlign:   rui.CenterAlign,
    rui.Content: rui.NewTextView(session, rui.Params{
        rui.Text: "Transformed text",
        rui.Transform: rui.NewTransformProperty(rui.Params{
            rui.TranslateX: rui.Px(10),  // Move view by 10 pixels in positive X-axis direction
            rui.Rotate:     rui.Deg(45), // Rotate the view by 45 degrees
            rui.ScaleX:     0.9,         // Scale down the view by 10%
            rui.ScaleY:     0.9,         // Scale down the view by 10%
        }),
    }),
})

Or we can change the property at any time using the Set() method of the view or its global function variant.

Go

view.Set(rui.Transform, rui.NewTransformProperty(rui.Params{
    rui.TranslateX: rui.Px(50),  // Move view by 50 pixels in positive X-axis direction
    rui.Rotate:     rui.Deg(45), // Rotate the view by 45 degrees
    rui.ScaleX:     0.9,         // Scale down the view by 10%
    rui.ScaleY:     0.9,         // Scale down the view by 10%
}))

When describing that property in resource description file a specific object format is used:

RUI

_{
    perspective = <size-value>,
    rotate-x = <float-value>,
    rotate-y = <float-value>,
    rotate-z = <float-value>,
    rotate = <angle-value>,
    translate-x = <size-value>,
    translate-y = <size-value>,
    translate-z = <size-value>,
    scale-x = <float-value>,
    scale-y = <float-value>,
    scale-z = <float-value>,
    skew-x = <angle-value>,
    skew-y = <angle-value>,
}

Where <float-value> is a text representation of the float value, <angle-value> is a text representation of the AngleUnit value, and <size-value> is a text representation of the SizeUnit value.

Transforming the view using the "transform" property from resource description file:

RUI

GridLayout {
    width = 100%,
    height = 100%,
    // Center content on the screen
    cell-horizontal-align = center,
    cell-vertical-align = center,
    content = TextView {
        text = "Transformed text",
        transform = _{
            translate-x = 50px, // Move view by 50 pixels in positive X-axis direction
            rotate = 45deg,     // Rotate the view by 45 degrees
            scale-x = 0.9,      // Scale down the view by 10%
            scale-y = 0.9,      // Scale down the view by 10%
        }
    }
}

Here’s how the above examples look:

View transform example 1

To read the actual values of the view transform, we can use the global rui.GetTransform() function, which will return a TransformProperty interface.

Go

if transform := rui.GetTransform(rootView, "view-id"); transform != nil {
    if angle, ok := transform.Get(rui.Rotate).(rui.AngleUnit); ok {
        // Do something with the angle value
    }
    // ...
}

The view also supports other transform-related properties, which may be convenient to use in some cases:

Property Type Description
"rotate" AngleUnit The angle of the view rotation around specified axis or Z-axis by default
"rotate-x" float The X-coordinate of the vector denoting the axis of rotation in range 0 to 1
"rotate-y" float The Y-coordinate of the vector denoting the axis of rotation in range 0 to 1
"rotate-z" float The Z-coordinate of the vector denoting the axis of rotation in range 0 to 1
"scale-x" float The X-axis scaling factor
"scale-y" float The Y-axis scaling factor
"scale-z" float The Z-axis scaling factor
"skew-x" AngleUnit The angle to use to distort the view along the X-axis
"skew-y" AngleUnit The angle to use to distort the view along the Y-axis
"translate-x" SizeUnit Translation of the view along X-axis
"translate-y" SizeUnit Translation of the view along Y-axis
"translate-z" SizeUnit Translation of the view along Z-axis

They are exactly the same as what rui.TransformProperty interface accepts. When setting such properties library will first check whether the "transform" property has been set and if not will create it implicitly, then update its corresponding values.

Below are a few examples that use such properties.

RUI

GridLayout {
    width = 100%,
    height = 100%,
    // Center content on the screen
    cell-horizontal-align = center,
    cell-vertical-align = center,
    content = TextView {
        text = "Transformed text",
        translate-x = 50px, // Move view by 50 pixels in positive X-axis direction
        rotate-z = 1.0,     // Specify the vector over which the view will be rotated
        rotate = 45deg,     // Rotate the view by 45 degrees
        scale-x = 0.9,      // Scale down the view by 10%
        scale-y = 0.9,      // Scale down the view by 10%
    }
}

Go

view := rui.NewGridLayout(session, rui.Params{
    rui.Width:  rui.Percent(100),
    rui.Height: rui.Percent(100),
    // Center content on the screen
    rui.CellHorizontalAlign: rui.CenterAlign,
    rui.CellVerticalAlign:   rui.CenterAlign,
    rui.Content: rui.NewTextView(session, rui.Params{
        rui.Text:       "Transformed text",
        rui.TranslateX: rui.Px(10),  // Move view by 10 pixels in positive X-axis direction
        rui.RotateZ:    1.0,         // Specify the vector over which the view will be rotated
        rui.Rotate:     rui.Deg(45), // Rotate the view by 45 degrees
        rui.ScaleX:     0.9,         // Scale down the view by 10%
        rui.ScaleY:     0.9,         // Scale down the view by 10%
    }),
})

There is a set of convenient global functions we can use to get back the values of the listed properties. These functions are different from what we saw for other properties of the view. They return values for several transform-related properties at once:

Go

rotateX, rotateY, rotateZ, rotateAngle := rui.GetRotate(rootView, "view-id")
// Do something with the view rotation

scaleX, scaleY, scaleZ := rui.GetScale(rootView, "view-id")
// Do something with the view scaling

translateX, translateY, translateZ := rui.GetTranslate(rootView, "view-id")
// Do something with the view translation

skewX, skewY := rui.GetSkew(rootView, "view-id")
// Do something with the view slanting

For more information please refer to TransformProperty interface and View reference documentation.

All transformations of the view are applied against the origin point, by default this is the center of the view, but it can be changed using the "transform-origin-x", "transform-origin-y", and "transform-origin-z" properties. These properties are not part of the "transform" property and must be set directly on the view. We can use a different types of units here since properties hold the values of the SizeUnit type.

Below is an example of how to scale the text starting from the left border of the view while hovering the mouse.

Go

// View creation code
view := rui.NewGridLayout(session, rui.Params{
    rui.Width:  rui.Percent(100),
    rui.Height: rui.Percent(100),
    // Center content on the screen
    rui.CellHorizontalAlign: rui.CenterAlign,
    rui.CellVerticalAlign:   rui.CenterAlign,
    rui.Content: rui.NewTextView(session, rui.Params{
        rui.Text:               "Transformed text",
        rui.TransformOriginX:   rui.Px(0), // The border of the view
        rui.MouseOver:          mouseOver, // Mouse over event handler
        rui.MouseOut:           mouseOut,  // Mouse out event handler
    }),
})

// mouseOver event handler function
func mouseOver(view rui.View, _ rui.MouseEvent) {
    view.Set(rui.Transform, rui.NewTransformProperty(rui.Params{
        rui.ScaleX: 1.1,
    }))
}

// mouseOut event handler function
func mouseOut(view rui.View, _ rui.MouseEvent) {
    view.Set(rui.Transform, rui.NewTransformProperty(rui.Params{
        rui.ScaleX: 1,
    }))
}

View transform example 2

TODO: add explanation of 3D transform operations with examples and uncover properties which miss the explanations

Missing properties