Transform
Draws its children like a layer - every child across the whole box, first one furthest back - then scales, rotates and shifts them together as one picture.
ui.transform
Example
Section titled “Example”new UiTransform{ Key = "needle", Rotation = UiValue.From(() => speed.Value * 1.8 - 90), OriginX = 0.5, OriginY = 0.9, Children = [new UiImage { Key = "needleArt", Source = needle }], Fallback = new UiTextRun { Key = "reading", Text = UiText.From(() => $"{speed.Value:0} km/h") },}
A gauge needle pivoting near its bottom edge. Each update is a set-properties patch carrying rotation
alone; the reader redraws locally, with no new image per update.
Rotating an icon
Section titled “Rotating an icon”new UiTransform { Key = "arrow", Rotation = 90, Children = [arrowIcon] }
Rotation is degrees, clockwise, about the pivot. The pivot defaults to the centre.
Moving the pivot
Section titled “Moving the pivot”new UiTransform { Key = "hand", Rotation = 30, OriginX = 0.5, OriginY = 1.0, Children = [hand] } / pivot at (0.5, 1.0): / the hand turns about o the middle of the bottom edgeOriginX and OriginY are fractions of the element’s own width and height. A value outside 0..1
puts the pivot outside the box.
Scaling and nudging
Section titled “Scaling and nudging”new UiTransform { Key = "art", Zoom = 1.2, OffsetX = 0.1, OffsetY = -0.05, Children = [artwork] }Applied in a fixed order: Zoom, then Rotation, both about the pivot, then the offsets in the parent’s
unrotated axes. These are the same keys a button frames its artwork with; on a
button the artwork scales about its own centre within the ranges listed there, here it scales about the
pivot and any finite value is allowed.
Nesting
Section titled “Nesting”new UiTransform { Key = "dial", Rotation = dialAngle, Children = [face, new UiTransform { Key = "needle", Rotation = needleAngle, Children = [needle] }] }Nested transforms compose.
Properties
Section titled “Properties”| Property | Values | Default | Meaning |
|---|---|---|---|
Rotation (rotation) |
double, degrees |
0 |
The clockwise turn about the pivot. |
OriginX (originX) |
double, fraction of own width |
0.5 |
Where the pivot sits across the box; outside 0..1 is outside the box. |
OriginY (originY) |
double, fraction of own height |
0.5 |
Where the pivot sits down the box. |
Zoom (zoom) |
double, multiplier |
1 |
Scales the content about the pivot; a value not greater than 0 means 1. |
OffsetX (offsetX) |
double, fraction of own width |
0 |
Shifts the content across, after zoom and rotation. |
OffsetY (offsetY) |
double, fraction of own height |
0 |
Shifts the content down, after zoom and rotation. |
MainSize (mainSize), Fill (fill), Answer (answer) |
- | - | Shared with every container - see Stack and layer. |
Events
Section titled “Events”None of its own.
Children
Section titled “Children”Any element, any number. Transforms nest and compose.
Layout
Section titled “Layout”The transform is visual only. The node’s own box, its size on the parent’s main axis and its siblings are laid out as if it were absent, and text inside it is fitted to its untransformed box. See Sizing.
Reader behaviour
Section titled “Reader behaviour”- Apply
zoom, thenrotation, both about the pivot, thenoffsetX/offsetYin the parent’s unrotated axes. - Treat a
zoomnot greater than0as1; accept any finite value otherwise. - Lay out and fit text as if the transform were absent.
- Clip nothing; an ancestor that clips, such as a tile or a button, still does.
- Presses hit the drawn shape. A
ui.sliderunder a non-zerorotationhas no defined pointer mapping. - A reader that does not know
ui.transformdraws the node’sfallback, so a gauge should carry one that still shows its reading:
{ "type": "ui.transform", "properties": { "rotation": 42, "originX": 0.5, "originY": 0.9 }, "children": [{ "type": "ui.image", "properties": { "source": { "resourceId": "needle" } } }], "fallback": { "type": "ui.text", "properties": { "text": "42 km/h" } }}See also
Section titled “See also”- Stack and layer
- Button -
zoomand offsets on artwork - Slider
- Sizing