Tutorial: Using getScreenPosition to Overlay UI at a World Position
The getScreenPosition
method (from the ViewController
service in Hology) converts a 3D world position (a Vector3
) into 2D screen coordinates. This is useful for overlaying UI elements (like markers, health bars, or tooltips) on top of objects in your 3D scene.
import { ViewController } from '@hology/core/gameplay';
import { useRenderLateUpdate, useService } from '@hology/react';
import { useRef } from 'react';
import { Vector3 } from 'three';
function WorldPositionMarker() {
const markerRef = useRef<HTMLDivElement>(null);
const view = useService(ViewController);
useRenderLateUpdate(() => {
// Replace (0,0,0) with any world position you want to track
const pos = view.getScreenPosition(new Vector3(0, 0, 0));
if (pos && markerRef.current) {
markerRef.current.style.visibility = 'visible';
markerRef.current.style.left = pos.x + 'px';
markerRef.current.style.top = pos.y + 'px';
} else if (markerRef.current) {
markerRef.current.style.visibility = 'hidden';
}
});
return (
<div
ref={markerRef}
style={{
position: 'absolute',
width: '20px',
height: '20px',
background: 'red',
borderRadius: '50%',
pointerEvents: 'none',
transform: 'translate(-50%, -50%)',
}}
/>
);
}
How it Works
The component uses useService(ViewController) to access the camera and projection logic.
On every frame (
useRenderLateUpdate
), it callsgetScreenPosition
with a 3D world coordinate.If the position is visible, it updates the marker's CSS to move it to the correct screen position.
If the position is off-screen or not visible, it hides the marker.
Customization
To track a different world position, change the argument to getScreenPosition.
You can style the marker as needed (color, size, etc.).
You can render multiple markers for different world positions by reusing this component.
Last updated