> 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-zh/chang-jing-sdk7/2d-ui/ui_background.md).

# UI 背景

设置 UI 实体的背景和边框。

以下属性用于为 UI 实体设置背景和边框。

## 背景

一个 `uiBackground` 组件为实体的区域提供颜色或纹理。它使用实体的 `uiTransform`.

以下字段可以配置，全部都是可选的：

* `color`：要在实体上使用的颜色，作为一个 [Color4](/creator/content-creator-zh/chang-jing-sdk7/3d-nei-rong-ji-chu/color-types.md) 值。

{% hint style="info" %}
**💡 提示**：通过将 `Color4` 的第 4 个值设置为小于 1，使实体半透明。
{% endhint %}

* `纹理`：要显示在实体上的纹理，这里传入一个包含纹理各种参数的对象。可用属性与 3D 实体上的 [材质中的纹理](/creator/content-creator-zh/chang-jing-sdk7/3d-nei-rong-ji-chu/materials.md#using-textures).

  * `src`：要用作纹理的图像文件路径。（字符串）

  * `filterMode`: *（可选）* 决定纹理中的像素在渲染时如何被拉伸或压缩。参见 [纹理缩放](/creator/content-creator-zh/chang-jing-sdk7/3d-nei-rong-ji-chu/materials.md#texture-scaling)。（FilterMode = 'point' | 'bi-linear' | 'tri-linear'）

  * `wrapMode`: *（可选）* 决定纹理如何平铺到实体上。这里使用来自 `TextureWrapMode` 枚举的值。参见 \[纹理包裹]\(([查看文档](https://github.com/decentraland/docs/tree/main/creator/sdk7/README.md)）。(WrapMode = 'repeat' | 'clamp' | 'mirror')

  > 提示：你可以将这两个 `纹理` 和 `color` 属性组合在同一个 `uiBackground` 组件上，以生成带色调的纹理。
* `textureMode`：选择你希望纹理如何适应其所应用实体的尺寸。（TextureMode = 'nine-slices' | 'center' | 'stretch'）枚举，支持以下值：
  * `center`：纹理不会被拉伸，它会居中放置在实体上，并且其部分内容可能会根据实体大小被裁剪。
  * `拉伸`：纹理会被拉伸以匹配实体的整个表面。
  * `九宫格切片`：纹理的某些部分会被拉伸以匹配实体的整个表面，而边距保持不变。参见 [九宫格纹理](#nine-slice-textures).
* `avatarTexture`：基于头像 ID 显示头像个人资料缩略图。参见 \[头像肖像]\(([查看文档](https://github.com/decentraland/docs/tree/main/creator/sdk7/README.md)).
* `textureSlices`：在使用九宫格纹理模式时，确定要使用的边距，参见 [九宫格纹理](#nine-slice-textures)。设置一个小于 1 的数值，作为图像总宽度或总高度的分数。

简单颜色：

***ui.tsx 文件：***

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

export const uiMenu = () => (
  <UiEntity
    uiTransform={{
      width: 700,
      height: 400
    }}
    uiBackground={{
		color: Color4.create(0.5, 0.8, 0.1, 0.6)
	}}
  />
)
```

***index.ts 文件：***

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

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

{% hint style="warning" %}
**📔 注意**：本页下面的所有代码片段都假设你有一个 `.ts` 类似于上面的内容，正在运行 `ReactEcsRenderer.setUiRenderer()` 函数。
{% endhint %}

重复纹理图案：

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

export const uiMenu = () => (
  <UiEntity
    uiTransform={{
      width: 700,
      height: 400
    }}
    uiBackground={{
		textureMode: 'center',
		texture: {
			src: "images/brick-wall-texture.png",
			wrapMode: 'repeat'
		}
	}}
  />
)
```

## 边框

有一些属性用于为 UI 实体设置边框。这些属性存在于 `uiTransform` 组件上。它们都允许你为边框的所有边设置单个值，或者为每一边设置不同的值。

* `borderColor`：要在实体上使用的颜色，作为一个 [Color4](/creator/content-creator-zh/chang-jing-sdk7/3d-nei-rong-ji-chu/color-types.md) 值。
* `borderWidth`：边框的宽度，单位为像素。它也支持百分比值，例如 `borderWidth: '2%'` 会将边框宽度设置为实体宽度的 2%。
* `borderRadius`：使用此属性可以让实体的角变成圆角边框。它以像素设置角的半径。

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

export const uiMenu = () => (
  <UiEntity
    uiTransform={{
      width: 700,
      height: 400,
      borderColor: Color4.Red(),
      borderWidth: 4,
      borderRadius: 10
    }}
  />
)
```

`borderWidth`, `borderColor` 和 `borderRadius` 也可以为实体的每一边设置不同的值。

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

export const uiMenu = () => (
  <UiEntity
    uiTransform={{
      width: 700,
      height: 400,
      borderColor: { top: Color4.White(), left: Color4.Red(), right: Color4.Blue(), bottom: Color4.Gray() },
      borderRadius: { topLeft: 20, topRight: 20, bottomLeft: 20, bottomRight:0 },
      borderWidth: { top: 3, left: 2, right: 3, bottom: 4 }
    }}
  />
)
```

## 不透明度

使用 `opacity` 属性在 `uiTransform` 中的 `UiEntity` 用于为实体及其所有子元素添加透明度。opacity 属性的值范围为 0 到 1，其中 0 表示完全透明，1 表示完全不透明。

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

export const uiMenu = () => (
  <UiEntity
    uiTransform={{
      width: 700,
      height: 400,
      opacity: 0.7
    }}
    uiBackground={{ color: Color4.Green() }}
  >
    <UiEntity
        uiTransform={{
          width: 100,
          height: 30,
        }}
        uiText={{
          value: "这段文字也同样是透明的",
          fontSize: 40
        }}
      />
   </UiEntity>
)
```

不透明度值会影响 UiEntity 的所有子元素，对背景颜色、文本颜色和背景图像都应用透明度。当父级和子级都设置了不透明度值时，子级最终的不透明度是其自身值与父级值的乘积。

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

export const uiMenu = () => (
  <UiEntity
    uiTransform={{
      width: 700,
      height: 400,
      opacity: 0.7
    }}
    uiBackground={{ color: Color4.Green() }}
  >
    <UiEntity
      uiTransform={{
        width: 100,
        height: 30,
        opacity: 0.7
      }}
      uiText={{
        value: "这段文字的透明度更高",
        fontSize: 40
      }}
    />
  </UiEntity>
)
```

## 九宫格纹理

你可以使用 [九切片缩放](https://en.wikipedia.org/wiki/9-slice_scaling) 配合你的纹理使用，以确保角落和边距不会被不均匀地拉伸。

使用这种流行的技术，你将一张图片切成 9 个部分，并以不同方式拉伸，以保持边距和角落的比例。例如，可用它来定义适配任意尺寸的圆角背景。请看下面这张图片（借自 [维基百科](https://en.wikipedia.org/wiki/9-slice_scaling#/media/File:Traditional_scaling_vs_9-slice_scaling.svg)):

![](https://2460066822-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-e2ac050bd4fa39a8b191cd36e282279f43613058%2F9-slice.png?alt=media\&token=097c41d5-86f7-4f0d-ba53-bac14132c9e7)

在这张图片中，我们看到原始纹理（左上），以及以传统方式缩放后的结果（右上）；注意角落是如何变形的。其下方，我们看到被分割为 9 个切片的纹理（左下），然后是按照九宫格方法拉伸后的结果（右下）。

以下是每个切片的受影响方式，以上图为参考。

* 第 5 个切片是图片中唯一在 x 和 y 轴上都完全被拉伸的部分。
* 第 1、3、7 和 9 个切片（角落）完全不会被拉伸。
* 第 2 和 8 个切片只会在水平方向上拉伸
* 第 4 和 6 个切片只会在垂直方向上拉伸。

要在实体上使用九宫格拉伸，请将 `textureMode` 为 `'nine-slices'`。你还可以可选地在 `textureSlices`.

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

export const uiMenu = () => (
  <UiEntity
    uiTransform={{ width: 700, height: 400 }}
    uiBackground={{
      textureMode: 'nine-slices',
      texture: {
        src: 'images/rounded_alpha_square.png'
      },
      textureSlices: {
        top: 0.2,
        bottom: 0.2,
        left: 0.2,
        right: 0.2
      }
	}}
  />
)
```

## 纹理 UV

使用 `uvs` 属性在一个 `uiBackground` 组件上，用于显示纹理的特定区域。这对于从精灵表中选取单个精灵，或用于旋转图像非常有用。

该 `uvs` 字段接受一个包含 8 个数字的数组，表示纹理区域四个角的 4 对 UV 坐标。顺序如下： **左下**, **左上**, **右上**, **右下**。每个值的范围为 0 到 1，其中 `(0, 0)` 是图像的左下角，而 `(1, 1)` 是右上角。

{% hint style="info" %}
**💡 提示**：当使用自定义 `uvs`，请将 `textureMode` 为 `'stretch'` 时，以便所选区域填满实体的区域。
{% endhint %}

### 来自精灵表的精灵

要显示较大图像的一部分（例如，来自包含多个卡牌的精灵表中的一张卡牌），请将 `uvs` 设置为该区域的坐标。

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

// 显示纹理的左半部分（例如，2 列精灵表中的第一张卡）
export const uiMenu = () => (
  <UiEntity
    uiTransform={{ width: 200, height: 300 }}
    uiBackground={{
      textureMode: 'stretch',
      texture: { src: 'images/card-atlas.png' },
      uvs: [
        // 左下、左上、右上、右下
        0, 0,
        0, 1,
        0.5, 1,
        0.5, 0
      ]
    }}
  />
)
```

对于带有帧网格的精灵表（例如，4 列 2 行的表），请根据你想要的帧所在的列和行来计算 UV：

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

// 从网格精灵表中选取一个单独的帧
function getFrameUVs(col: number, row: number, totalCols: number, totalRows: number): number[] {
  const stepU = 1 / totalCols
  const stepV = 1 / totalRows
  const left = col * stepU
  const right = (col + 1) * stepU
  const top = 1 - row * stepV
  const bottom = 1 - (row + 1) * stepV
  return [
    left, bottom,
    left, top,
    right, top,
    right, bottom
  ]
}

// 显示 4x2 精灵表中的第 2 列、第 0 行
export const uiMenu = () => (
  <UiEntity
    uiTransform={{ width: 128, height: 128 }}
    uiBackground={{
      textureMode: 'stretch',
      texture: { src: 'images/spritesheet.png' },
      uvs: getFrameUVs(2, 0, 4, 2)
    }}
  />
)
```

### 使用 UV 旋转图像

你可以通过对 UV 坐标应用二维旋转来旋转纹理。这对于旋转指示器或加载动画很有用，而无需基于变换的旋转。

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

// 围绕中心旋转一个二维点
function rotate2D(angle: number, x: number, y: number, cx: number, cy: number): number[] {
  const cos = Math.cos(angle)
  const sin = Math.sin(angle)
  return [
    cos * (x - cx) - sin * (y - cy) + cx,
    sin * (x - cx) + cos * (y - cy) + cy
  ]
}

// 构建旋转后的 UV 坐标
function rotateUVs(angle: number): number[] {
  const uv00 = rotate2D(angle, 0, 0, 0.5, 0.5)
  const uv01 = rotate2D(angle, 0, 1, 0.5, 0.5)
  const uv11 = rotate2D(angle, 1, 1, 0.5, 0.5)
  const uv10 = rotate2D(angle, 1, 0, 0.5, 0.5)
  return [uv00[0], uv00[1], uv01[0], uv01[1], uv11[0], uv11[1], uv10[0], uv10[1]]
}

let spinnerAngle = 0

// 每帧更新角度的系统
engine.addSystem((dt: number) => {
  spinnerAngle += dt * 5
})

export const uiMenu = () => (
  <UiEntity
    uiTransform={{ width: 128, height: 128 }}
    uiBackground={{
      textureMode: 'stretch',
      texture: { src: 'images/spinner.png' },
      uvs: rotateUVs(spinnerAngle)
    }}
  />
)
```

该 `rotateUVs` 函数会围绕中心点按给定的弧度角旋转四个 UV 角点 `(0.5, 0.5)` 。由于这会被类似 React 的渲染器在每一帧调用，因此旋转指示器会平滑更新。

{% hint style="info" %}
**💡 提示**：在 [UI 动画](https://github.com/decentraland/sdk7-goerli-plaza/tree/main/ui-animations) 示例场景中查看包含精灵、动画精灵表、旋转指示器等内容的完整可运行示例。
{% endhint %}


---

# 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 by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.decentraland.org/creator/content-creator-zh/chang-jing-sdk7/2d-ui/ui_background.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

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.
