> 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`.

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

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

{% hint style="info" %}
**💡 提示**：通过将以下内容的第 4 个值设置为 `Color4` 小于 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')

  > 提示：你可以将这两者结合使用 `纹理` 和 `颜色` 属性用于单个 `uiBackground` 组件，以生成带色调的纹理。
* `textureMode`：选择纹理如何适应其应用所在实体的尺寸。（TextureMode = 'nine-slices' | 'center' | 'stretch'）枚举，支持以下值：
  * `中心`：纹理不会拉伸，它会居中放置在实体上，并且根据实体尺寸，其部分内容可能会被裁剪。
  * `拉伸`：纹理会被拉伸以匹配实体的整个表面。
  * `九宫格`：纹理的部分区域会被拉伸以匹配实体的整个表面，同时保留边距不拉伸。请参见 [九宫格纹理](#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` 用于为实体及其所有子元素添加透明度。不透明度属性的取值范围为 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>
)
```

## 九宫格纹理

你可以使用 [9 宫格缩放](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)

在这张图中，我们看到原始纹理（左上），以及以传统方式缩放后的结果（右上）；注意角是如何变形的。在下方，我们看到被分割成 9 个切片的纹理（左下），以及按照 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'

// 显示纹理的左半部分（例如，两列图集中的第一张卡牌）
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 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-zh/chang-jing-sdk7/2d-ui/ui_background.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.
