> For the complete documentation index, see [llms.txt](https://docs.decentraland.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.decentraland.org/creator/content-creator-es/scenes-sdk7/ui-2d/onscreen-ui.md).

# UI en pantalla

Puedes construir una UI para tu escena, para que se muestre en el espacio 2D fijo de la pantalla, en lugar de en el espacio 3D del mundo.

Los elementos de UI solo son visibles cuando el jugador está dentro de las parcelas LAND de la escena, ya que las escenas vecinas podrían tener su propia UI para mostrar. Partes de la UI también pueden activarse para abrirse cuando ocurren ciertos eventos en el world-space, por ejemplo, si el jugador hace clic en un lugar específico.

Construye una UI definiendo una estructura de `UIEntity` objetos anidados en JSX. La sintaxis usada para las UIs es muy similar a la de [React](https://reactjs.org/) (una biblioteca muy popular basada en JavaScript para construir UIs web).

{% hint style="warning" %}
**📔 Nota**: Solo puedes definir la sintaxis de UI en archivos que tengan una `.tsx` extensión. `.tsx` los archivos admiten todo lo que `.ts` los archivos admiten, además de la sintaxis de UI. Recomendamos crear un `ui.tsx` archivo y definir allí tu UI. Recuerda llamar a tu método de renderizado de UI desde `index.ts` con `ReactEcsRenderer.setUiRenderer(yourUiMethodName)`, consulta el ejemplo de abajo.
{% endhint %}

Una UI simple con elementos estáticos puede parecerse mucho a HTML, pero cuando añades elementos dinámicos que responden a un cambio de estado, puedes hacer cosas mucho más potentes.

La UI predeterminada del Explorer de Decentraland incluye un widget de chat, un mapa y otros elementos. Estos elementos de UI siempre se muestran en la capa superior, por encima de cualquier UI específica de la escena. Así que, si tu escena tiene elementos de UI que ocupan el mismo espacio de pantalla que estos, quedarán ocultos.

Consulta [guías de UX](/creator/content-creator-es/scenes-sdk7/disenando-la-experiencia/ux-ui-guide.md) para obtener consejos sobre cómo diseñar el aspecto y la experiencia de tu UI.

{% hint style="info" %}
**📱 Diseño para móviles**: El [cliente móvil](/creator/content-creator-es/scenes-sdk7/creacion-para-moviles/building-for-mobile.md) reserva el lado izquierdo, la esquina superior derecha y la esquina inferior derecha de la pantalla para los controles del sistema (joystick, chat, perfil, cámara, botón de interacción). La UI de la escena en esas regiones chocará con los controles. Antes de publicar, revisa la [Área segura para móviles](/creator/content-creator-es/scenes-sdk7/creacion-para-moviles/safe-area.md) y las [mejores prácticas de UI para móviles](/creator/content-creator-es/scenes-sdk7/creacion-para-moviles/ui-best-practices.md). Un buen punto de partida es diseñar tu UI en escritorio y luego **escalar los tamaños por 3×** para mejorar la legibilidad en móviles.
{% endhint %}

{% hint style="info" %}
**📱 Evita los márgenes reservados por el hardware**: En mobile, los dispositivos reservan espacio de pantalla para la muesca, la barra de estado, el indicador de inicio y las esquinas redondeadas. Envuelve tu UI en el [`ScreenInsetArea` component](/creator/content-creator-es/scenes-sdk7/creacion-para-moviles/safe-area.md#device-hardware-insets-screeninsetarea) para mantenerla automáticamente alejada de estas áreas. Solo afecta al cliente móvil — en escritorio no tiene efecto, así que es seguro dejarla en UI multiplataforma.
{% endhint %}

Cuando el jugador hace clic en el *botón Cerrar UI* en la esquina inferior derecha de la pantalla, todos los elementos de UI se ocultan.

## Renderizar una UI

Para mostrar una UI en tu escena, usa la `ReactEcsRenderer.setUiRenderer()` función, pasándole una estructura válida de entities, descrita en un `.tsx` archivo.

Cada entity se define como un nodo similar a HTML, con propiedades para cada uno de sus components.

***archivo ui.tsx:***

```ts
import { UiEntity, ReactEcs } from '@dcl/sdk/react-ecs'
import { Color4 } from '@dcl/sdk/math'

export const uiMenu = () => (
  <UiEntity
    uiTransform={{
      width: 700,
      height: 400,
      margin: { top: '35px', left: '500px' },
    }}
    uiBackground={{ color: Color4.Red() }}
  />
)
```

***archivo index.ts:***

```ts
import { ReactEcsRenderer } from '@dcl/sdk/react-ecs'
import { uiMenu } from './ui'

export function main() {
    ReactEcsRenderer.setUiRenderer(uiMenu, { virtualWidth: 1920, virtualHeight: 1080 })
}
```

También puedes definir una estructura de entity y renderizarla, todo en un mismo comando en un `.tsx` archivo.

***archivo ui.tsx:***

```tsx
import ReactEcs, { ReactEcsRenderer, UiEntity } from '@dcl/sdk/react-ecs'
import { Color4 } from '@dcl/sdk/math'

export function setupUI() {
  ReactEcsRenderer.setUiRenderer(() => (
    <UiEntity
      uiTransform={{
        width: 700,
        height: 400,
        margin: { top: '35px', left: '500px' },
      }}
      uiBackground={{ color: Color4.Red() }}
    />
  ), { virtualWidth: 1920, virtualHeight: 1080 })
}
```

***archivo index.ts:***

```ts
import { setupUI } from './ui'

export function main() {
    setupUI()
}
```

{% hint style="warning" %}
**📔 Nota**: Todos tus elementos de UI necesitan estar anidados dentro de la misma estructura y tener un único parent en la raíz de la estructura. Solo puedes llamar `ReactEcsRenderer.setUiRenderer()` una vez en la escena.
{% endhint %}

## UI Entities

Cada elemento de la UI debe definirse como un `UiEntity`, ya sea una imagen, texto, fondo, una caja de alineación invisible, etc. Al igual que en el espacio 3D de la escena, cada `UiEntity` tiene sus propios components para darle posición, color, etc.

La sintaxis similar a React te permite especificar cada component como una propiedad dentro del `UiEntity`, esto hace que el código sea más corto y legible.

Los components usados en un `UiEntity` son diferentes de los usados en entities normales. No puedes aplicar un UI component a una entity normal, ni un component normal a una UI entity.

Los siguientes components están disponibles para usar en un `UiEntity`:

* `uiTransform`
* `uiBackground`
* `uiText`
* `onClick`

Al igual que con las etiquetas HTML, puedes definir components como autocerrados o anidar uno dentro de otro.

***archivo ui.tsx:***

```tsx
import ReactEcs, { ReactEcsRenderer, UiEntity } from '@dcl/sdk/react-ecs'
import { Color4 } from '@dcl/sdk/math'

export const uiMenu = () => (
  // entity padre
  <UiEntity
    uiTransform={{
      width: 200,
      height: 200,
      margin: { top: '250px', left: '500px' },
    }}
    uiBackground={{ color: Color4.Blue() }}
  >
    // entity hija autocerrada
    <UiEntity
      uiTransform={{
        width: 400,
        height: 400,
        margin: { top: '35px', left: '500px' },
      }}
      uiText={{ value: `¡Hola, mundo!`, fontSize: 40 }}
    />
    // instrucción de cierre para la entity padre
  </UiEntity>
)
```

***archivo index.ts:***

```ts
import { ReactEcsRenderer } from '@dcl/sdk/react-ecs'
import { uiMenu } from './ui'

export function main() {
    ReactEcsRenderer.setUiRenderer(uiMenu, { virtualWidth: 1920, virtualHeight: 1080 })
}
```

Una definición de un módulo de UI solo puede tener una entity de nivel superior. Puedes definir tantas otras entities como quieras, pero todas deben encajar dentro de una estructura con un único parent en la parte superior.

## Escala virtual de pantalla

Establece un ancho y alto virtuales para la UI. Esto se recomienda para asegurarte de que tu UI se vea igual en diferentes tamaños de pantalla, independientemente del tamaño real de la pantalla en píxeles.

```ts
export function setupUi() {
    ReactEcsRenderer.setUiRenderer(uiComponent, { virtualWidth: 1920, virtualHeight: 1080 })
}
```

Si estableces un ancho virtual de 1920 y un alto virtual de 1080, la UI se escalará para ajustarse al tamaño de la pantalla. Si la pantalla es de 1920x1080, la UI se mostrará del mismo tamaño que el tamaño virtual. Si la pantalla es más grande o más pequeña, cualquier valor en píxeles se escalará para ajustarse al tamaño virtual. Por ejemplo, si la pantalla es de 3840x2160, un elemento definido con 100 píxeles de ancho se mostrará ocupando 200 píxeles reales.

El cálculo real del factor de escala de UI que se aplica a los valores en píxeles es [`Math.min(realWidth / virtualWidth, realHeight / virtualHeight)`](https://github.com/decentraland/js-sdk-toolchain/blob/fbf4826ef686982ca1e60d368186e8e10c02a6e6/packages/%40dcl/react-ecs/src/system.ts#L124)

## Múltiples módulos de UI

Si tu escena contiene múltiples systems o módulos que definen su propia UI, puedes renderizar cada módulo de UI con `ReactEcsRenderer.addUiRenderer()`. Esto es especialmente útil cuando trabajas en una escena compleja con múltiples UI components, o cuando defines UIs para un [smart item](https://github.com/decentraland/docs/blob/main/creator/sdk7/smart-items/smart-items.md), que debería poder usarse independientemente de lo que haya en el código del resto de la escena.

La `ReactEcsRenderer.addUiRenderer()` función requiere que proporciones una entity como propietario de la UI. Puede ser cualquier entity, incluso una entity ficticia creada solo para usarse como propietario de la UI.

```ts
export function setupUi() {

    // Crear una entity ficticia para ser la propietaria de la UI
    const dummyEntity = engine.addEntity()

    // Definir el módulo de UI como una función que devuelve un array de módulos de UI
    const uiComponent = () => [
      // Función que devuelve un módulo de UI,
      // Función que devuelve un módulo de UI
      // ...
    ]

    // Renderizar el módulo de UI con la entity ficticia como propietaria
    ReactEcsRenderer.addUiRenderer(dummyEntity, uiComponent)
}
```

Este fragmento puede existir independientemente de cualquier otro código de UI en la escena. El resto de la escena podría incluir un `ReactEcsRenderer.setUiRenderer()`, o ninguno en absoluto, y la UI se renderizará de todos modos.

Una `addUiRenderer()` llamada también puede incluir un ancho y alto virtuales, igual que `setUiRenderer()`. Sin embargo, si la escena tiene una `setUiRenderer()` llamada que también define un ancho y alto virtuales, el ancho y alto virtuales de la `addUiRenderer()` llamada se ignorarán.

```tsx
ReactEcsRenderer.addUiRenderer(dummyEntity, uiComponent, { virtualWidth: 1920, virtualHeight: 1080 })
```

Esa UI puede eliminarse con `ReactEcsRenderer.removeUiRenderer(dummyEntity)` , además, si la entity que posee la UI se destruye, la UI también se eliminará. Si `ReactEcsRenderer.addUiRenderer()` se llama de nuevo para la misma entity pero con un UiRenderer diferente, el anterior se limpia y el nuevo lo reemplaza.

### Compartir una única instrucción setUiRenderer

En lugar de llamar a `ReactEcsRenderer.addUiRenderer()` para cada módulo de UI, puedes llamar a `ReactEcsRenderer.setUiRenderer()` una sola vez con un array de módulos de UI, que pueden estar en archivos diferentes.

```ts
const uiComponent = () => [
  // Función que devuelve un módulo de UI,
  // Función que devuelve un módulo de UI
  // ...
]

ReactEcsRenderer.setUiRenderer(uiComponent, { virtualWidth: 1920, virtualHeight: 1080 })
```

A continuación se muestra un ejemplo más completo:

***archivo ui.tsx:***

```ts
export function UIModule1() {
  return (
    <UiEntity
      uiTransform={{
        flexDirection: 'column',
        alignItems: 'center',
        justifyContent: 'space-between',
        positionType: 'absolute',
        position: { right: '3%', bottom: '3%' },
      }}
    >
      <Label value="¡Hola, mundo!" fontSize={18} textAlign="middle-center" />
    </UiEntity>
  )
}

export function UIModule2() {
  return (
    <UiEntity
      uiTransform={{
        flexDirection: 'column',
        alignItems: 'center',
        justifyContent: 'space-between',
        positionType: 'absolute',
        position: { right: '3%', top: '3%' },
      }}
    >
      <Label
        value="¡Aquí hay más UI!"
        fontSize={18}
        textAlign="middle-center"
      />
    </UiEntity>
  )
}
```

***archivo index.ts:***

```ts
import { ReactEcsRenderer } from '@dcl/sdk/react-ecs'
import { UIModule1, UIModule2 } from './ui'

export function main() {
    ReactEcsRenderer.setUiRenderer([
      UIModule1(),
      UIModule2(),
      // ...
      // La línea de abajo es para usar la biblioteca DCL UI Toolkit
      // https://github.com/decentraland-scenes/dcl-ui-toolkit
      ui.render(),
    ], { virtualWidth: 1920, virtualHeight: 1080 })
}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.decentraland.org/creator/content-creator-es/scenes-sdk7/ui-2d/onscreen-ui.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
