Align
This aligns / pins a plane to a fixed screen position. This is useful for making responsive user interface elements which adjust to the window size and device pixel ratio.
UI.Align(group, plane, marginPx, x, y, distance);
If the plane is the root of your UI, you can pass it in like:
UI.Align(plane, plane, marginPx, x, y, distance);
It's recommended to disable this when in XR, as it locks to the camera's position.
Aligned UI keeps the same apparent screen size when the camera FOV or zoom
changes. A 50-degree FOV is used as the reference: the group's authored scale is
unchanged at 50 degrees and compensated at other FOVs. Compensation does not
accumulate when UI.Align is called every frame, and caller-authored scale
changes remain supported.
What controls the displayed size?
UI.Align deals with three different kinds of sizing, and they are easy to mix up:
- A
UI.Panel'spixelWidth,pixelHeight, anddprcontrol CSS layout and texture resolution. marginPxcontrols the panel's inset from the chosen screen edge in viewport pixels.group.scalecontrols how large the aligned panel actually appears. Thedistancefrom the camera also affects its apparent size.
In particular, panel texture pixels are not screen pixels. Reducing a panel from
720 × 480 to 360 × 240 does not make it half as large on screen when its aspect
ratio and object scale stay the same. It mainly gives the UI half as many pixels to
render with, which makes text and edges blurrier.
Keep the panel resolution high and change its scale when you want a smaller HUD:
const hud = new UI.Panel(720, 480, 2);
hud.scale.set(0.1, 0.1, 0.1);
await hud.init();
this.update = () => {
UI.Align(hud, hud.hitbox, 20, "center", "bottom", 0.25);
};
UI.Align treats the scale you set as the authored base size, then compensates it
when the camera FOV changes. If you change the scale later, the new value becomes
the base size on the next alignment call.
Example
this.update = () => {
// Each frame the element is aligned with the camera / viewport view
UI.Align(this, this.plane, 10, "left", "center", 0.2);
};
Signature
UI.Align(
group: U.Object3D,
plane: U.Mesh,
marginPx: number = 10,
x: 'left' | 'center' | 'right',
y: 'top' | 'center' | 'bottom',
distance: number = 0.25 // distance from the camera on the Z axis
): void