mirror of
				https://github.com/unanmed/HumanBreak.git
				synced 2025-11-04 15:12:58 +08:00 
			
		
		
		
	docs: 组件使用指南 & 部分文档微调
This commit is contained in:
		
							parent
							
								
									d39e2c2159
								
							
						
					
					
						commit
						1169db5dfd
					
				@ -20,7 +20,7 @@ export default defineConfig({
 | 
			
		||||
        outline: [2, 3],
 | 
			
		||||
        nav: [
 | 
			
		||||
            { text: '主页', link: '/' },
 | 
			
		||||
            { text: '指南', link: '/guide/diff' },
 | 
			
		||||
            { text: '指南', link: '/guide/quick-start' },
 | 
			
		||||
            { text: 'API', link: '/api/' },
 | 
			
		||||
            { text: '错误代码', link: '/logger/' }
 | 
			
		||||
        ],
 | 
			
		||||
@ -39,12 +39,17 @@ export default defineConfig({
 | 
			
		||||
                            text: 'UI 系统',
 | 
			
		||||
                            collapsed: false,
 | 
			
		||||
                            items: [
 | 
			
		||||
                                { text: 'UI 编写', link: '/guide/ui' },
 | 
			
		||||
                                { text: 'UI 优化', link: '/guide/ui-perf' },
 | 
			
		||||
                                { text: 'UI 系统', link: '/guide/ui-system' },
 | 
			
		||||
                                { text: 'UI 元素', link: '/guide/ui-elements' },
 | 
			
		||||
                                { text: 'UI 常见问题', link: '/guide/ui-faq' },
 | 
			
		||||
                                { text: '未来规划', link: '/guide/ui-future' }
 | 
			
		||||
                                { text: '快速浏览', link: '/guide/ui/' },
 | 
			
		||||
                                { text: '编写 UI', link: '/guide/ui/ui' },
 | 
			
		||||
                                { text: 'UI 元素', link: '/guide/ui/elements' },
 | 
			
		||||
                                {
 | 
			
		||||
                                    text: '组件使用指南',
 | 
			
		||||
                                    link: '/guide/ui/component'
 | 
			
		||||
                                },
 | 
			
		||||
                                { text: '优化性能', link: '/guide/ui/perf' },
 | 
			
		||||
                                { text: 'UI 系统', link: '/guide/ui/system' },
 | 
			
		||||
                                { text: '常见问题', link: '/guide/ui/faq' },
 | 
			
		||||
                                { text: '未来规划', link: '/guide/ui/future' }
 | 
			
		||||
                            ]
 | 
			
		||||
                        },
 | 
			
		||||
                        {
 | 
			
		||||
 | 
			
		||||
@ -7,7 +7,22 @@
 | 
			
		||||
## 接口定义
 | 
			
		||||
 | 
			
		||||
```typescript
 | 
			
		||||
interface GraphicBaseProps extends BaseProps {
 | 
			
		||||
interface ILineProperty {
 | 
			
		||||
    /** 线宽 */
 | 
			
		||||
    lineWidth: number;
 | 
			
		||||
    /** 线的虚线设置 */
 | 
			
		||||
    lineDash?: number[];
 | 
			
		||||
    /** 虚线偏移量 */
 | 
			
		||||
    lineDashOffset?: number;
 | 
			
		||||
    /** 线的连接样式 */
 | 
			
		||||
    lineJoin: CanvasLineJoin;
 | 
			
		||||
    /** 线的顶端样式 */
 | 
			
		||||
    lineCap: CanvasLineCap;
 | 
			
		||||
    /** 线的斜接限制,当连接为miter类型时可填,默认为10 */
 | 
			
		||||
    miterLimit: number;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
interface GraphicBaseProps extends BaseProps, Partial<ILineProperty> {
 | 
			
		||||
    /** 是否填充(默认 false) */
 | 
			
		||||
    fill?: boolean;
 | 
			
		||||
    /** 是否描边(默认 false) */
 | 
			
		||||
@ -30,14 +45,20 @@ interface GraphicBaseProps extends BaseProps {
 | 
			
		||||
## 核心属性说明
 | 
			
		||||
 | 
			
		||||
| 属性             | 类型                                            | 默认值      | 说明                                                           |
 | 
			
		||||
| --------------- | ----------------------------------------------- | ----------- | -------------------------------------------------------------- |
 | 
			
		||||
| `fill`          | `boolean`                                       | `false`     | 启用填充(需设置 `fillStyle`)                                 |
 | 
			
		||||
| `stroke`        | `boolean`                                       | `false`     | 启用描边(需设置 `strokeStyle` 和 `strokeWidth`)              |
 | 
			
		||||
| `strokeAndFill` | `boolean`                                       | `false`     | 强制先描边后填充(覆盖 `fill` 和 `stroke` 的设置)             |
 | 
			
		||||
| `fillRule`      | `"nonzero"` \| `"evenodd"`                      | `"evenodd"` | 填充路径计算规则(影响复杂图形的镂空效果)                     |
 | 
			
		||||
| `fillStyle`     | `string` \| `CanvasGradient` \| `CanvasPattern` | -           | 填充样式(支持 CSS 颜色、渐变对象等)                          |
 | 
			
		||||
| ---------------- | ----------------------------------------------- | ----------- | -------------------------------------------------------------- |
 | 
			
		||||
| `fill`           | `boolean`                                       | `false`     | 启用填充                                                       |
 | 
			
		||||
| `stroke`         | `boolean`                                       | `false`     | 启用描边                                                       |
 | 
			
		||||
| `strokeAndFill`  | `boolean`                                       | `false`     | 先描边后填充                                                   |
 | 
			
		||||
| `fillRule`       | `'nonzero'` \| `'evenodd'`                      | `'evenodd'` | 填充路径环绕原则                                               |
 | 
			
		||||
| `fillStyle`      | `string` \| `CanvasGradient` \| `CanvasPattern` | -           | 填充样式                                                       |
 | 
			
		||||
| `strokeStyle`    | `string` \| `CanvasGradient` \| `CanvasPattern` | -           | 描边样式                                                       |
 | 
			
		||||
| `actionStroke`   | `boolean`                                       | `false`     | 设为 `true` 时,交互事件仅响应描边区域(需配合 `stroke` 使用) |
 | 
			
		||||
| `lineWidth`      | `number`                                        | `2`         | 设置描边的线宽                                                 |
 | 
			
		||||
| `lineDash`       | `number[]`                                      | `[]`        | 设置虚线样式                                                   |
 | 
			
		||||
| `lineDashOffset` | `number`                                        | `0`         | 虚线样式偏移量                                                 |
 | 
			
		||||
| `lineJoin`       | `string`                                        | `bevel`     | 线的连接方式                                                   |
 | 
			
		||||
| `lineCap`        | `string`                                        | `butt`      | 线的末端样式                                                   |
 | 
			
		||||
| `miterLimit`     | `number`                                        | `10`        | 当使用 `miter` 连接方式时,其最大斜接限制                      |
 | 
			
		||||
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
@ -67,7 +88,7 @@ interface GraphicBaseProps extends BaseProps {
 | 
			
		||||
    loc={[400, 200, 180, 120]}
 | 
			
		||||
    stroke
 | 
			
		||||
    strokeStyle="rgba(0,0,0,0.8)"
 | 
			
		||||
    strokeWidth={4}
 | 
			
		||||
    lineWidth={4}
 | 
			
		||||
    actionStroke // 点击时仅描边区域响应
 | 
			
		||||
/>
 | 
			
		||||
```
 | 
			
		||||
@ -88,7 +109,7 @@ interface GraphicBaseProps extends BaseProps {
 | 
			
		||||
    stroke
 | 
			
		||||
    fillStyle="#ffe66d"
 | 
			
		||||
    strokeStyle="#2d3436"
 | 
			
		||||
    strokeWidth={2}
 | 
			
		||||
    lineWidth={2}
 | 
			
		||||
/>
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
@ -99,7 +120,7 @@ interface GraphicBaseProps extends BaseProps {
 | 
			
		||||
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
### 示例 4:强制先描边后填充
 | 
			
		||||
### 示例 4:先描边后填充
 | 
			
		||||
 | 
			
		||||
```tsx
 | 
			
		||||
<g-rect
 | 
			
		||||
@ -107,7 +128,7 @@ interface GraphicBaseProps extends BaseProps {
 | 
			
		||||
    strokeAndFill
 | 
			
		||||
    fillStyle="#a29bfe"
 | 
			
		||||
    strokeStyle="#6c5ce7"
 | 
			
		||||
    strokeWidth={8}
 | 
			
		||||
    lineWidth={8}
 | 
			
		||||
/>
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
@ -138,7 +159,7 @@ const leave = () => void (hovered.value = false);
 | 
			
		||||
    fillStyle="#ffffff"
 | 
			
		||||
    stroke={hovered.value}
 | 
			
		||||
    strokeStyle="#e84393"
 | 
			
		||||
    strokeWidth={3}
 | 
			
		||||
    lineWidth={3}
 | 
			
		||||
    onEnter={enter}
 | 
			
		||||
    onLeave={leave}
 | 
			
		||||
/>;
 | 
			
		||||
 | 
			
		||||
@ -8,6 +8,8 @@
 | 
			
		||||
 | 
			
		||||
图标比例固定,会自动根据传入的长宽缩放。
 | 
			
		||||
 | 
			
		||||
图标继承所有图形参数,参考[此文档](../motajs-render-vue/GraphicBaseProps.md)
 | 
			
		||||
 | 
			
		||||
## 图标列表
 | 
			
		||||
 | 
			
		||||
- `RollbackIcon`: 回退图标
 | 
			
		||||
@ -20,6 +22,13 @@
 | 
			
		||||
- `PauseIcon`: 暂停播放图标
 | 
			
		||||
- `DoubleArrow`: 双箭头图标(向右)
 | 
			
		||||
- `StepForward`: 单步向前图标
 | 
			
		||||
- `SoundVolume`: 音量图标
 | 
			
		||||
- `Fullscreen`: 全屏图标
 | 
			
		||||
- `ExitFullscreen`: 退出全屏图标
 | 
			
		||||
- `ArrowLeftTailless`: 无尾巴左箭头图标
 | 
			
		||||
- `ArrowRightTailless`: 无尾巴右箭头图标
 | 
			
		||||
- `ArrowUpTailless`: 无尾巴上箭头图标
 | 
			
		||||
- `ArrowDownTailless`: 无尾巴下箭头图标
 | 
			
		||||
 | 
			
		||||
## 使用示例
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -116,3 +116,14 @@ export const MyCom = defineComponent(() => {
 | 
			
		||||
    {page => renderChunk(data.slice(page * 50, (page + 1) * 50))}
 | 
			
		||||
</Page>
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### 2. 缓存建议
 | 
			
		||||
 | 
			
		||||
如果子元素数量较多,建议给 `Scroll` 组件的所有子元素添加 `nocache` 标记:
 | 
			
		||||
 | 
			
		||||
```tsx {2}
 | 
			
		||||
<Scroll>
 | 
			
		||||
    <item nocache />
 | 
			
		||||
    {/* 更多内容 */}
 | 
			
		||||
</Scroll>
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
@ -30,5 +30,5 @@ lang: zh-CN
 | 
			
		||||
 | 
			
		||||
- [系统说明](./system)
 | 
			
		||||
- [UI 编写](./ui)
 | 
			
		||||
-   [UI 系统](./ui-system)
 | 
			
		||||
- [UI 系统](./ui/system)
 | 
			
		||||
- [音频系统](./audio)
 | 
			
		||||
 | 
			
		||||
@ -2,6 +2,10 @@
 | 
			
		||||
 | 
			
		||||
2.B 提供了专门的动画接口,允许你用短短几行就可以做出一个效果不错的动画。本节主要讲述的是 UI 中的动画。
 | 
			
		||||
 | 
			
		||||
:::warning
 | 
			
		||||
`mutate-animate` 库在未来会重构,可能会修改引入方式,但整体逻辑不会怎么变。
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
## 定义动画属性
 | 
			
		||||
 | 
			
		||||
我们以一个自定义 UI 为例,来讲述如何编写一段动画。自定义 UI 参考[此指南](./new-ui.md)和[此教程](../../guide/ui.md)。
 | 
			
		||||
 | 
			
		||||
@ -179,6 +179,98 @@ export const MyCom = defineComponent(props => {
 | 
			
		||||
});
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## 拓展-输入框
 | 
			
		||||
 | 
			
		||||
与选择框、确认框类似,只不过允许玩家输入一段内容,然后返回给程序。使用 `getInput` 来让玩家输入字符串,使用 `getInputNumber` 来让玩家输入数字。
 | 
			
		||||
 | 
			
		||||
输入框包含一个确认键和取消键,玩家点击确认键时会将输入结果返回,而如果点击了取消,那么会返回空字符串或 `NaN`。
 | 
			
		||||
 | 
			
		||||
### 输入字符串
 | 
			
		||||
 | 
			
		||||
使用 `getInput` 接口:
 | 
			
		||||
 | 
			
		||||
```tsx
 | 
			
		||||
import { getInput } from '../components';
 | 
			
		||||
 | 
			
		||||
// UI 模板及如何编写 UI 参考 “新增 UI” 需求指南,这里只给出必要的修改部分,模板部分不再给出
 | 
			
		||||
export const MyCom = defineComponent(props => {
 | 
			
		||||
    const click = async () => {
 | 
			
		||||
        // 调用接口,并等待执行完毕,获取异步返回值
 | 
			
		||||
        const inputData = await getInput(
 | 
			
		||||
            props.controller, // UI 控制器
 | 
			
		||||
            '请输入一句话', // 显示的文字
 | 
			
		||||
            [240, 240, void 0, void 0, 0.5, 0.5], // 输入框位置
 | 
			
		||||
            240, // 输入框宽度
 | 
			
		||||
            // 其他参数配置,参考 API 文档
 | 
			
		||||
            {
 | 
			
		||||
                // 例如设置一个占位符
 | 
			
		||||
                input: {
 | 
			
		||||
                    placeholder: '输入一句话'
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        );
 | 
			
		||||
        if (inputData.length === 0) {
 | 
			
		||||
            // 如果用户没有输入任何内容或点了取消
 | 
			
		||||
        } else {
 | 
			
		||||
            // 如果用户输入了内容
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    return () => (
 | 
			
		||||
        <container>
 | 
			
		||||
            <text
 | 
			
		||||
                text="这是一个按钮"
 | 
			
		||||
                // 监听 click 事件
 | 
			
		||||
                onClick={click}
 | 
			
		||||
            />
 | 
			
		||||
        </container>
 | 
			
		||||
    );
 | 
			
		||||
});
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### 输入数字
 | 
			
		||||
 | 
			
		||||
与 `getInput` 类似,不过要用 `getInputNumber` 接口:
 | 
			
		||||
 | 
			
		||||
```tsx
 | 
			
		||||
import { getInputNumber } from '../components';
 | 
			
		||||
 | 
			
		||||
// UI 模板及如何编写 UI 参考 “新增 UI” 需求指南,这里只给出必要的修改部分,模板部分不再给出
 | 
			
		||||
export const MyCom = defineComponent(props => {
 | 
			
		||||
    const click = async () => {
 | 
			
		||||
        // 调用接口,并等待执行完毕,获取异步返回值
 | 
			
		||||
        const num = await getInputNumber(
 | 
			
		||||
            props.controller, // UI 控制器
 | 
			
		||||
            '请输入一个数字', // 显示的文字
 | 
			
		||||
            [240, 240, void 0, void 0, 0.5, 0.5], // 输入框位置
 | 
			
		||||
            240, // 输入框宽度
 | 
			
		||||
            // 其他参数配置,参考 API 文档
 | 
			
		||||
            {
 | 
			
		||||
                // 例如设置一个占位符
 | 
			
		||||
                input: {
 | 
			
		||||
                    placeholder: '输入数字'
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        );
 | 
			
		||||
        if (isNaN(num)) {
 | 
			
		||||
            // 如果用户输入的不是数字或点了取消
 | 
			
		||||
        } else {
 | 
			
		||||
            // 如果用户输入了数字
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    return () => (
 | 
			
		||||
        <container>
 | 
			
		||||
            <text
 | 
			
		||||
                text="这是一个按钮"
 | 
			
		||||
                // 监听 click 事件
 | 
			
		||||
                onClick={click}
 | 
			
		||||
            />
 | 
			
		||||
        </container>
 | 
			
		||||
    );
 | 
			
		||||
});
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## 拓展-API参考
 | 
			
		||||
 | 
			
		||||
- [ConfirmBox](../../api/user-client-modules/组件%20ConfirmBox.md)
 | 
			
		||||
 | 
			
		||||
@ -7,13 +7,37 @@
 | 
			
		||||
 | 
			
		||||
## 客户端内容
 | 
			
		||||
 | 
			
		||||
以下内容中,一级列表是基础需求指南,二级列表是拓展需求指南。
 | 
			
		||||
 | 
			
		||||
- [修改状态栏显示](./status-bar.md)
 | 
			
		||||
    - [可交互按钮](./status-bar.md#拓展-可交互按钮)
 | 
			
		||||
    - [新增勇士属性](./status-bar.md#拓展-新增勇士属性) (既包含客户端,也包含数据端)
 | 
			
		||||
- [编写新 UI](./new-ui.md)
 | 
			
		||||
- [自定义按键](./hotkey.md)
 | 
			
		||||
    - [UI 与组件的区别](./new-ui.md#拓展-ui-与组件的区别)
 | 
			
		||||
    - [UI 编写参考](../ui.md)
 | 
			
		||||
- [新增按键](./hotkey.md)
 | 
			
		||||
    - [添加辅助按键](./hotkey.md#拓展-添加辅助按键)
 | 
			
		||||
    - [在 UI 内实现按键](./hotkey.md#拓展-在-ui-内实现按键)
 | 
			
		||||
    - [单功能多按键](./hotkey.md#拓展-单功能多按键)
 | 
			
		||||
    - [按下时触发](./hotkey.md#拓展-按下时触发)
 | 
			
		||||
- [动画效果](./animate.md)
 | 
			
		||||
    - [颜色动画](./animate.md#拓展-颜色动画)
 | 
			
		||||
    - [配合交互](./animate.md#拓展-配合交互)
 | 
			
		||||
- [选择框与确认框](./choice.md)
 | 
			
		||||
    - [使用枚举定义选择框](./choice.md#拓展-使用枚举定义选择框)
 | 
			
		||||
    - [等待框](./choice.md#拓展-等待框)
 | 
			
		||||
    - [输入框](./choice.md#拓展-输入框)
 | 
			
		||||
 | 
			
		||||
## 数据端内容
 | 
			
		||||
 | 
			
		||||
- [怪物伤害计算](./damage.md)
 | 
			
		||||
以下内容中,一级列表是基础需求指南,二级列表是拓展需求指南。
 | 
			
		||||
 | 
			
		||||
- [怪物特殊属性](./special.md)
 | 
			
		||||
    - [用函数声明属性](./special.md#拓展-用函数声明属性)
 | 
			
		||||
    - [地图伤害](./special.md#拓展-地图伤害)
 | 
			
		||||
    - [光环属性](./special.md#拓展-光环属性)
 | 
			
		||||
    - [输出回合数](./special.md#拓展-输出回合数)
 | 
			
		||||
- [主动技能](./skill.md)
 | 
			
		||||
    - [多技能设计思路](./skill.md#拓展-多技能设计思路)
 | 
			
		||||
    - [战后自动关闭技能](./skill.md#拓展-战后自动关闭技能)
 | 
			
		||||
    - [在开启或关闭技能时执行内容](./skill.md#拓展-在开启或关闭技能时执行内容)
 | 
			
		||||
 | 
			
		||||
@ -265,7 +265,7 @@ col.applyHalo(
 | 
			
		||||
 | 
			
		||||
## 拓展-输出回合数
 | 
			
		||||
 | 
			
		||||
样板默认的 `calDamageWith` 函数只允许输出伤害值,而有时候我们可能会需要战斗的回合数,这时候我们需要修改一下这部分内容,将伤害计算逻辑单独提出来,然后在 `calDamageWith` 中调用它。在需要回合数的时候,我们调用提出了的函数即可,如下例所示:
 | 
			
		||||
样板默认的 `calDamageWith` 函数只允许输出伤害值,而有时候我们可能会需要战斗的回合数,这时候我们需要修改一下这部分内容,将伤害计算逻辑单独提出来,命名为 `calDamageWithTurn`,然后在 `calDamageWith` 中调用它。在需要回合数的时候,我们调用 `calDamageWithTurn` 函数即可,如下例所示:
 | 
			
		||||
 | 
			
		||||
```ts
 | 
			
		||||
/** 包含回合数的伤害计算 */
 | 
			
		||||
 | 
			
		||||
@ -181,6 +181,47 @@ leftStatus.def = getHeroStatusOn('def');
 | 
			
		||||
leftStatus.atkSpeed = getHeroStatusOn('atkSpeed');
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
状态栏组件中:
 | 
			
		||||
 | 
			
		||||
```tsx
 | 
			
		||||
// 使用模板字符串,显示百分比
 | 
			
		||||
<text text={`${s.atkSpeed * 100}%`} />
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### 属性实现
 | 
			
		||||
 | 
			
		||||
为了实现勇士属性,我们需要修改伤害计算逻辑。我们打开 `packages-user/data-state/src/enemy/damage.ts`,翻到最后找到 `calDamageWith` 函数,在它上面有一个名为 `realStatus` 的数组,我们在这里新增一项 `atkSpeed`:
 | 
			
		||||
 | 
			
		||||
```ts
 | 
			
		||||
/**
 | 
			
		||||
 * 计算伤害时会用到的勇士属性,攻击防御,其余的不会有buff加成,直接从core.status.hero取
 | 
			
		||||
 */
 | 
			
		||||
const realStatus: (keyof HeroStatus)[] = [
 | 
			
		||||
    'atk',
 | 
			
		||||
    'def',
 | 
			
		||||
    // ... 原有内容
 | 
			
		||||
 | 
			
		||||
    // 新增 atkSpeed 属性
 | 
			
		||||
    'atkSpeed' // [!code ++]
 | 
			
		||||
];
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
然后在 `calDamageWith` 伤害计算中修改伤害计算,给勇士每回合造成的伤害乘以攻速,注意放置的位置:
 | 
			
		||||
 | 
			
		||||
```ts
 | 
			
		||||
export function calDamageWith(
 | 
			
		||||
    info: UserEnemyInfo,
 | 
			
		||||
    hero: Partial<HeroStatus>
 | 
			
		||||
): number {
 | 
			
		||||
    // ... 原有逻辑
 | 
			
		||||
 | 
			
		||||
    // 乘以攻速
 | 
			
		||||
    heroPerDamage *= hero.atkSpeed ?? 1;
 | 
			
		||||
 | 
			
		||||
    // ... 原有逻辑
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## 拓展-了解 UI 编写的基本逻辑
 | 
			
		||||
 | 
			
		||||
参考[此文档](./ui.md),此文档将会教你如何从头开始编写一个 UI,并解释 UI 运行与渲染的基本逻辑。
 | 
			
		||||
 | 
			
		||||
@ -6,11 +6,15 @@
 | 
			
		||||
 | 
			
		||||
参考[此文档](./implements.md)
 | 
			
		||||
 | 
			
		||||
## 热重载
 | 
			
		||||
 | 
			
		||||
2.B 样板支持热重载,允许一些内容在不刷新页面的情况下就可以直接更新,包括 UI、怪物数据、道具数据等。例如,你在编辑器里面修改了一个怪物的攻击并保存,这时候进入游戏界面,可以直接看到地图上的怪物伤害变化了(怪物手册等 UI 中的怪物数据需要重新打开一次 UI 才会更新)。
 | 
			
		||||
 | 
			
		||||
## 启动游戏与编辑器
 | 
			
		||||
 | 
			
		||||
在造塔群中的群文件中找到 `启动服务->2.B+ 启动服务`,根据自己设备的系统下载对应的启动服务(此版本不支持移动端造塔),下载后运行安装到自己的设备,可以选择安装路径。
 | 
			
		||||
 | 
			
		||||
安装完毕后,打开软件,在左侧点击选择文件夹,然后打开 2.B 样板文件夹,即包含 `package.json` `packages` `packages-user` 这些目录的文件,打开错了会提示打开错误。
 | 
			
		||||
安装完毕后,打开软件,在左侧点击选择文件夹,然后打开 2.B 样板文件夹,即包含 `package.json` `packages` `packages-user` 这些目录的文件夹,打开错了会提示打开错误。
 | 
			
		||||
 | 
			
		||||
然后点击右侧的安装依赖,耐心等待一段时间,等待依赖安装完毕。
 | 
			
		||||
 | 
			
		||||
@ -82,7 +86,9 @@ graph TD
 | 
			
		||||
 | 
			
		||||
### 协议问题
 | 
			
		||||
 | 
			
		||||
2.B 样板换用了 `GPL3.0` 开源协议,这要求所有以此为基础开发的项目也必须完全开源,但考虑到很多作者不了解其中的细节,因此样板将会针对此问题自动处理,处理方案为:**将源码原封不动地打包为压缩包,放到构建完成的游戏中**,届时,只要在网站上下载游戏,就可以解压压缩包查看源码。
 | 
			
		||||
2.B 样板换用了 `GPL3.0` 开源协议,这要求所有以此为基础开发的项目也必须完全开源,但考虑到很多作者不了解其中的细节,因此样板将会针对此问题自动处理,处理方案为:**将源码原封不动地打包为压缩包,放到构建完成的游戏中**,届时,只要在网站上下载游戏,就可以解压压缩包查看源码及开源协议。
 | 
			
		||||
 | 
			
		||||
同时,这也意味着,如果你使用本样板开发游戏,其他任何人都可以以你的游戏为基础进行二次开发,而不需要你本人同意。如果不想让素材也能被别人使用,可以单独针对素材使用其他协议(如 `CC` 协议,可以上网查询具体信息),而不使用 `GPL3.0` 协议,但代码必须遵循 `GPL3.0` 协议。
 | 
			
		||||
 | 
			
		||||
## 学会查阅此文档
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										556
									
								
								docs/guide/ui/component.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										556
									
								
								docs/guide/ui/component.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,556 @@
 | 
			
		||||
# 组件使用指南
 | 
			
		||||
 | 
			
		||||
2.B 内置了很多实用的组件,本节将会介绍一些常用组件的使用方式。
 | 
			
		||||
 | 
			
		||||
## 组件引入
 | 
			
		||||
 | 
			
		||||
组件都在 `packages-user/client-modules/src/render/components` 文件夹中,如果在 `ui` 文件夹下引用,注意路径关系,应该如下引入:
 | 
			
		||||
 | 
			
		||||
```ts
 | 
			
		||||
// 从 components 文件夹引入,注意路径关系
 | 
			
		||||
import { TextContent } from '../components';
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## 组件与元素
 | 
			
		||||
 | 
			
		||||
一般情况下,组件会包含所有元素拥有的参数,例如 `loc` `alpha` `zIndex`,甚至是 `noevent` `cache` 等,也可以监听 `onClick` `onEnter` 这些交互事件。
 | 
			
		||||
 | 
			
		||||
除了元素的参数,组件自身可能还会包含一些参数和事件。
 | 
			
		||||
 | 
			
		||||
有些组件还提供了暴露接口,可以使用这些接口直接控制组件内部。
 | 
			
		||||
 | 
			
		||||
## 多行文本 TextContent
 | 
			
		||||
 | 
			
		||||
类似于 2.x 的 `drawTextContent`,可以用于多行文本,包含打字机功能。相比于 `drawTextContent` 的主要优势是支持了英文以及更好的性能表现。
 | 
			
		||||
 | 
			
		||||
### 显示文字
 | 
			
		||||
 | 
			
		||||
直接调用组件即可:
 | 
			
		||||
 | 
			
		||||
```tsx
 | 
			
		||||
import { TextContent } from '../components';
 | 
			
		||||
 | 
			
		||||
// 不再展示完整 UI 模板,只展示核心部分
 | 
			
		||||
export const MyCom = defineComponent(() => {
 | 
			
		||||
    // 显示一段长文字
 | 
			
		||||
    const toShow = 'man what can i say '.repeat(10);
 | 
			
		||||
 | 
			
		||||
    return () => (
 | 
			
		||||
        <container>
 | 
			
		||||
            {/* 直接调用组件,其中宽度 width 必填,而 loc 中设定的宽度是无效的 */}
 | 
			
		||||
            <TextContent loc={[0, 0, 240, 200]} width={240} text={toShow} />
 | 
			
		||||
        </container>
 | 
			
		||||
    );
 | 
			
		||||
});
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### 常用配置
 | 
			
		||||
 | 
			
		||||
| 配置          | 数据类型  | 说明                                       |
 | 
			
		||||
| ------------- | --------- | ------------------------------------------ |
 | 
			
		||||
| `font`        | `Font`    | 文字字体                                   |
 | 
			
		||||
| `interval`    | `number`  | 打字机效果每两个字之间的时间间隔,单位毫秒 |
 | 
			
		||||
| `lineHeight`  | `number`  | 行间距,单位像素                           |
 | 
			
		||||
| `fill`        | `boolean` | 是否填充文字,默认填充                     |
 | 
			
		||||
| `stroke`      | `boolean` | 是否描边文字,默认不描边                   |
 | 
			
		||||
| `fillStyle`   | `string`  | 文字填充样式                               |
 | 
			
		||||
| `strokeStyle` | `string`  | 文字描边样式                               |
 | 
			
		||||
 | 
			
		||||
使用示例:
 | 
			
		||||
 | 
			
		||||
:::code-group
 | 
			
		||||
 | 
			
		||||
```tsx [自定义字体]
 | 
			
		||||
import { Font } from '@motajs/style'; // [!code ++]
 | 
			
		||||
import { TextContent } from '../components';
 | 
			
		||||
 | 
			
		||||
// 不再展示完整 UI 模板,只展示核心部分
 | 
			
		||||
export const MyCom = defineComponent(() => {
 | 
			
		||||
    // 显示一段长文字
 | 
			
		||||
    const toShow = 'man what can i say '.repeat(10);
 | 
			
		||||
    // 24px 大小的 Arial 字体
 | 
			
		||||
    const myFont = new Font('Arial', 24); // [!code ++]
 | 
			
		||||
 | 
			
		||||
    return () => (
 | 
			
		||||
        <container>
 | 
			
		||||
            <TextContent
 | 
			
		||||
                loc={[0, 0, 240, 200]}
 | 
			
		||||
                width={240}
 | 
			
		||||
                text={toShow}
 | 
			
		||||
                font={myFont} // 使用自定义字体 [!code ++]
 | 
			
		||||
            />
 | 
			
		||||
        </container>
 | 
			
		||||
    );
 | 
			
		||||
});
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
```tsx [修改字体颜色]
 | 
			
		||||
import { TextContent } from '../components';
 | 
			
		||||
 | 
			
		||||
// 不再展示完整 UI 模板,只展示核心部分
 | 
			
		||||
export const MyCom = defineComponent(() => {
 | 
			
		||||
    // 显示一段长文字
 | 
			
		||||
    const toShow = 'man what can i say '.repeat(10);
 | 
			
		||||
 | 
			
		||||
    return () => (
 | 
			
		||||
        <container>
 | 
			
		||||
            <TextContent
 | 
			
		||||
                loc={[0, 0, 240, 200]}
 | 
			
		||||
                width={240}
 | 
			
		||||
                text={toShow}
 | 
			
		||||
                fill // 文字填充 [!code ++]
 | 
			
		||||
                stroke // 文字描边 [!code ++]
 | 
			
		||||
                fillStyle="yellow" // 文字填充为黄色 [!code ++]
 | 
			
		||||
                strokeStyle="cyan" // 文字描边为青色 [!code ++]
 | 
			
		||||
            />
 | 
			
		||||
        </container>
 | 
			
		||||
    );
 | 
			
		||||
});
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
```tsx [修改行间距]
 | 
			
		||||
import { TextContent } from '../components';
 | 
			
		||||
 | 
			
		||||
// 不再展示完整 UI 模板,只展示核心部分
 | 
			
		||||
export const MyCom = defineComponent(() => {
 | 
			
		||||
    // 显示一段长文字
 | 
			
		||||
    const toShow = 'man what can i say '.repeat(10);
 | 
			
		||||
 | 
			
		||||
    return () => (
 | 
			
		||||
        <container>
 | 
			
		||||
            <TextContent
 | 
			
		||||
                loc={[0, 0, 240, 200]}
 | 
			
		||||
                width={240}
 | 
			
		||||
                text={toShow}
 | 
			
		||||
                lineHeight={8} // 行间距为 8px [!code ++]
 | 
			
		||||
            />
 | 
			
		||||
        </container>
 | 
			
		||||
    );
 | 
			
		||||
});
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
### 自动调整高度
 | 
			
		||||
 | 
			
		||||
如果我们不知道这些文字显示的时候会有多高,那么我们可以使用 `autoHeight` 来让组件自动确定自身的高度,可以用于滚动条等场景。
 | 
			
		||||
 | 
			
		||||
```tsx
 | 
			
		||||
import { TextContent } from '../components';
 | 
			
		||||
 | 
			
		||||
// 不再展示完整 UI 模板,只展示核心部分
 | 
			
		||||
export const MyCom = defineComponent(() => {
 | 
			
		||||
    // 显示一段长文字
 | 
			
		||||
    const toShow = 'man what can i say '.repeat(10);
 | 
			
		||||
 | 
			
		||||
    return () => (
 | 
			
		||||
        <container>
 | 
			
		||||
            <TextContent
 | 
			
		||||
                loc={[0, 0, 240, 200]}
 | 
			
		||||
                width={240}
 | 
			
		||||
                text={toShow}
 | 
			
		||||
                autoHeight // 使用 autoHeight,让组件自动确定自己的高度 [!code ++]
 | 
			
		||||
            />
 | 
			
		||||
        </container>
 | 
			
		||||
    );
 | 
			
		||||
});
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### 转义字符
 | 
			
		||||
 | 
			
		||||
与 2.x 类似,2.B 的 `TextContent` 也允许转义字符。具体请参考[此文档](../../api/user-client-modules/TextContentParser.md#转义字符语法说明)。
 | 
			
		||||
 | 
			
		||||
### API 参考
 | 
			
		||||
 | 
			
		||||
`TextContent` 还有很多功能和特性,这里只做最基础的教学,如果需要其他功能,请参考[API 文档](../../api/user-client-modules/组件%20TextContent.md)
 | 
			
		||||
 | 
			
		||||
## 滚动条 Scroll
 | 
			
		||||
 | 
			
		||||
`Scroll` 是滚动条组件,如果内容在一个界面大小内显示不下,可以使用滚动条组件,这样玩家可以使用鼠标滚轮或点击拖动来滚动内容。
 | 
			
		||||
 | 
			
		||||
### 基本使用
 | 
			
		||||
 | 
			
		||||
直接调用组件,然后填写组件内容即可:
 | 
			
		||||
 | 
			
		||||
```tsx {7-10}
 | 
			
		||||
import { Scroll } from '../components';
 | 
			
		||||
 | 
			
		||||
// 不再展示完整 UI 模板,只展示核心部分
 | 
			
		||||
export const MyCom = defineComponent(() => {
 | 
			
		||||
    return () => (
 | 
			
		||||
        // loc 必填,表示组件位置
 | 
			
		||||
        <Scroll loc={[0, 0, 416, 416]}>
 | 
			
		||||
            <text text="text1" />
 | 
			
		||||
            {/* 省略更多内容 */}
 | 
			
		||||
        </Scroll>
 | 
			
		||||
    );
 | 
			
		||||
});
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### 平铺布局
 | 
			
		||||
 | 
			
		||||
在使用 `Scroll` 组件时,我们推荐使用平铺式布局,即所有内容平铺在 `Scroll` 组件中,而不是将整体用一个 `container` 将它包起来,这非常有助于提高滚动条组件的性能。
 | 
			
		||||
 | 
			
		||||
例如下面这种格式就是**好的写法**:
 | 
			
		||||
 | 
			
		||||
```tsx {8-10}
 | 
			
		||||
import { Scroll } from '../components';
 | 
			
		||||
 | 
			
		||||
// 不再展示完整 UI 模板,只展示核心部分
 | 
			
		||||
export const MyCom = defineComponent(() => {
 | 
			
		||||
    return () => (
 | 
			
		||||
        <Scroll loc={[0, 0, 416, 416]}>
 | 
			
		||||
            {/* 平铺内容,性能表现更好 */}
 | 
			
		||||
            <text text="text1" />
 | 
			
		||||
            <text text="text2" />
 | 
			
		||||
            <text text="text3" />
 | 
			
		||||
            {/* 省略更多内容 */}
 | 
			
		||||
        </Scroll>
 | 
			
		||||
    );
 | 
			
		||||
});
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
而下面这种就是**不好的写法**:
 | 
			
		||||
 | 
			
		||||
```tsx {8-12}
 | 
			
		||||
import { Scroll } from '../components';
 | 
			
		||||
 | 
			
		||||
// 不再展示完整 UI 模板,只展示核心部分
 | 
			
		||||
export const MyCom = defineComponent(() => {
 | 
			
		||||
    return () => (
 | 
			
		||||
        <Scroll loc={[0, 0, 416, 416]}>
 | 
			
		||||
            {/* 用一个 container 包裹,性能表现不好 */}
 | 
			
		||||
            <container>
 | 
			
		||||
                <text text="text1" />
 | 
			
		||||
                <text text="text2" />
 | 
			
		||||
                <text text="text3" />
 | 
			
		||||
            </container>
 | 
			
		||||
        </Scroll>
 | 
			
		||||
    );
 | 
			
		||||
});
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### 横向滚动条
 | 
			
		||||
 | 
			
		||||
添加 `hor` 标记,即可使滚动条变为横向。暂时没有既可以横向又可以纵向的滚动条。
 | 
			
		||||
 | 
			
		||||
```tsx {7}
 | 
			
		||||
import { Scroll } from '../components';
 | 
			
		||||
 | 
			
		||||
// 不再展示完整 UI 模板,只展示核心部分
 | 
			
		||||
export const MyCom = defineComponent(() => {
 | 
			
		||||
    return () => (
 | 
			
		||||
        // 添加 hor 标记,变为横向
 | 
			
		||||
        <Scroll loc={[0, 0, 416, 416]} hor>
 | 
			
		||||
            <text text="text1" />
 | 
			
		||||
            {/* 省略更多内容 */}
 | 
			
		||||
        </Scroll>
 | 
			
		||||
    );
 | 
			
		||||
});
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### 隐藏滚动条
 | 
			
		||||
 | 
			
		||||
有时候可能需要隐藏滚动条(例如样板的浏览地图界面中左侧的楼层列表),可以使用 `noscroll` 标记实现:
 | 
			
		||||
 | 
			
		||||
```tsx {7}
 | 
			
		||||
import { Scroll } from '../components';
 | 
			
		||||
 | 
			
		||||
// 不再展示完整 UI 模板,只展示核心部分
 | 
			
		||||
export const MyCom = defineComponent(() => {
 | 
			
		||||
    return () => (
 | 
			
		||||
        // 添加 noscroll 标记,隐藏滚动条
 | 
			
		||||
        <Scroll loc={[0, 0, 416, 416]} noscroll>
 | 
			
		||||
            <text text="text1" />
 | 
			
		||||
            {/* 省略更多内容 */}
 | 
			
		||||
        </Scroll>
 | 
			
		||||
    );
 | 
			
		||||
});
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### 布局补偿
 | 
			
		||||
 | 
			
		||||
有时候我们需要在滚动条滚动到最后时填充一些空白内容,可以使用 `padEnd` 来实现:
 | 
			
		||||
 | 
			
		||||
```tsx {7}
 | 
			
		||||
import { Scroll } from '../components';
 | 
			
		||||
 | 
			
		||||
// 不再展示完整 UI 模板,只展示核心部分
 | 
			
		||||
export const MyCom = defineComponent(() => {
 | 
			
		||||
    return () => (
 | 
			
		||||
        // 使用 padEnd 在滚动条最后填充空白内容,单位像素
 | 
			
		||||
        <Scroll loc={[0, 0, 416, 416]} padEnd={120}>
 | 
			
		||||
            <text text="text1" />
 | 
			
		||||
            {/* 省略更多内容 */}
 | 
			
		||||
        </Scroll>
 | 
			
		||||
    );
 | 
			
		||||
});
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### 代码控制滚动条
 | 
			
		||||
 | 
			
		||||
可以使用 `Scroll` 提供的接口来用代码控制滚动条:
 | 
			
		||||
 | 
			
		||||
```tsx {5-12,15-16}
 | 
			
		||||
import { Scroll, ScrollExpose } from '../components'; // [!code ++]
 | 
			
		||||
import { vue } from 'vue'; // [!code ++]
 | 
			
		||||
 | 
			
		||||
// 不再展示完整 UI 模板,只展示核心部分
 | 
			
		||||
export const MyCom = defineComponent(() => {
 | 
			
		||||
    // 使用响应式变量定义 scroll 引用
 | 
			
		||||
    const scrollRef = ref<ScrollExpose>();
 | 
			
		||||
 | 
			
		||||
    onMounted(() => {
 | 
			
		||||
        // 滚动至 100 像素的位置,动画时长 500ms
 | 
			
		||||
        scrollRef.value?.scrollTo(100, 500);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    return () => (
 | 
			
		||||
        // 将 ref 属性设为 scrollRef 来获取 Scroll 的接口
 | 
			
		||||
        <Scroll loc={[0, 0, 416, 416]} ref={scrollRef}>
 | 
			
		||||
            <text text="text1" />
 | 
			
		||||
            {/* 省略更多内容 */}
 | 
			
		||||
        </Scroll>
 | 
			
		||||
    );
 | 
			
		||||
});
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### API 参考
 | 
			
		||||
 | 
			
		||||
API 参考[此文档](../../api/user-client-modules/组件%20Scroll.md)。
 | 
			
		||||
 | 
			
		||||
## 图标组件
 | 
			
		||||
 | 
			
		||||
在 `components/icons.tsx` 中内置了一些图标,可以直接使用。
 | 
			
		||||
 | 
			
		||||
### 基本使用
 | 
			
		||||
 | 
			
		||||
以箭头图标为例:
 | 
			
		||||
 | 
			
		||||
```tsx {8}
 | 
			
		||||
import { ArrowDownTailless } from '../components';
 | 
			
		||||
 | 
			
		||||
// 不再展示完整 UI 模板,只展示核心部分
 | 
			
		||||
export const MyCom = defineComponent(() => {
 | 
			
		||||
    return () => (
 | 
			
		||||
        <container>
 | 
			
		||||
            {/* 调用图标组件 */}
 | 
			
		||||
            <ArrowDownTailless loc={[0, 0, 48, 48]} />
 | 
			
		||||
        </container>
 | 
			
		||||
    );
 | 
			
		||||
});
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
所有图标都可以填写图形元素的参数,例如 `fill` `stroke` `strokeStyle` `lineWidth` 等。大部分图标默认都是描边样式,如果使用填充可能会导致效果不好。例如修改描边样式和线宽:
 | 
			
		||||
 | 
			
		||||
```tsx {8}
 | 
			
		||||
import { ArrowDownTailless } from '../components';
 | 
			
		||||
 | 
			
		||||
// 不再展示完整 UI 模板,只展示核心部分
 | 
			
		||||
export const MyCom = defineComponent(() => {
 | 
			
		||||
    return () => (
 | 
			
		||||
        <container>
 | 
			
		||||
            <ArrowDownTailless
 | 
			
		||||
                loc={[0, 0, 48, 48]}
 | 
			
		||||
                strokeStyle="cyan" // 描边使用青色
 | 
			
		||||
                lineWidth={2} // 线宽为 2px
 | 
			
		||||
            />
 | 
			
		||||
        </container>
 | 
			
		||||
    );
 | 
			
		||||
});
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### 图标列表
 | 
			
		||||
 | 
			
		||||
目前样板包含这些图标:
 | 
			
		||||
 | 
			
		||||
- `RollbackIcon`: 回退图标
 | 
			
		||||
- `RetweenIcon`: 回收图标
 | 
			
		||||
- `ViewMapIcon`: 浏览地图图标
 | 
			
		||||
- `DanmakuIcon`: 弹幕图标
 | 
			
		||||
- `ReplayIcon`: 回放图标
 | 
			
		||||
- `numpadIcon`: 数字键盘图标
 | 
			
		||||
- `PlayIcon`: 开始播放图标
 | 
			
		||||
- `PauseIcon`: 暂停播放图标
 | 
			
		||||
- `DoubleArrow`: 双箭头图标(向右)
 | 
			
		||||
- `StepForward`: 单步向前图标
 | 
			
		||||
- `SoundVolume`: 音量图标
 | 
			
		||||
- `Fullscreen`: 全屏图标
 | 
			
		||||
- `ExitFullscreen`: 退出全屏图标
 | 
			
		||||
- `ArrowLeftTailless`: 无尾巴左箭头图标
 | 
			
		||||
- `ArrowRightTailless`: 无尾巴右箭头图标
 | 
			
		||||
- `ArrowUpTailless`: 无尾巴上箭头图标
 | 
			
		||||
- `ArrowDownTailless`: 无尾巴下箭头图标
 | 
			
		||||
 | 
			
		||||
### API 及参数参考
 | 
			
		||||
 | 
			
		||||
参数参考[此文档](../../api/motajs-render-vue/GraphicBaseProps.md)。
 | 
			
		||||
 | 
			
		||||
API 参考[此文档](../../api/user-client-modules/图标组件.md)
 | 
			
		||||
 | 
			
		||||
## 分页 Page
 | 
			
		||||
 | 
			
		||||
分页可以用来展示大量内容,在极端情况下,其性能要比 `Scroll` 更好,但交互手感与易用性不如滚动条。
 | 
			
		||||
 | 
			
		||||
### 基本使用
 | 
			
		||||
 | 
			
		||||
`Page` 组件需要传入两个必填参数 `pages` 和 `loc`,`pages` 代表总页数,`loc` 代表位置。
 | 
			
		||||
 | 
			
		||||
每个页面的内容使用插槽形式传入,接收 `page` 作为参数,代表当前是第几页。你可能不理解这句话,用代码写的话就是这样:
 | 
			
		||||
 | 
			
		||||
```tsx {6-17}
 | 
			
		||||
import { Page } from '../components';
 | 
			
		||||
 | 
			
		||||
// 不再展示完整 UI 模板,只展示核心部分
 | 
			
		||||
export const MyCom = defineComponent(() => {
 | 
			
		||||
    return () => (
 | 
			
		||||
        <Page
 | 
			
		||||
            loc={[0, 0, 416, 416]} // 位置
 | 
			
		||||
            pages={10} // 总页码数
 | 
			
		||||
        >
 | 
			
		||||
            {/* 插槽内容,传入一个函数,参数代表当前是第几页 */}
 | 
			
		||||
            {(page: number) => (
 | 
			
		||||
                <container>
 | 
			
		||||
                    {/* 这里面填写当前页显示的内容,例如添加一个文字显示当前第几页 */}
 | 
			
		||||
                    <text text={page.toString()} />
 | 
			
		||||
                </container>
 | 
			
		||||
            )}
 | 
			
		||||
        </Page>
 | 
			
		||||
    );
 | 
			
		||||
});
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### 第一种设置与获取当前页
 | 
			
		||||
 | 
			
		||||
可以通过 `v-model` 指令来创建双向数据绑定,从而达到设置与获取当前页码的功能。
 | 
			
		||||
 | 
			
		||||
这种方式一般情况下相对来说没有下一节提到的方式更好,因此相对不推荐。使用示例如下:
 | 
			
		||||
 | 
			
		||||
```tsx {7-13}
 | 
			
		||||
import { Page } from '../components';
 | 
			
		||||
// 从 vue 引入 ref 响应式函数
 | 
			
		||||
import { ref, watch } from 'vue'; // [!code ++]
 | 
			
		||||
 | 
			
		||||
// 不再展示完整 UI 模板,只展示核心部分
 | 
			
		||||
export const MyCom = defineComponent(() => {
 | 
			
		||||
    // 定义响应式变量
 | 
			
		||||
    const nowPage = ref(0);
 | 
			
		||||
 | 
			
		||||
    // 监听当且页码的变化,需要的时候直接用 nowPage.value 获取也可
 | 
			
		||||
    watch(nowPage, value => core.drawTip(`切换至${value}页!`));
 | 
			
		||||
    /** 设置当前页码 */
 | 
			
		||||
    const changePage = (value: number) => void (nowPage.value = value);
 | 
			
		||||
 | 
			
		||||
    return () => (
 | 
			
		||||
        <Page
 | 
			
		||||
            loc={[0, 0, 416, 416]}
 | 
			
		||||
            pages={10}
 | 
			
		||||
            // 使用 v-model 指令创建双向数据绑定
 | 
			
		||||
            v-model:page={nowPage.value} // [!code ++]
 | 
			
		||||
        >
 | 
			
		||||
            {(page: number) => (
 | 
			
		||||
                <container>
 | 
			
		||||
                    <text text={page.toString()} />
 | 
			
		||||
                </container>
 | 
			
		||||
            )}
 | 
			
		||||
        </Page>
 | 
			
		||||
    );
 | 
			
		||||
});
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### 第二种设置与获取当前页方式
 | 
			
		||||
 | 
			
		||||
相比于上一种方式,我们更推荐使用下面这种方式来设置与获取当前页。
 | 
			
		||||
 | 
			
		||||
可以使用 `Page` 组件提供的 `changePage` 和 `movePage` 来切换页码,其中前者是直接切换至某一页,后者是在当前页的基础上移动页码数。
 | 
			
		||||
 | 
			
		||||
可以使用 `now` 来获取当前页。
 | 
			
		||||
 | 
			
		||||
二者的示例如下:
 | 
			
		||||
 | 
			
		||||
:::code-group
 | 
			
		||||
 | 
			
		||||
```tsx [切换页码] {6-16,19-20}
 | 
			
		||||
import { Page, PageExpose } from '../components'; // [!code ++]
 | 
			
		||||
import { vue } from 'vue'; // [!code ++]
 | 
			
		||||
 | 
			
		||||
// 不再展示完整 UI 模板,只展示核心部分
 | 
			
		||||
export const MyCom = defineComponent(() => {
 | 
			
		||||
    // 使用响应式变量定义 Page 引用
 | 
			
		||||
    const pageRef = ref<PageExpose>();
 | 
			
		||||
 | 
			
		||||
    onMounted(() => {
 | 
			
		||||
        // 切换至第五页
 | 
			
		||||
        pageRef.value?.changePage(5);
 | 
			
		||||
        // 在当前页的基础上增加两页,也就是切换到第七页
 | 
			
		||||
        pageRef.value?.movePage(2);
 | 
			
		||||
        // 在当前页的基础上减少两页,也就是切换回第五页
 | 
			
		||||
        pageRef.value?.movePage(-2);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    return () => (
 | 
			
		||||
        // 将 ref 属性赋值为 pageRef 来获取其接口
 | 
			
		||||
        <Page loc={[0, 0, 416, 416]} pages={10} ref={pageRef}>
 | 
			
		||||
            {(page: number) => (
 | 
			
		||||
                <container>
 | 
			
		||||
                    <text text={page.toString()} />
 | 
			
		||||
                </container>
 | 
			
		||||
            )}
 | 
			
		||||
        </Page>
 | 
			
		||||
    );
 | 
			
		||||
});
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
```tsx [获取页码] {6-12,15-16}
 | 
			
		||||
import { Page, PageExpose } from '../components'; // [!code ++]
 | 
			
		||||
import { vue } from 'vue'; // [!code ++]
 | 
			
		||||
 | 
			
		||||
// 不再展示完整 UI 模板,只展示核心部分
 | 
			
		||||
export const MyCom = defineComponent(() => {
 | 
			
		||||
    // 使用响应式变量定义 Page 引用
 | 
			
		||||
    const pageRef = ref<PageExpose>();
 | 
			
		||||
 | 
			
		||||
    onMounted(() => {
 | 
			
		||||
        const page = pageRef.value?.now();
 | 
			
		||||
        core.drawTip(`当前是第${page}页!`);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    return () => (
 | 
			
		||||
        // 将 ref 属性赋值为 pageRef 来获取其接口
 | 
			
		||||
        <Page loc={[0, 0, 416, 416]} pages={10} ref={pageRef}>
 | 
			
		||||
            {(page: number) => (
 | 
			
		||||
                <container>
 | 
			
		||||
                    <text text={page.toString()} />
 | 
			
		||||
                </container>
 | 
			
		||||
            )}
 | 
			
		||||
        </Page>
 | 
			
		||||
    );
 | 
			
		||||
});
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
## 更多组件
 | 
			
		||||
 | 
			
		||||
本文只简单讲解了部分常用的组件,样板还有很多内置的组件。以下是所有内置组件的 API 参考:
 | 
			
		||||
 | 
			
		||||
- [ConfirmBox](../../api/user-client-modules/组件%20ConfirmBox.md):确认框,一般使用 `getConfirm` 接口,不直接使用组件。
 | 
			
		||||
- [Choices](../../api/user-client-modules/组件%20Choices.md):选择框,一般使用 `getChoice` 接口,不直接使用组件。
 | 
			
		||||
- [FloorSelector](../../api/user-client-modules/组件%20FloorSelector.md):楼层选择组件,浏览地图左侧的楼层选择就是使用的本组件。
 | 
			
		||||
- [图标组件](../../api/user-client-modules/图标组件.md):一些常用图标。
 | 
			
		||||
- [Input](../../api/user-client-modules/组件%20Input.md):输入组件,可以放到组件内部,可以用于搜索栏等。
 | 
			
		||||
- [InputBox](../../api/user-client-modules/组件%20InputBox.md):输入框组件,类似于确认框,一般使用 `getInput` 或 `getInputNumber` 接口,不使用本组件。
 | 
			
		||||
- [List](../../api/user-client-modules/组件%20List.md):列表组件,可以用于展示一列内容。
 | 
			
		||||
- [ListPage](../../api/user-client-modules/组件%20ListPage.md):左侧是列表,右侧是当前选项对应的详情页,可以用于游戏机制说明等。
 | 
			
		||||
- [Progress](../../api/user-client-modules/组件%20Progress.md):进度条组件,播放录像时右下角的进度条就是本组件。
 | 
			
		||||
- [Arrow](../../api/user-client-modules/组件%20Arrow.md):箭头组件,画一个箭头。
 | 
			
		||||
- [ScrollText](../../api/user-client-modules/组件%20ScrollText.md):滚动文本组件,可以用于长剧情或是 staff 表等。
 | 
			
		||||
- [Selection](../../api/user-client-modules/组件%20Selection.md):选择光标,列表组件的选择光标就是使用的本组件。
 | 
			
		||||
- [Background](../../api/user-client-modules/组件%20Background.md):背景组件,可以设置为纯色或 `winskin`。
 | 
			
		||||
- [WaitBox](../../api/user-client-modules/组件%20WaitBox.md):等待框,一般使用 `waitbox` 接口,不直接使用组件。
 | 
			
		||||
- [Page](../../api/user-client-modules/组件%20Page.md):分页组件,本文已经详细讲解。
 | 
			
		||||
- [Scroll](../../api/user-client-modules/组件%20Scroll.md):滚动条组件,本文已经详细讲解。
 | 
			
		||||
- [TextContent](../../api/user-client-modules/组件%20TextContent.md):多行文本组件,本文已经详细讲解。
 | 
			
		||||
- [Textbox](../../api/user-client-modules/组件%20Textbox.md):文本框组件,就是事件的显示文字,一般不会直接用。
 | 
			
		||||
- [Thumbnail](../../api/user-client-modules/组件%20Thumbnail.md):缩略图组件,用于展示某个地图的缩略图。
 | 
			
		||||
- [Tip](../../api/user-client-modules/组件%20Tip.md):提示组件,就是左上角的提示,一般不会直接使用。
 | 
			
		||||
@ -349,7 +349,7 @@ type RenderFn = (canvas: MotaOffscreenCanvas2D, transform: Transform) => void;
 | 
			
		||||
- `canvas`: 要渲染至的画布,一般直接将内容渲染至这个画布上
 | 
			
		||||
- `transform`: 当前元素的变换矩阵,相对于父元素,不常用
 | 
			
		||||
 | 
			
		||||
多数情况下,我们只会使用到第一个参数,`MotaOffscreenCanvas2D` 接口请参考 [API 文档](../api/motajs-render-core/index.md)。下面是一个典型案例:
 | 
			
		||||
多数情况下,我们只会使用到第一个参数,`MotaOffscreenCanvas2D` 接口请参考 [API 文档](../../api/motajs-render-core/index.md)。下面是一个典型案例:
 | 
			
		||||
 | 
			
		||||
```tsx
 | 
			
		||||
const render = (canvas: MotaOffscreenCanvas2D) => {
 | 
			
		||||
@ -753,4 +753,4 @@ const themeStyle = {
 | 
			
		||||
 | 
			
		||||
## API 参考
 | 
			
		||||
 | 
			
		||||
参考[API 文档](../api/motajs-render-vue/index.md),这里有更细致的 API 介绍。
 | 
			
		||||
参考[API 文档](../../api/motajs-render-vue/index.md),这里有更细致的 API 介绍。
 | 
			
		||||
@ -31,7 +31,7 @@ watch(data, () => mySprite.value?.update());
 | 
			
		||||
 | 
			
		||||
## 我的 UI 很卡
 | 
			
		||||
 | 
			
		||||
可能使用了平铺式布局,建议使用 `Scroll` 组件或者 `Page` 组件来对平铺内容分割,从而提高渲染效率。可以参考对应的 [API 文档](../api/user-client-modules/组件%20Scroll.md)。
 | 
			
		||||
可能使用了平铺式布局,建议使用 `Scroll` 组件或者 `Page` 组件来对平铺内容分割,从而提高渲染效率。可以参考对应的 [API 文档](../../api/user-client-modules/组件%20Scroll.md)。
 | 
			
		||||
 | 
			
		||||
## 玩着玩着突然黑屏了一下,然后画面就不显示了
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										17
									
								
								docs/guide/ui/index.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								docs/guide/ui/index.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,17 @@
 | 
			
		||||
# UI 系统指南
 | 
			
		||||
 | 
			
		||||
2.B 提供了强大的 UI 系统,可以让你更快地做出更好看的 UI。
 | 
			
		||||
 | 
			
		||||
## 热重载
 | 
			
		||||
 | 
			
		||||
2.B 对 UI 有热重载支持,当你修改了代码时,你可以不刷新游戏画面就看到 UI 的变化,可以省去大量时间。
 | 
			
		||||
 | 
			
		||||
## 指南目录
 | 
			
		||||
 | 
			
		||||
- [UI 编写](./ui.md):教你如何从头开始编写一个 UI,包括界面显示、交互等。
 | 
			
		||||
- [UI 元素](./elements.md):讲述所有常用的 UI 元素(标签),包括图片、图形、文字等。
 | 
			
		||||
- [组件使用指南](./component.md):教你如何使用一些常用组件。
 | 
			
		||||
- [优化性能](./perf.md):教你如何优化一个 UI 的性能表现。
 | 
			
		||||
- [UI 系统](./system.md):解释 UI 系统中 UI 控制器的工作原理,重点在于 UI 的打开与关闭。
 | 
			
		||||
- [常见问题](./faq.md):编写 UI 时的常见问题解答。
 | 
			
		||||
- [未来规划](./future.md):UI 系统的未来规划。
 | 
			
		||||
@ -45,7 +45,7 @@ lang: zh-CN
 | 
			
		||||
 | 
			
		||||
## 使用 `Scroll` 或 `Page` 组件优化平铺性能
 | 
			
		||||
 | 
			
		||||
在一些特殊情况下,我们不得不使用平铺布局,例如上一节提到的怪物手册,或是展示一个列表等,这时候必须平铺元素。这时候我们可以使用 `Scroll` 组件或 `Page` 组件来优化性能表现。`Scroll` 组件中,只有在画面内的元素会被渲染,而画面外的不会被渲染,这会大大提高渲染效率;`Page` 组件允许你把列表拆分成多个部分,然后把内容放在不同页中,从而提高渲染性能。极端情况下,`Page` 组件的渲染效率要明显高于 `Scroll` 组件,但是滚动条对于交互更友好,我们推荐在简单场景下使用 `Scroll` 组件,而对于复杂场景,换为 `Page` 组件。两个组件的使用方式可以参考 [API 文档](../api/motajs-render-elements/)。
 | 
			
		||||
在一些特殊情况下,我们不得不使用平铺布局,例如上一节提到的怪物手册,或是展示一个列表等,这时候必须平铺元素。这时候我们可以使用 `Scroll` 组件或 `Page` 组件来优化性能表现。`Scroll` 组件中,只有在画面内的元素会被渲染,而画面外的不会被渲染,这会大大提高渲染效率;`Page` 组件允许你把列表拆分成多个部分,然后把内容放在不同页中,从而提高渲染性能。极端情况下,`Page` 组件的渲染效率要明显高于 `Scroll` 组件,但是滚动条对于交互更友好,我们推荐在简单场景下使用 `Scroll` 组件,而对于复杂场景,换为 `Page` 组件。两个组件的使用方式可以参考 [API 文档](../../api/motajs-render-elements/)。
 | 
			
		||||
 | 
			
		||||
我们建议:
 | 
			
		||||
 | 
			
		||||
@ -3,7 +3,52 @@
 | 
			
		||||
本节将会讲解 2.B 的渲染树与 UI 系统的工作原理,以及一些常用 API。
 | 
			
		||||
 | 
			
		||||
:::info
 | 
			
		||||
**这部分可以选择性阅读,多数功能一般场景下用不到。**
 | 
			
		||||
**这部分可以选择性阅读,只有打开和关闭较为重要,其他功能一般场景下用不到。**
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
## 打开与关闭 UI
 | 
			
		||||
 | 
			
		||||
在 UI 编写章节已经提到了打开和关闭 UI 使用 `open` 和 `close` 方法,现在我们更细致地讲解一下如何打开与关闭 UI。打开 UI 使用 `open` 方法,定义如下:
 | 
			
		||||
 | 
			
		||||
```ts
 | 
			
		||||
function open<T extends UIComponent>(
 | 
			
		||||
    ui: IGameUI<T>,
 | 
			
		||||
    props: UIProps<T>,
 | 
			
		||||
    alwaysShow?: boolean
 | 
			
		||||
): IUIInstance;
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
其中第一个参数表示要打开的 UI,第二个表示传给 UI 的参数,第三个表示 UI 是否永远保持显示状态(除非被关闭),不受到显示模式的影响。同种 UI 可以打开多个,也可以在不同的控制器上同时打开多个相同的 UI。例如,如果我们想在主 UI 控制器中添加一个常量的返回游戏按钮,就可以这么写:
 | 
			
		||||
 | 
			
		||||
```ts
 | 
			
		||||
// BackToGame 是自定义 UI,第三个参数传 true 来保证它一直显示在画面上
 | 
			
		||||
mainUIController.open(BackToGame, {}, true);
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
关闭 UI 使用 `close` 方法,传入 UI 实例,即 `open` 方法的返回值,没有其他参数。例如:
 | 
			
		||||
 | 
			
		||||
```ts
 | 
			
		||||
const MyUI = defineComponent(props => {
 | 
			
		||||
    // 所有通过 UI 控制器打开的,同时按照 UI 模板填写了 props 的 UI 都包含 controller 和 instance 属性
 | 
			
		||||
    props.controller.close(props.instance);
 | 
			
		||||
}, myUIProps);
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
除此之外,还提供了一个关闭所有 UI 的:
 | 
			
		||||
 | 
			
		||||
```ts
 | 
			
		||||
function closeAll(ui?: IGameUI): void;
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
其中参数表示要关闭的 UI 类型,不填时表示关闭所有 UI,填写时表示关闭所有指定类型的 UI。例如我想关闭所有 `EnemyInfo` UI,可以这么写:
 | 
			
		||||
 | 
			
		||||
```ts
 | 
			
		||||
// EnemyInfo 是自定义 UI
 | 
			
		||||
mainUIController.closeAll(EnemyInfo);
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
:::warning
 | 
			
		||||
以下内容属于进阶内容,没有高级需求不需要理解。
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
## 创建一个自己的 UI 管理器
 | 
			
		||||
@ -149,47 +194,6 @@ keep.safelyUnload();
 | 
			
		||||
keep.unload();
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## 打开与关闭 UI
 | 
			
		||||
 | 
			
		||||
在 UI 编写章节已经提到了打开和关闭 UI 使用 `open` 和 `close` 方法,现在我们更细致地讲解一下如何打开与关闭 UI。打开 UI 使用 `open` 方法,定义如下:
 | 
			
		||||
 | 
			
		||||
```ts
 | 
			
		||||
function open<T extends UIComponent>(
 | 
			
		||||
    ui: IGameUI<T>,
 | 
			
		||||
    props: UIProps<T>,
 | 
			
		||||
    alwaysShow?: boolean
 | 
			
		||||
): IUIInstance;
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
其中第一个参数表示要打开的 UI,第二个表示传给 UI 的参数,第三个表示 UI 是否永远保持显示状态(除非被关闭),不受到显示模式的影响。同种 UI 可以打开多个,也可以在不同的控制器上同时打开多个相同的 UI。例如,如果我们想在主 UI 控制器中添加一个常量的返回游戏按钮,就可以这么写:
 | 
			
		||||
 | 
			
		||||
```ts
 | 
			
		||||
// BackToGame 是自定义 UI,第三个参数传 true 来保证它一直显示在画面上
 | 
			
		||||
myController.open(BackToGame, {}, true);
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
关闭 UI 使用 `close` 方法,传入 UI 实例,即 `open` 方法的返回值,没有其他参数。例如:
 | 
			
		||||
 | 
			
		||||
```ts
 | 
			
		||||
const MyUI = defineComponent(props => {
 | 
			
		||||
    // 所有通过 UI 控制器打开的,同时按照 UI 模板填写了 props 的 UI 都包含 controller 和 instance 属性
 | 
			
		||||
    props.controller.close(props.instance);
 | 
			
		||||
}, myUIProps);
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
除此之外,还提供了一个关闭所有 UI 的:
 | 
			
		||||
 | 
			
		||||
```ts
 | 
			
		||||
function closeAll(ui?: IGameUI): void;
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
其中参数表示要关闭的 UI 类型,不填时表示关闭所有 UI,填写时表示关闭所有指定类型的 UI。例如我想关闭所有 `EnemyInfo` UI,可以这么写:
 | 
			
		||||
 | 
			
		||||
```ts
 | 
			
		||||
// EnemyInfo 是自定义 UI
 | 
			
		||||
myController.closeAll(EnemyInfo);
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## 渲染系统的树结构
 | 
			
		||||
 | 
			
		||||
接下来我们来讲解一下渲染系统的一些工作原理。下面的部分由 `DeepSeek R1` 模型生成并稍作修改。
 | 
			
		||||
@ -58,7 +58,7 @@ return () => (
 | 
			
		||||
 | 
			
		||||
## 显示 UI
 | 
			
		||||
 | 
			
		||||
我们编写完 UI 之后,这个 UI 并不会自己显示,需要手动打开。我们找到 `ui/main.tsx`,在 `MainScene` 这个根组件中添加一句话:
 | 
			
		||||
我们编写完 UI 之后,这个 UI 并不会自己显示,需要手动打开。我们找到 `ui/main.tsx`,在 `MainScene` 这个根组件中调用 `mainUIController.open`:
 | 
			
		||||
 | 
			
		||||
```ts
 | 
			
		||||
// 在这添加引入
 | 
			
		||||
@ -68,7 +68,7 @@ const MainScene = defineComponent(() => {
 | 
			
		||||
    // ... 其他内容
 | 
			
		||||
    // 在这添加一句话,打开 UI,第二个参数为传入 UI 的参数,后面会有讲解
 | 
			
		||||
    // 纵深设为 100 以保证可以显示出来,纵深越大,元素越靠上,会覆盖纵深低的元素
 | 
			
		||||
    mainUIController.open(MyBookUI, { zIndex: 100 });
 | 
			
		||||
    mainUIController.open(MyBookUI, { zIndex: 100 }); // [!code ++]
 | 
			
		||||
    return () => (
 | 
			
		||||
        // ... 其他内容
 | 
			
		||||
    );
 | 
			
		||||
@ -80,7 +80,7 @@ const MainScene = defineComponent(() => {
 | 
			
		||||
```tsx
 | 
			
		||||
export const MyBook = defineComponent<MyBookProps>(props => {
 | 
			
		||||
    // 例如,我们可以让它在打开 10 秒钟后关闭:
 | 
			
		||||
    setTimeout(() => props.controller.close(props.instance), 10000);
 | 
			
		||||
    setTimeout(() => props.controller.close(props.instance), 10000); // [!code ++]
 | 
			
		||||
    return () => (
 | 
			
		||||
        // ... UI 内容
 | 
			
		||||
    );
 | 
			
		||||
@ -119,7 +119,9 @@ import { UIController } from '@motajs/system-ui';
 | 
			
		||||
const mainUIController = UIController.getController('main-ui');
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
更多的 UI 控制功能可以参考后续文档以及相关的 [UI 系统指南](./ui-system.md) 或 [API 文档](../api/motajs-system-ui/UIController)。
 | 
			
		||||
关于 UI 打开与关闭的细节参考[此文档](./system.md#打开与关闭-ui)
 | 
			
		||||
 | 
			
		||||
更多的 UI 控制功能可以参考后续文档以及相关的 [UI 系统指南](./system.md) 或 [API 文档](../../api/motajs-system-ui/UIController)。
 | 
			
		||||
 | 
			
		||||
## 添加更多内容
 | 
			
		||||
 | 
			
		||||
@ -169,7 +171,7 @@ return () => (
 | 
			
		||||
);
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
更多的字体使用方法可以参考 [API 文档](../api/motajs-render-style/Font)
 | 
			
		||||
更多的字体使用方法可以参考 [API 文档](../../api/motajs-render-style/Font)
 | 
			
		||||
 | 
			
		||||
### 圆角矩形
 | 
			
		||||
 | 
			
		||||
@ -820,7 +822,7 @@ watch(selected, () => {
 | 
			
		||||
 | 
			
		||||
## 修改 UI 参数
 | 
			
		||||
 | 
			
		||||
在打开 UI 时,我们可以传入参数,默认情况下,可以传入所有的 `BaseProps`,也就是所有元素通用属性,以及自己定义的 UI 参数。`BaseProps` 内容较多,可以参考 [API 文档](../api/motajs-render-core/RenderItem.md)。除此之外,我们还为这个自定义怪物手册添加了 `floorId` 参数,它也可以在打开 UI 时传入。如果需要打开的 UI 参数具有响应式,例如可以动态修改楼层 id,可以使用 `reactive` 方法。示例如下:
 | 
			
		||||
在打开 UI 时,我们可以传入参数,默认情况下,可以传入所有的 `BaseProps`,也就是所有元素通用属性,以及自己定义的 UI 参数。`BaseProps` 内容较多,可以参考 [API 文档](../../api/motajs-render-core/RenderItem.md)。除此之外,我们还为这个自定义怪物手册添加了 `floorId` 参数,它也可以在打开 UI 时传入。如果需要打开的 UI 参数具有响应式,例如可以动态修改楼层 id,可以使用 `reactive` 方法。示例如下:
 | 
			
		||||
 | 
			
		||||
```ts
 | 
			
		||||
import { MyBookProps, MyBookUI } from './myUI';
 | 
			
		||||
@ -1,4 +1,5 @@
 | 
			
		||||
export * from './choices';
 | 
			
		||||
export * from './floorSelect';
 | 
			
		||||
export * from './icons';
 | 
			
		||||
export * from './input';
 | 
			
		||||
export * from './list';
 | 
			
		||||
 | 
			
		||||
@ -517,4 +517,12 @@ export async function getInputNumber(
 | 
			
		||||
    return parseFloat(value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export async function routedInput() {
 | 
			
		||||
    // todo
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export async function routedInputNumber() {
 | 
			
		||||
    // todo
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const InputBoxUI = new GameUI('input-box', InputBox);
 | 
			
		||||
 | 
			
		||||
@ -230,12 +230,13 @@ export const Page = defineComponent<
 | 
			
		||||
                <container loc={contentLoc.value}>
 | 
			
		||||
                    {slots.default?.(nowPage.value)}
 | 
			
		||||
                </container>
 | 
			
		||||
                <container loc={pageLoc.value} hidden={hide.value}>
 | 
			
		||||
                <container loc={pageLoc.value} hidden={hide.value} nocache>
 | 
			
		||||
                    <container
 | 
			
		||||
                        key={1}
 | 
			
		||||
                        loc={leftLoc.value}
 | 
			
		||||
                        onClick={lastPage}
 | 
			
		||||
                        cursor="pointer"
 | 
			
		||||
                        nocache
 | 
			
		||||
                    >
 | 
			
		||||
                        <g-rectr
 | 
			
		||||
                            loc={rectLoc.value}
 | 
			
		||||
@ -257,6 +258,7 @@ export const Page = defineComponent<
 | 
			
		||||
                            loc={leftPageLoc.value}
 | 
			
		||||
                            onClick={lastPage}
 | 
			
		||||
                            cursor="pointer"
 | 
			
		||||
                            nocache
 | 
			
		||||
                        >
 | 
			
		||||
                            <g-rectr
 | 
			
		||||
                                loc={rectLoc.value}
 | 
			
		||||
@ -272,7 +274,7 @@ export const Page = defineComponent<
 | 
			
		||||
                            ></text>
 | 
			
		||||
                        </container>
 | 
			
		||||
                    )}
 | 
			
		||||
                    <container loc={nowPageLoc.value} key={3}>
 | 
			
		||||
                    <container loc={nowPageLoc.value} key={3} nocache>
 | 
			
		||||
                        <g-rectr
 | 
			
		||||
                            loc={rectLoc.value}
 | 
			
		||||
                            circle={[round.value]}
 | 
			
		||||
@ -295,6 +297,7 @@ export const Page = defineComponent<
 | 
			
		||||
                            loc={rightPageLoc.value}
 | 
			
		||||
                            onClick={nextPage}
 | 
			
		||||
                            cursor="pointer"
 | 
			
		||||
                            nocache
 | 
			
		||||
                        >
 | 
			
		||||
                            <g-rectr
 | 
			
		||||
                                loc={rectLoc.value}
 | 
			
		||||
@ -315,6 +318,7 @@ export const Page = defineComponent<
 | 
			
		||||
                        loc={rightLoc.value}
 | 
			
		||||
                        onClick={nextPage}
 | 
			
		||||
                        cursor="pointer"
 | 
			
		||||
                        nocache
 | 
			
		||||
                    >
 | 
			
		||||
                        <g-rectr
 | 
			
		||||
                            loc={rectLoc.value}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user