> 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/escenas-sdk7/ui-2d/onscreen-ui.md).

# UI en pantalla

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

Los elementos de la UI solo son visibles cuando el jugador está dentro de los parcels de LAND de la scene, ya que las scenes vecinas podrían tener su propia UI para mostrar. Partes de la UI también pueden activarse para abrirse cuando ocurren ciertos events en el espacio del mundo, por ejemplo si el jugador hace click 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 files que tengan una `.tsx` extensión. `.tsx` files admiten todo lo que `.ts` files admiten, además de la sintaxis de UI. Recomendamos crear un `ui.tsx` file y definir tu UI allí. Recuerda llamar a tu método de render de UI desde `index.ts` con `ReactEcsRenderer.setUiRenderer(yourUiMethodName)`, mira el ejemplo a continuación.
{% 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 state, puedes hacer cosas que son 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 scene. Así que si tu scene tiene elementos de UI que ocupan el mismo espacio en pantalla que estos, quedarán ocultos.

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

{% hint style="info" %}
**📱 Diseñando para móviles**: La [client móvil](/creator/content-creator-es/escenas-sdk7/desarrollar-para-movil/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 scene en esas regiones entrará en conflicto con los controles. Antes de publicar, revisa la [Área segura móvil](/creator/content-creator-es/escenas-sdk7/desarrollar-para-movil/safe-area.md) y la [Buenas prácticas de UI para móviles](/creator/content-creator-es/escenas-sdk7/desarrollar-para-movil/ui-best-practices.md). Un punto de partida útil es diseñar tu UI en desktop y luego **escalar los tamaños por 3×** para mejorar la legibilidad en móvil.
{% endhint %}

{% hint style="info" %}
**📱 Evita los márgenes reservados por el hardware**: En móviles, los dispositivos reservan espacio de pantalla para el notch, la barra de estado, el indicador de inicio y las esquinas redondeadas. Envuelve tu UI en [`ScreenInsetArea` componente](/creator/content-creator-es/escenas-sdk7/desarrollar-para-movil/safe-area.md#device-hardware-insets-screeninsetarea) para mantenerla automáticamente fuera de estas áreas. Solo afecta al client móvil — en desktop no tiene efecto, así que es seguro dejarlo en una UI multiplataforma.
{% endhint %}

Cuando el jugador hace click en el *cerrar UI* button, en la esquina inferior derecha de la pantalla, se ocultan todos los elementos de la UI.

## Renderizar una UI

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

Cada entity se define como un nodo similar a HTML, con properties 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 los elementos de tu UI necesitan estar anidados en la misma estructura y tener un único padre en la raíz de la estructura. Solo puedes llamar `ReactEcsRenderer.setUiRenderer()` una vez en la scene.
{% endhint %}

## Entities de UI

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

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

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

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

* `uiTransform`
* `uiBackground`
* `uiText`
* `onMouseDown`
* `onMouseUp`
* `onMouseEnter`
* `onMouseLeave`

Como 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 }}
    />
    {/* declaració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 padre en la parte superior.

## Escala virtual de la pantalla

Establece un ancho y alto virtuales para la UI. Se recomienda para asegurarte de que tu UI se vea igual en distintos 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 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 3840x2160, un elemento que esté definido con un ancho de 100 píxeles se mostrará sobre 200 píxeles reales.

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

## Múltiples módulos de UI

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

El `ReactEcsRenderer.addUiRenderer()` function requiere que proporciones una entity como propietaria de la UI. Puede ser cualquier entity, incluso una entity dummy creada solo para ser usada como propietaria de la UI.

```ts
export function setupUi() {

    // Crear una entity dummy para que sea 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 dummy como propietaria
    ReactEcsRenderer.addUiRenderer(dummyEntity, uiComponent)
}
```

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

Un `addUiRenderer()` llamada también puede incluir un ancho y alto virtuales, igual que `setUiRenderer()`. Sin embargo, si la scene 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 declaración de setUiRenderer

En lugar de llamar `ReactEcsRenderer.addUiRenderer()` para cada módulo de UI, puedes llamar `ReactEcsRenderer.setUiRenderer()` una vez con un array de módulos de UI, que pueden vivir en distintos files.

```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 hay 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/escenas-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.
