---
title: "Understanding 2D labels"
canonical: "https://help.twinfinity.com/space/HCFD/151126023/Understanding%202D%20labels"
format: markdown
---
When building a Twinfinity App, interactive elements like labels can greatly improve the user experience and how data is represented. This article walks through a playground example that shows how to dynamically place and update 2D labels in your model.

A 2D label is rendered on top of the Twinfinity canvas, almost as if the camera were showing the scene through a glass pane. 2D labels are ideal for displaying model data on top of the model itself, giving users an easy, at-a-glance way to consume that data.

## Code overview

The example below loads property sets, picks out specific space types, and pins a label over each one. Try it live: [Tracked HTML labels](https://playground.twinfinity.dev/?pgId=labels-and-icons/tracked-labels).

## Key functionalities

1. **Initializing the environment** — the script sets up a 3D scene, enabling a grid and disabling the skybox for clarity. It also prevents scrolling outside the canvas area for a streamlined experience.
2. **Loading and filtering data** — it loads property sets and filters out specific space types (LOA and ROOM) based on the Swedish BIP standard.
3. **Creating a coordinate tracker** — a central feature is the `CoordinateTracker`, which updates label positions in real time. This is the key piece for keeping labels glued to the model as the camera moves.
4. **Adapting to screen scaling** — the code accounts for hardware scaling, so labels stay correctly positioned on screens with different resolutions, such as 4K displays.
5. **Interactive labeling** — it dynamically creates and positions a label for each space, using the centre of geometry for placement.

## Tracking a 3D point with an HTML label

A coordinate tracker projects a world coordinate to screen space and calls your update function whenever the camera moves. You create the tracker, register an update callback, then `track` a 3D point together with the HTML element that should follow it.

```ts
// Create a coordinate tracker used to update label positions on top of the 3D view.
const coordinateTracker = api.createCoordinateTracker();

// Register a function called each time the camera moves.
coordinateTracker.onUpdate(coordinateTrackerUpdater);

// Track the 3D centre of the space with an HTML label element.
const label = createLabel(property.value, randomLoaColor);
coordinateTracker.track(loa.boundingInfo().boundingSphere.center, label);

// Runs for every tracked coordinate whenever the camera moves.
function coordinateTrackerUpdater(coord: TrackCoordinate2D<Vertex3>): void {
  const div = coord.id as HTMLDivElement;
  // Position the HTML element over the projected 3D coordinate.
  div.style.left = coord.position.x - div.offsetWidth / 2 + 'px';
  div.style.top = coord.position.y - div.offsetHeight + 'px';
  // Hide the label when its point is out of view.
  div.style.display = coord.visible ? 'block' : 'none';
}
```

## Practical applications

Dynamically placing and updating labels as the user interacts and the camera moves makes this a powerful tool for interactive 3D visualizations. Showing model data in a spatial context lets users quickly get an overview of selected data points right where they live in the 3D model.

## See also

2D labels live on a flat plane in front of the scene, like writing on glass. If instead you want markers that sit *in* the 3D world and scale with depth, see [Understanding 3D icons](https://twinfinity.atlassian.net/wiki/spaces/HCFD/pages/147062785).