This commit is contained in:
AncTe 2025-06-25 15:43:42 +00:00 committed by GitHub
commit 8883eca285
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
822 changed files with 90192 additions and 28167 deletions

View File

@ -27,7 +27,7 @@ jobs:
run: |
npm i -g pnpm@7.27.0
pnpm i
pnpm build-gh
pnpm build
# 执行部署
- name: 部署

18
.gitignore vendored
View File

@ -35,4 +35,20 @@ index.cjs
!public/swap/*.h5save
_bundle
out
dist-resource
dist-resource
_temp
dam1.png
dam2.png
dam3.png
dam4.png
meeting.md
*.csv
script/special.ts
script/people.ts
user.ts
.antlr
graph.svg
docs/.vitepress/cache
docs/.vitepress/dist
docs/.vitepress/apiSidebar.ts

12
.madgerc Normal file
View File

@ -0,0 +1,12 @@
{
"fileExtensions": [
"ts",
"tsx"
],
"tsConfig": "./tsconfig.json",
"detectiveOptions": {
"ts": {
"skipTypeImports": true
}
}
}

View File

@ -5,4 +5,12 @@ public/project/floors/*.js
public/project/items.js
public/project/floors/*.js
public/project/maps.js
script/**/*.js
public/project/icons.js
public/project/enemys.js
public/_server/**/*.js
script/**/*.js
public/editor.html
keyCodes.ts
src/core/main/setting.ts
src/core/fx/shadow.ts
dist/

13
.prettierrc Normal file
View File

@ -0,0 +1,13 @@
{
"printWidth": 80,
"tabWidth": 4,
"useTabs": false,
"semi": true,
"singleQuote": true,
"quoteProps": "as-needed",
"bracketSpacing": true,
"vueIndentScriptAndStyle": false,
"arrowParens": "avoid",
"trailingComma": "none",
"endOfLine": "auto"
}

View File

@ -1,3 +1,9 @@
{
"recommendations": ["Vue.volar"]
"recommendations": [
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"vue.volar",
"slevesque.shader",
"tobermory.es6-string-html"
]
}

178
LICENSE
View File

@ -1,21 +1,165 @@
MIT License
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (c) 2023 unanmed
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.

3
components.d.ts vendored
View File

@ -7,7 +7,9 @@ export {}
declare module '@vue/runtime-core' {
export interface GlobalComponents {
AButton: typeof import('ant-design-vue/es')['Button']
ADivider: typeof import('ant-design-vue/es')['Divider']
AInput: typeof import('ant-design-vue/es')['Input']
AProgress: typeof import('ant-design-vue/es')['Progress']
ASelect: typeof import('ant-design-vue/es')['Select']
ASelectOption: typeof import('ant-design-vue/es')['SelectOption']
@ -17,6 +19,7 @@ declare module '@vue/runtime-core' {
BoxAnimate: typeof import('./src/components/boxAnimate.vue')['default']
Colomn: typeof import('./src/components/colomn.vue')['default']
EnemyOne: typeof import('./src/components/enemyOne.vue')['default']
Minimap: typeof import('./src/components/minimap.vue')['default']
Scroll: typeof import('./src/components/scroll.vue')['default']
}
}

97
docs/.vitepress/api.ts Normal file
View File

@ -0,0 +1,97 @@
import fs from 'fs-extra';
import path from 'path';
import chokidar from 'chokidar';
import { DefaultTheme } from 'vitepress';
const apiDir = path.resolve('./docs/api');
const sidebarConfigPath = path.resolve('./docs/.vitepress/apiSidebar.ts');
const weight: Record<string, number> = {
主页: 10,
函数: 5
};
function generateSidebar(): void {
const sidebar: DefaultTheme.SidebarItem[] = [
{ text: '目录', link: '/api/' }
];
// 遍历 api 目录,查找 package 目录
const packages = fs
.readdirSync(apiDir)
.filter(pkg => fs.statSync(path.join(apiDir, pkg)).isDirectory());
packages.forEach(pkg => {
const pkgPath = path.join(apiDir, pkg);
const files = fs
.readdirSync(pkgPath)
.filter(file => file.endsWith('.md'));
const items: DefaultTheme.SidebarItem[] = files.map(file => {
const filePath = `api/${pkg}/${file}`;
const fileName = path.basename(file, '.md');
return {
text:
fileName === 'index'
? '主页'
: fileName === 'functions'
? '函数'
: fileName,
link: `/${filePath.replace(/\\/g, '/')}` // 兼容 Windows 路径
};
});
items.sort((a, b) => {
const titleA = a.text ?? '';
const titleB = b.text ?? '';
return (weight[titleB] ?? 0) - (weight[titleA] ?? 0);
});
sidebar.push({
text: pkg,
collapsed: true,
items
});
});
// 生成 sidebar.ts
const sidebarContent = `import { DefaultTheme } from 'vitepress';
export default ${JSON.stringify(
sidebar,
null,
4
)} as DefaultTheme.SidebarItem[];`;
fs.writeFileSync(sidebarConfigPath, sidebarContent);
console.log('✅ Sidebar 配置已更新');
}
// 初次运行
generateSidebar();
// 监听文件变动
chokidar
.watch(apiDir, { ignoreInitial: true })
.on('add', filePath => {
console.log(`📄 文件新增: ${filePath}`);
generateSidebar();
})
.on('unlink', filePath => {
console.log(`❌ 文件删除: ${filePath}`);
generateSidebar();
})
.on('addDir', dirPath => {
console.log(`📁 目录新增: ${dirPath}`);
generateSidebar();
})
.on('unlinkDir', dirPath => {
console.log(`📁 目录删除: ${dirPath}`);
generateSidebar();
})
.on('raw', (event, path, details) => {
if (event === 'rename') {
console.log(`🔄 文件或文件夹重命名: ${path}`);
generateSidebar();
}
});

119
docs/.vitepress/config.ts Normal file
View File

@ -0,0 +1,119 @@
import { defineConfig } from 'vitepress';
import { MermaidMarkdown, MermaidPlugin } from 'vitepress-plugin-mermaid';
import api from './apiSidebar';
// https://vitepress.dev/reference/site-config
export default defineConfig({
title: 'HTML5 魔塔样板 V2.B',
description: 'HTML5 魔塔样板 V2.B 帮助文档',
base: '/_docs/',
markdown: {
math: true,
config(md) {
md.use(MermaidMarkdown);
}
},
themeConfig: {
// https://vitepress.dev/reference/default-theme-config
outline: [2, 3],
nav: [
{ text: '主页', link: '/' },
{ text: '指南', link: '/guide/diff' },
{ text: 'API', link: '/api/' },
{ text: '错误代码', link: '/logger/' }
],
sidebar: {
'/guide/': [
{
text: '深度指南',
items: [
{ text: '差异说明', link: '/guide/diff' },
{ text: '系统说明', link: '/guide/system' },
{ text: '代码编写', link: '/guide/coding' },
{
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/audio' }
]
}
],
'/logger/': [
{
text: '错误代码一览',
items: [
{
text: '错误代码',
collapsed: false,
items: [
{ text: '1-50', link: '/logger/error/error1' }
]
},
{
text: '警告代码',
collapsed: false,
items: [
{ text: '1-50', link: '/logger/warn/warn1' },
{ text: '51-100', link: '/logger/warn/warn2' }
]
}
]
}
],
'/api/': [
{
text: 'API 列表',
items: api
}
]
},
socialLinks: [
{ icon: 'github', link: 'https://github.com/unanmed/HumanBreak' }
],
search: {
provider: 'local',
options: {
locales: {
zh: {
translations: {
button: {
buttonText: '搜索文档',
buttonAriaLabel: '搜索文档'
},
modal: {
noResultsText: '无法找到相关结果',
resetButtonTitle: '清除查询条件',
footer: {
selectText: '选择',
navigateText: '切换'
}
}
}
}
}
}
}
},
locales: {
root: {
lang: 'zh',
label: '中文'
}
},
vite: {
plugins: [MermaidPlugin()],
optimizeDeps: {
include: ['mermaid']
},
ssr: {
noExternal: ['mermaid']
}
}
});

View File

@ -0,0 +1,7 @@
.mermaid {
max-width: 600px; /* 限制最大宽度 */
max-height: 400px; /* 限制最大高度 */
overflow: auto; /* 允许滚动以防止超出 */
display: block;
margin: 0 auto;
}

32
docs/api/index.md Normal file
View File

@ -0,0 +1,32 @@
---
lang: zh-CN
---
# API 列表
- [@motajs/client](./motajs-client) 渲染层代码
- [@motajs/client-base](./motajs-client-base) 渲染层底层代码
- [@motajs/common](./motajs-common) 渲染层和数据层通用代码
- [@motajs/legacy-client](./motajs-legacy-client) 遗留渲染层代码
- [@motajs/legacy-common](./motajs-legacy-common) 遗留通用代码
- [@motajs/legacy-data](./motajs-legacy-data) 遗留数据层代码
- [@motajs/legacy-system](./motajs-legacy-system) 遗留渲染层系统代码
- [@motajs/legacy-ui](./motajs-legacy-ui) 遗留 UI 相关代码
- [@motajs/render](./motajs-render) 渲染系统代码
- [@motajs/render-core](./motajs-render-core) 渲染系统核心代码
- [@motajs/render-elements](./motajs-render-elements) 渲染系统内置元素代码
- [@motajs/render-style](./motajs-render-style) 渲染系统样式代码
- [@motajs/render-vue](./motajs-render-vue) 渲染系统 vue 支持代码
- [@motajs/system](./motajs-system) 渲染层系统代码
- [@motajs/system-action](./motajs-system-action) 渲染层交互系统代码
- [@motajs/system-ui](./motajs-system-ui) 渲染层 UI 系统代码
- [@motajs/types](./motajs-types) 渲染层类型代码
- [@user/client-modules](./user-client-modules) 用户渲染层主要代码
- [@user/data-base](./user-data-base) 用户数据层底层代码
- [@user/data-fallback](./user-data-fallback) 用户数据层向后兼容代码
- [@user/data-state](./user-data-state) 用户数据层状态代码
- [@user/data-utils](./user-data-utils) 用户数据层工具代码
- [@user/entry-client](./user-entry-client) 用户渲染层入口
- [@user/entry-data](./user-entry-data) 用户数据层入口
- [@user/legacy-plugin-client](./user-legacy-plugin-client) 用户遗留渲染层代码
- [@user/legacy-plugin-data](./user-legacy-plugin-data) 用户遗留数据层代码

View File

@ -0,0 +1,3 @@
# KeyCode
参考 `monaco-editor` 文档 [KeyCode](https://microsoft.github.io/monaco-editor/docs.html#enums/KeyCode.html)

View File

@ -0,0 +1,5 @@
# @motajs/client-base
目录:
- [KeyCode](./KeyCode.md)

View File

@ -0,0 +1,13 @@
# @motajs/client
`@motajs/client` 包含多个模块:
- [`@motajs/client-base`](../motajs-client-base/)
示例:
```ts
import { KeyCode } from '@motajs/client';
const { KeyCOde } = Mota.require('@motajs/client');
```

View File

@ -0,0 +1,212 @@
# Logger
本文档由 `DeepSeek R1` 模型生成并微调。
## 属性说明
| 属性名 | 类型 | 默认值 | 说明 |
| --------- | ------------- | ------ | ---------------------------------------------------------------- |
| `enabled` | `boolean` | `true` | 控制日志输出是否启用。设为 `false` 可临时关闭日志输出。 |
| `level` | `LogLevel` | - | 日志级别,决定输出的最低日志等级(通过构造函数传入,不可修改)。 |
| `info` | `ILoggerInfo` | - | 包含错误和警告信息的配置对象(通过构造函数传入,不可修改)。 |
## 方法说明
### `constructor`
```ts
function constructor(level: LogLevel, info: ILoggerInfo): Logger;
```
#### 描述
构造一个 `Logger` 实例。
#### 参数
- `level`: 日志对象输出等级。
- `info`: 日志内容。
### `error`
```ts
function error(code: number, ...params: string[]): void;
```
#### 描述
记录一个错误信息。
#### 参数
- `code`: 错误代码,对应 `info.error` 中的键值。
- `...params`: 替换错误信息中的占位符(如 $1, $2的参数。
#### 行为
- 如果未找到对应 `code` 的错误信息,会触发 `error(16)` 表示代码未定义。
- 根据日志级别 `level` 决定是否输出到控制台
### `warn`
```ts
function warn(code: number, ...params: string[]): void;
```
#### 描述
记录一个警告信息。
#### 参数
- `code`: 警告代码,对应 `info.warn` 中的键值。
- `...params`: 替换警告信息中的占位符的参数。
#### 行为
- 如果未找到对应 `code` 的警告信息,会触发 `error(16)`
- 仅在 `level <= LogLevel.WARNING` 时输出。
### `log`
```ts
function log(text: string): void;
```
#### 描述
记录一条普通日志。
#### 参数
`text`: 日志文本内容。
#### 行为
- 仅在 `level <= LogLevel.LOG` 时输出到控制台。
### `catch`
```ts
function catch<T>(fn: () => T): LoggerCatchReturns<T>;
```
#### 描述
捕获函数执行期间产生的日志信息,并抑制日志输出。
#### 参数
- `fn`: 需要执行的函数。
#### 返回值
- `ret`: 函数 `fn` 的返回值。
- `info`: 捕获的日志信息数组。
#### 行为
- 执行期间会临时禁用日志输出,执行完成后恢复原有状态。
### `disable`
```ts
function disable(): void;
```
#### 描述
禁用日志输出(设置 `enabled = false`)。
### `enable`
```ts
function enable(): void;
```
#### 描述
启用日志输出(设置 `enabled = true`)。
## 接口说明
### `LoggerCatchInfo`
#### 结构
```ts
interface LoggerCatchInfo {
/** 错误/警告代码(仅 error/warn 方法存在) */
code?: number;
/** 日志等级 */
level: LogLevel;
/** 解析后的完整信息 */
message: string;
}
```
### `LoggerCatchReturns<T>`
#### 结构
```ts
interface LoggerCatchReturns<T> {
/** 被捕获函数的返回值 */
ret: T;
/** 捕获的日志信息列表 */
info: LoggerCatchInfo[];
}
```
## 使用示例
- 初始化 Logger
```ts
import { LogLevel, Logger } from './logger';
const logInfo = {
error: {
404: 'Page $1 not found.',
500: 'Internal server error: $1'
},
warn: {
101: 'Deprecated API: $1'
}
};
const logger = new Logger(LogLevel.WARNING, logInfo);
```
- 记录错误
```ts
logger.error(404, 'home');
// 控制台输出: [ERROR Code 404] Page home not found.
```
- 记录警告
```ts
logger.warn(101, '/old-api');
// 控制台输出: [WARNING Code 101] Deprecated API: /old-api
```
- 捕获日志
```ts
const result = logger.catch(() => {
logger.error(500, 'database timeout');
return { success: false };
});
console.log(result.info[0].message); // "Internal server error: database timeout"
```
- 禁用日志
```ts
logger.disable();
logger.log('This will not be printed'); // 无输出
logger.enable();
```

View File

@ -0,0 +1,24 @@
# @motajs/common 函数
## `sleep`
```ts
function sleep(time: number): Promise<void>;
```
#### 描述
创建一个等待指定时长的异步。
#### 参数
- `time`: 等待时长
#### 使用示例
```ts
async function myFunc() {
await sleep(1000);
// 这后面的内容会在 1 秒之后执行
}
```

View File

@ -0,0 +1,11 @@
# @motajs/common
目录:
- [函数](./functions.md)
---
类目录:
- [Logger](./Logger.md)

View File

@ -0,0 +1,3 @@
# @motajs/legacy-client
目录:

View File

@ -0,0 +1,120 @@
# Patch API 文档
本文档由 `DeepSeek R1` 模型生成并微调。
## 类描述
`Patch` 类用于对旧版接口的函数实现进行动态重写,支持按模块类别批量修改目标类的原型方法。需配合 `PatchClass` 枚举指定要修改的模块类型。
---
## 泛型说明
- `T extends PatchClass`: 表示要修改的模块类别(如 `PatchClass.Actions` 对应动作模块)
---
## 属性说明
| 属性名 | 类型 | 描述 |
| ------------ | ---- | ---------------------------- |
| `patchClass` | `T` | 只读,当前补丁关联的模块类别 |
---
## 构造方法
```typescript
function constructor<T extends PatchClass>(patchClass: T): Patch<T>;
```
- **参数**
- `patchClass`: 指定要修改的模块类别(从 `PatchClass` 枚举中选择)
**示例**
```typescript
// 创建针对控制模块的补丁
const patch = new Patch(PatchClass.Control);
```
---
## 方法说明
### `add`
```typescript
function add<K extends keyof PatchList[T]>(
key: K,
patch: PatchList[T][K]
): void;
```
为目标模块添加函数补丁。
- **参数**
- `key`: 要修改的函数名(需为目标模块原型存在的函数)
- `patch`: 新的函数实现
**示例**
```typescript
// 重写控制模块的 setFlag 方法
control.add('setFlag', function (this: Control, key, value) {
console.log('执行重写后的 setFlag 代码');
if (typeof value === 'number') {
// 数字额外增加 100 点
core.status.hero.flags[key] = value + 100;
} else {
core.status.hero.flags[key] = value;
}
});
```
---
### `Patch.patchAll`
```typescript
function patchAll(): void;
```
**静态方法**:应用所有未执行的补丁修改。一般不需要自己调用,游戏启动阶段已经包含了此方法的调用。
---
### `Patch.patch`
```typescript
function patch(patch: Patch<PatchClass>): void;
```
**静态方法**:立即应用指定补丁实例的修改。一般不需要自己调用,游戏启动阶段已经包含了此方法的调用。
- **参数**
- `patch`: 要应用的补丁实例
---
## 总使用示例
```typescript
import { Patch, PatchClass } from '@motajs/legacy-common';
// 新建函数,这个操作是必要的,我们不能直接在顶层使用这个接口
export function patchMyFunctions() {
// 创建 Patch 实例,参数表示这个 Patch 示例要重写哪个文件中的函数
// 如果需要复写两个文件,那么就需要创建两个实例
const patch = new Patch(PatchClass.Control);
// 使用 add 函数来重写,第一个参数会有自动补全
// 如果要重写的函数以下划线开头,可能会有报错
// 这时候需要去 types/declaration 中对应的文件中添加声明
patch.add('getFlag', (name, defaultValue) => {
// 重写 getFlag如果变量是数字那么 +100 后返回
const value = core.status?.hero?.flags[name] ?? defaultValue;
return typeof value === 'number' ? value + 100 : value;
});
}
```

View File

@ -0,0 +1,3 @@
# @motajs/legacy-common
目录:

View File

@ -0,0 +1,3 @@
# @motajs/legacy-system
目录:

View File

@ -0,0 +1,3 @@
# @motajs/legacy-ui
目录:

View File

@ -0,0 +1,121 @@
# Container 类 API 文档
本文档由 `DeepSeek R1` 模型生成并微调。
---
## 继承关系
```mermaid
graph LR
Container --> RenderItem --> EventEmitter
click RenderItem "./RenderItem"
click EventEmitter "https://nodejs.org/api/events.html#class-eventemitter"
```
## 属性说明
| 属性名 | 类型 | 默认值 | 说明 |
| ---------------- | -------------- | ------ | ------------------------------ |
| `sortedChildren` | `RenderItem[]` | `[]` | 按 `zIndex` 排序后的子元素列表 |
---
## 构造方法
### `constructor`
**参数**
- `type`: 渲染模式(`absolute` 绝对定位 / `static` 跟随摄像机)
- `cache`: 是否启用渲染缓存
- `fall`: 是否启用变换矩阵下穿机制
**示例**
```typescript
const container = new Container('static');
```
---
## 方法说明
### `appendChild`
```typescript
function appendChild(...children: RenderItem[]): void;
```
**描述**
添加子元素并触发重新排序。
**示例**
```typescript
const child = new RenderItem('static');
container.appendChild(child); // 添加子元素
```
---
### `removeChild`
```typescript
function removeChild(...child: RenderItem[]): void;
```
**描述**
移除指定子元素并触发重新排序。
**示例**
```typescript
container.removeChild(child); // 移除子元素
```
---
### `requestSort`
```typescript
function requestSort(): void;
```
**描述**
标记需要重新排序子元素(在下一帧前自动执行)。
---
### `forEachChild`
```typescript
function forEachChild(fn: (ele: RenderItem) => void): void;
```
**描述**
遍历元素的每一个子元素DFS 遍历),并对每一个元素执行函数。
---
## 总使用示例
```typescript
// 创建基础容器
const baseContainer = new Container('absolute');
baseContainer.size(800, 600);
// 添加子元素
const sprite1 = new Sprite('static');
sprite1.pos(100, 100).setZIndex(2);
baseContainer.appendChild(sprite1);
const sprite2 = new Sprite('static');
sprite2.pos(200, 200).setZIndex(1);
baseContainer.appendChild(sprite2);
// 将容器添加到根元素
rootElement.appendChild(baseContainer);
// 动态修改子元素层级
sprite1.setZIndex(0); // 自动触发重新排序
```

View File

@ -0,0 +1,71 @@
# ContainerCustom 类 API 文档
本文档由 `DeepSeek R1` 模型生成并微调。
---
## 继承关系
```mermaid
graph LR
ContainerCustom --> Container --> RenderItem --> EventEmitter
click Container "./Container"
click RenderItem "./RenderItem"
click EventEmitter "https://nodejs.org/api/events.html#class-eventemitter"
```
---
## 属性说明
| 属性名 | 类型 | 默认值 | 说明 |
| ---------- | ------------------------- | ----------- | ---------------------- |
| `renderFn` | `CustomContainerRenderFn` | `undefined` | 自定义渲染函数(可选) |
---
## 构造方法
继承自 `Container`,参数与父类一致。
---
## 方法说明
### `setRenderFn`
```typescript
function setRenderFn(render?: CustomContainerRenderFn): void;
```
**描述**
设置自定义渲染函数,覆盖默认的子元素渲染逻辑。
**参数**
- `render`: 接收画布、子元素列表和变换矩阵的回调函数
**示例**
```typescript
customContainer.setRenderFn((canvas, children, transform) => {
children.forEach(child => {
child.renderContent(canvas, transform);
});
});
```
---
## 总使用示例
```ts
// 创建自定义容器
const customContainer = new ContainerCustom('static');
customContainer.setRenderFn((canvas, children) => {
// 倒序渲染子元素
children.reverse().forEach(child => {
child.renderContent(canvas, Transform.identity);
});
});
```

View File

@ -0,0 +1,201 @@
# Event 模块 API 文档
以下内容由 `DeepSeek R1` 模型生成并微调。
---
## 枚举说明
### MouseType
| 值 | 说明 |
| --------- | ---------------- |
| `None` | 没有按键按下 |
| `Left` | 左键 |
| `Middle` | 中键(按下滚轮) |
| `Right` | 右键 |
| `Back` | 侧键后退 |
| `Forward` | 侧键前进 |
### WheelType
| 值 | 说明 |
| ------- | -------------------------- |
| `None` | 无单位 |
| `Pixel` | 以像素为单位 |
| `Line` | 以行为单位(约 1rem |
| `Page` | 以页为单位(一个屏幕高度) |
### ActionType
| 值 | 说明 |
| ------- | -------------------------------- |
| `Click` | 点击事件(按下与抬起在同一元素) |
| `Down` | 鼠标或手指按下事件 |
| `Move` | 鼠标或手指移动事件 |
| `Up` | 鼠标或手指抬起事件 |
| `Enter` | 进入元素时触发 |
| `Leave` | 离开元素时触发 |
| `Wheel` | 滚轮事件 |
### EventProgress
| 值 | 说明 |
| --------- | -------- |
| `Capture` | 捕获阶段 |
| `Bubble` | 冒泡阶段 |
---
## 接口说明
### IActionEventBase
| 属性名 | 类型 | 说明 |
| ---------- | ------------ | ----------------------------------------------------------------- |
| `target` | `RenderItem` | 触发事件的元素 |
| `touch` | `boolean` | 是否为触摸操作(`true` 表示触摸,`false` 表示鼠标) |
| `type` | `MouseType` | 触发事件的按键类型(参考 `MouseType` |
| `buttons` | `number` | 当前按下的按键(通过位运算判断,例如 `buttons & MouseType.Left` |
| `altKey` | `boolean` | 是否按下 `Alt` 键 |
| `shiftKey` | `boolean` | 是否按下 `Shift` 键 |
| `ctrlKey` | `boolean` | 是否按下 `Ctrl` 键 |
| `metaKey` | `boolean` | 是否按下 `Windows/Command` 键 |
---
### IActionEvent
#### 继承关系
```mermaid
graph LR
IActionEvent --> IActionEventBase
```
| 属性名 | 类型 | 说明 |
| ------------ | -------- | -------------------------------------------- |
| `identifier` | `number` | 操作的唯一标识符(在按下、移动、抬起中一致) |
| `offsetX` | `number` | 相对于元素左上角的横坐标 |
| `offsetY` | `number` | 相对于元素左上角的纵坐标 |
| `absoluteX` | `number` | 相对于整个画布左上角的横坐标 |
| `absoluteY` | `number` | 相对于整个画布左上角的纵坐标 |
#### 方法说明
##### `stopPropagation`
```typescript
function stopPropagation(): void;
```
**描述**
停止事件的传播(捕获或冒泡阶段)。
**示例**
```typescript
item.on('click', ev => {
ev.stopPropagation(); // 阻止事件继续传播
});
```
---
### IWheelEvent
```mermaid
graph LR
IWheelEvent --> IActionEvent --> IActionEventBase
```
| 属性名 | 类型 | 说明 |
| ----------- | ----------- | -------------------- |
| `wheelX` | `number` | 横向滚动量 |
| `wheelY` | `number` | 纵向滚动量 |
| `wheelZ` | `number` | 垂直屏幕方向的滚动量 |
| `wheelType` | `WheelType` | 滚动量的单位类型 |
---
### ERenderItemActionEvent
描述了所有的交互事件类型。
| 事件名 | 参数类型 | 说明 |
| -------------- | ---------------------------- | ------------------ |
| `clickCapture` | `Readonly<IActionEvent>` | 点击事件的捕获阶段 |
| `click` | `Readonly<IActionEvent>` | 点击事件的冒泡阶段 |
| `downCapture` | `Readonly<IActionEvent>` | 按下事件的捕获阶段 |
| `down` | `Readonly<IActionEvent>` | 按下事件的冒泡阶段 |
| `moveCapture` | `Readonly<IActionEvent>` | 移动事件的捕获阶段 |
| `move` | `Readonly<IActionEvent>` | 移动事件的冒泡阶段 |
| `upCapture` | `Readonly<IActionEvent>` | 抬起事件的捕获阶段 |
| `up` | `Readonly<IActionEvent>` | 抬起事件的冒泡阶段 |
| `enter` | `Readonly<IActionEventBase>` | 进入元素事件 |
| `leave` | `Readonly<IActionEventBase>` | 离开元素事件 |
| `wheelCapture` | `Readonly<IWheelEvent>` | 滚轮事件的捕获阶段 |
| `wheel` | `Readonly<IWheelEvent>` | 滚轮事件的冒泡阶段 |
---
### ActionEventMap
| 键ActionType | 值类型 | 说明 |
| ---------------- | -------------- | ------------ |
| `Click` | `IActionEvent` | 点击事件 |
| `Down` | `IActionEvent` | 按下事件 |
| `Enter` | `IActionEvent` | 进入元素事件 |
| `Leave` | `IActionEvent` | 离开元素事件 |
| `Move` | `IActionEvent` | 移动事件 |
| `Up` | `IActionEvent` | 抬起事件 |
| `Wheel` | `IWheelEvent` | 滚轮事件 |
---
## 总使用示例
::: code-group
```typescript
// 创建渲染元素(以 Sprite 为例)
const item = new Sprite();
// 监听点击事件(冒泡阶段)
item.on('click', ev => {
console.log('点击坐标:', ev.offsetX, ev.offsetY);
ev.stopPropagation(); // 阻止冒泡
});
// 监听滚轮事件(捕获阶段)
item.on('wheelCapture', ev => {
console.log('滚轮滚动量:', ev.wheelY, '单位:', WheelType[ev.wheelType]);
});
// 监听进入元素事件
item.on('enter', ev => {
console.log('进入元素,触发按键:', MouseType[ev.type]);
});
```
```tsx
// 监听点击事件(冒泡阶段)
const click = (ev: IActionEvent) => {
console.log('点击坐标:', ev.offsetX, ev.offsetY);
ev.stopPropagation(); // 阻止冒泡
};
// 监听滚轮事件(捕获阶段)
const wheel = (ev: IWheelEvent) => {
console.log('滚轮滚动量:', ev.wheelY, '单位:', WheelType[ev.wheelType]);
};
// 监听进入元素事件
const enter = (ev: IActionEventBase) => {
console.log('进入元素,触发按键:', MouseType[ev.type]);
};
<sprite onClick={click} onWheelCapture={wheel} onEnter={enter} />;
```
:::

View File

@ -0,0 +1,151 @@
# GL2 类 API 文档
**需丰富**
本文档由 `DeepSeek R1` 模型生成并微调。
## 继承关系
```mermaid
graph LR
GL2 --> RenderItem --> EventEmitter
click RenderItem "./RenderItem"
click EventEmitter "https://nodejs.org/api/events.html#class-eventemitter"
```
---
## 属性说明
| 属性名 | 类型 | 默认值 | 说明 |
| ------------------------------- | ------------------------ | ------------------ | --------------------------------------------- |
| `support` | `boolean`(静态) | 检测 WebGL2 支持性 | 标识当前环境是否支持 WebGL2 |
| `canvas` | `HTMLCanvasElement` | - | 绑定的 WebGL2 画布元素 |
| `gl` | `WebGL2RenderingContext` | - | WebGL2 渲染上下文 |
| `UNIFORM_1f` ~ `UNIFORM_4uiv` | `UniformType` 枚举 | 对应枚举值 | WebGL uniform 类型常量(共 25 种) |
| `U_MATRIX_2x2` ~ `U_MATRIX_4x4` | `UniformMatrix` 枚举 | 对应枚举值 | 矩阵类型 uniform 常量9 种) |
| `ATTRIB_1f` ~ `ATTRIB_I4uiv` | `AttribType` 枚举 | 对应枚举值 | 顶点属性类型常量12 种) |
| `MAX_TEXTURE_COUNT` | `number` | `0` | 最大纹理支持数量(实际值由 WebGL 上下文决定) |
---
## 构造方法
### `constructor`
**参数**
- `type`: 渲染模式(`absolute` 绝对定位 / `static` 跟随摄像机)
**行为**
- 初始化 WebGL2 上下文
- 自动检测 WebGL2 支持性(通过静态属性 `support`
- 设置默认渲染模式
---
## 方法说明
### `createProgram`
```typescript
function createProgram<T extends GL2Program>(
Program: ProgramConstructor<T>,
vs?: string,
fs?: string
): T;
```
**描述**
创建 WebGL 着色器程序
**参数**
- `Program`: 着色器程序类(需继承 `GL2Program`
- `vs`: 自定义顶点着色器代码(可选)
- `fs`: 自定义片元着色器代码(可选)
**示例**
```typescript
class MyProgram extends GL2Program {}
const program = gl2.createProgram(MyProgram);
```
---
### `useProgram`
```typescript
function useProgram(program: GL2Program): void;
```
**描述**
切换当前使用的着色器程序
**示例**
```typescript
gl2.useProgram(shaderProgram);
```
---
### `framebuffer`
```typescript
function framebuffer(
name: string,
texture: IShaderTexture2D,
clear?: boolean
): void;
```
**描述**
将渲染结果输出到帧缓冲纹理
**参数**
- `name`: 帧缓冲名称
- `texture`: 目标纹理对象
- `clear`: 是否清空画布
---
### `drawScene`(抽象方法)
```typescript
function drawScene(
canvas: MotaOffscreenCanvas2D,
gl: WebGL2RenderingContext,
program: GL2Program,
transform: Transform
): void;
```
**描述**
抽象渲染方法,子类必须实现具体绘制逻辑
---
## 静态方法说明
### `GL2.support`
```typescript
static readonly support: boolean;
```
**描述**
静态只读属性,检测 WebGL2 支持性
**示例**
```typescript
if (GL2.support) {
// 初始化 WebGL2 功能
}
```
---
## 总使用示例
暂时没有。

View File

@ -0,0 +1,188 @@
# GL2Program 类 API 文档
**需丰富**
本文档由 `DeepSeek R1` 模型生成并微调。
---
## 继承关系
```mermaid
graph LR
GL2Program --> EventEmitter
click EventEmitter "https://nodejs.org/api/events.html#class-eventemitter"
```
---
## 属性说明
| 属性名 | 类型 | 说明 |
| -------------- | ------------------------ | ------------------------------------------ |
| `gl` | `WebGL2RenderingContext` | WebGL2 渲染上下文 |
| `element` | `GL2` | 关联的 GL2 渲染元素 |
| `program` | `WebGLProgram \| null` | WebGL 着色器程序对象 |
| `renderMode` | `RenderMode` | 当前渲染模式(默认 `RenderMode.Elements` |
| `usingIndices` | `IShaderIndices \| null` | 当前使用的顶点索引数组 |
---
## 方法说明
### `defineUniform`
```typescript
function defineUniform<T extends UniformType>(
uniform: string,
type: T
): IShaderUniform<T> | null;
```
**描述**
定义 Uniform 变量
**参数**
- `uniform`: Uniform 变量名
- `type`: Uniform 类型(如 `GL2.UNIFORM_2f`
**返回值**
- 操作对象(可设置值)或 `null`(定义失败)
---
### `defineTexture`
```typescript
function defineTexture(
name: string,
index: number,
w?: number,
h?: number
): IShaderTexture2D | null;
```
**描述**
定义纹理对象
**参数**
- `name`: 纹理名称
- `index`: 纹理索引(建议不超过 8
- `w`: 纹理宽度(可选)
- `h`: 纹理高度(可选)
**示例**
```typescript
const tex = program.defineTexture('diffuse', 0, 512, 512);
```
---
### `paramElements`
```typescript
function paramElements(
mode: GLenum,
count: number,
type: GLenum,
offset: number
): void;
```
**描述**
设置元素模式渲染参数
**参数**
- `mode`: 渲染模式(如 `gl.TRIANGLES`
- `count`: 元素数量
- `type`: 数据类型(如 `gl.UNSIGNED_SHORT`
- `offset`: 数据偏移量
---
### `requestCompile`
```typescript
function requestCompile(force?: boolean): boolean;
```
**描述**
请求编译着色器
**参数**
- `force`: 是否强制重新编译
**返回值**
- `true` 表示编译成功
---
### `vs`
```typescript
function vs(vs: string): void;
```
**描述**
设置顶点着色器代码
**示例**
```typescript
program.vs(`
${GL2_PREFIX.VERTEX}
in vec4 aPosition;
void main() {
gl_Position = aPosition;
}
`);
```
---
## 事件说明
| 事件名 | 触发时机 | 参数类型 |
| -------- | ---------------- | -------- |
| `load` | 程序被加载使用时 | `[]` |
| `unload` | 程序被卸载时 | `[]` |
---
## 总使用示例
```typescript
// 创建着色器程序
const program = gl2.createProgram(GL2Program);
// 定义着色器
program.vs(`
${GL2_PREFIX.VERTEX}
uniform mat4 uProjection;
in vec4 aPosition;
void main() {
gl_Position = uProjection * aPosition;
}
`);
program.fs(`
${GL2_PREFIX.FRAGMENT}
out vec4 fragColor;
uniform vec3 uColor;
void main() {
fragColor = vec4(uColor, 1.0);
}
`);
// 定义 Uniform 和纹理
const colorUniform = program.defineUniform('uColor', UniformType.Uniform3f);
const diffuseTex = program.defineTexture('diffuse', 0, 512, 512);
// 设置渲染参数
program.paramElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
// 编译并应用
if (program.requestCompile()) {
gl2.useProgram(program);
colorUniform?.set(1.0, 0.5, 0.2);
diffuseTex?.set(imageElement);
}
```

View File

@ -0,0 +1,311 @@
# MotaOffscreenCanvas2D 类 API 文档
以下内容由 `DeepSeek R1` 模型生成并微调。
---
## 继承关系
```mermaid
graph LR
MotaOffscreenCanvas2D --> EventEmitter
click EventEmitter "https://nodejs.org/api/events.html#class-eventemitter"
```
---
## 属性说明
| 属性名 | 类型 | 默认值 | 说明 |
| ---------------- | -------------------------- | -------- | ------------------------------------------- |
| `canvas` | `HTMLCanvasElement` | - | 关联的 HTML 画布元素 |
| `ctx` | `CanvasRenderingContext2D` | - | 画布的 2D 渲染上下文 |
| `width` | `number` | 自动计算 | 画布的逻辑宽度(不包含缩放比例) |
| `height` | `number` | 自动计算 | 画布的逻辑高度(不包含缩放比例) |
| `autoScale` | `boolean` | `false` | 是否自动跟随 `core.domStyle.scale` 进行缩放 |
| `highResolution` | `boolean` | `true` | 是否启用高清画布(根据设备像素比例缩放) |
| `antiAliasing` | `boolean` | `true` | 是否启用抗锯齿 |
| `scale` | `number` | `1` | 当前画布的缩放比例 |
| `symbol` | `number` | `0` | 更新标识符,值变化表示画布被被动清空或调整 |
| `freezed` | `boolean`(只读) | `false` | 当前画布是否被冻结(冻结后不可修改属性) |
| `active` | `boolean`(只读) | `true` | 当前画布是否处于激活状态 |
---
## 构造方法
### `constructor`
```ts
function constructor(
alpha: boolean = true,
canvas?: HTMLCanvasElement
): MotaOffscreenCanvas2D;
```
**描述**
创建一个新的离屏画布。
**参数**
- `alpha`: 是否启用透明度通道(默认为 `true`)。
- `canvas`: 可指定现有画布,未提供时自动创建新画布。
**注意**
- 在自定义渲染元素中,建议使用 `RenderItem.requireCanvas` 而非直接调用此构造函数。
---
## 方法说明
### `size`
```ts
function size(width: number, height: number): void;
```
**描述**
设置画布的尺寸。
**参数**
- `width`: 逻辑宽度(最小为 1
- `height`: 逻辑高度(最小为 1
**行为**
- 自动计算缩放比例(考虑 `highResolution``autoScale`)。
- 调整画布物理尺寸和样式尺寸。
**示例**
```typescript
const canvas = new MotaOffscreenCanvas2D();
canvas.size(800, 600); // 设置画布尺寸为 800x600逻辑尺寸
```
---
### `withGameScale`
```ts
function withGameScale(auto: boolean): void;
```
**描述**
设置画布是否跟随 `core.domStyle.scale` 自动缩放。
**参数**
- `auto`: 是否启用自动缩放。
**示例**
```typescript
canvas.withGameScale(true); // 启用自动缩放
```
---
### `setHD`
```ts
function setHD(hd: boolean): void;
```
**描述**
设置是否为高清画布(基于设备像素比例)。
**参数**
- `hd`: 是否启用高清模式。
**示例**
```typescript
canvas.setHD(false); // 关闭高清模式
```
---
### `setAntiAliasing`
```ts
function setAntiAliasing(anti: boolean): void;
```
**描述**
设置抗锯齿功能。
**参数**
- `anti`: 是否启用抗锯齿。
**示例**
```typescript
canvas.setAntiAliasing(false); // 关闭抗锯齿
```
---
### `clear`
```ts
function clear(): void;
```
**描述**
清空画布内容。
**注意**
- 冻结状态下调用此方法会触发警告。
**示例**
```typescript
canvas.clear(); // 清空画布
```
---
### `delete`
```ts
function delete(): void
```
**描述**
删除画布,释放资源并解除 DOM 绑定。
**示例**
```typescript
canvas.delete(); // 删除画布
```
---
### `freeze`
```ts
function freeze(): void;
```
**描述**
冻结画布,禁止修改属性,并从全局列表中移除。
**示例**
```typescript
canvas.freeze(); // 冻结画布
```
---
### `activate`
```ts
function activate(): void;
```
**描述**
激活画布,使其跟随游戏缩放调整尺寸。
**示例**
```typescript
canvas.activate(); // 激活画布
```
---
### `deactivate`
```ts
function deactivate(): void;
```
**描述**
停用画布,不再自动调整尺寸,可能被垃圾回收。
**示例**
```typescript
canvas.deactivate(); // 停用画布
```
---
## 静态方法说明
### `MotaOffscreenCanvas2D.clone`
```ts
function clone(canvas: MotaOffscreenCanvas2D): MotaOffscreenCanvas2D;
```
**描述**
复制一个画布对象,结果画布将被冻结。
**返回值**
- 复制的画布对象(不可修改属性,但可绘制)。
**示例**
```typescript
const cloned = MotaOffscreenCanvas2D.clone(sourceCanvas); // 复制画布
```
---
### `MotaOffscreenCanvas2D.refreshAll`
```ts
function refreshAll(force: boolean = false): void;
```
**描述**
刷新所有已注册画布的尺寸(仅在窗口大小变化时自动调用)。
**参数**
- `force`: 是否强制刷新所有画布(默认仅刷新启用 `autoScale` 的画布)。
---
## 事件类型
### `resize`
**触发时机**
当画布被动调整尺寸时触发(例如窗口大小变化或 `core.domStyle.scale` 变化)。
**监听示例**
```typescript
canvas.on('resize', () => {
console.log('画布尺寸已调整');
});
```
---
## 使用示例
```typescript
// 创建画布
const canvas = new MotaOffscreenCanvas2D();
// 配置属性
canvas.size(800, 600);
canvas.withGameScale(true);
canvas.setHD(true);
// 监听调整事件
canvas.on('resize', () => {
console.log('画布尺寸已更新');
});
// 绘制内容
canvas.ctx.fillStyle = 'red';
canvas.ctx.fillRect(0, 0, canvas.width, canvas.height);
// 冻结画布
canvas.freeze();
// 复制画布
const cloned = MotaOffscreenCanvas2D.clone(canvas);
```

View File

@ -0,0 +1,174 @@
# MotaRenderer 类 API 文档
本文档由 `DeepSeek R1` 模型生成并微调。
---
## 继承关系
```mermaid
graph LR
MotaRenderer --> Container --> RenderItem --> EventEmitter
click Container "./Container"
click RenderItem "./RenderItem"
click EventEmitter "https://nodejs.org/api/events.html#class-eventemitter"
```
---
## 属性说明
| 属性名 | 类型 | 默认值 | 说明 |
| -------- | ------------------------- | ----------- | ------------------------------- |
| `isRoot` | `boolean` | `true` | 标识为渲染树根节点 |
| `target` | `MotaOffscreenCanvas2D` | - | 绑定的目标画布 |
| `idMap` | `Map<string, RenderItem>` | `new Map()` | ID 到渲染元素的映射表(受保护) |
---
## 构造方法
### `constructor`
**参数**
- `id`: 目标 canvas 元素的 DOM ID默认为 `render-main`
**行为**
- 自动绑定指定 ID 的 canvas 元素
- 初始化渲染循环和事件监听
- 设置默认锚点为中心点0.5, 0.5
**示例**
```typescript
// 创建主渲染器
const renderer = new MotaRenderer();
// 创建带自定义 ID 的渲染器
const customRenderer = new MotaRenderer('game-canvas');
```
---
## 方法说明
### `getElementById`
```typescript
function getElementById(id: string): RenderItem | null;
```
**描述**
通过 ID 获取渲染树中的元素。
**示例**
```typescript
const hero = renderer.getElementById('player');
```
---
### `refresh`
```typescript
function refresh(): void;
```
**描述**
强制刷新渲染内容(清空画布并重新渲染所有元素)。
---
### `toTagTree`
```typescript
function toTagTree(space?: number): string;
```
**描述**
(调试用)将渲染树输出为 XML 格式字符串。
**参数**
- `space`: 缩进空格数
**示例**
```typescript
console.log(renderer.toTagTree());
/* 输出示例:
<MotaRenderer id="render-main" uid="0">
<Container uid="1">
<Sprite id="cloud" uid="2" />
</Container>
</MotaRenderer>
*/
```
---
### `destroy`
```typescript
function destroy(): void;
```
**描述**
销毁渲染器,释放所有资源并解除事件监听。
---
## 静态方法说明
### `MotaRenderer.get`
```typescript
function get(id: string): MotaRenderer | undefined;
```
**描述**
通过 ID 获取已注册的渲染器实例。
**示例**
```typescript
const mainRenderer = MotaRenderer.get('render-main');
```
---
## 总使用示例
```typescript
// 初始化渲染器
const renderer = new MotaRenderer();
// 创建游戏元素
const player = new Sprite();
player.size(32, 32);
player.setRenderFn(canvas => {
canvas.ctx.fillStyle = 'blue';
canvas.ctx.fillRect(0, 0, 32, 32);
});
// 添加交互逻辑
player.on('click', ev => {
console.log('玩家被点击', ev.offsetX, ev.offsetY);
});
// 构建场景
const scene = new Container('absolute');
scene.appendChild(player);
renderer.appendChild(scene);
// 动态查找元素
setTimeout(() => {
const found = renderer.getElementById('player');
found?.pos(100, 100);
}, 1000);
// 销毁渲染器(退出时调用)
window.addEventListener('beforeunload', () => {
renderer.destroy();
});
```

View File

@ -0,0 +1,230 @@
# RenderAdapter API 文档
本文档由 `DeepSeek R1` 模型生成并微调。
---
```mermaid
graph LR
RenderAdapter --> 无继承关系
```
_RenderAdapter 为独立类无父类或子类。_
---
## 属性说明
| 属性名 | 类型 | 描述 |
| ------------------ | --------------------------------- | ------------------------------ |
| `items` | `Set<T>` | 所有元素的集合 |
| `id` | `string` | 适配器的唯一标识符 |
| `adapters`(静态) | `Map<string, RenderAdapter<any>>` | 全局存储所有已创建的适配器实例 |
---
## 构造方法
### `constructor`
```typescript
function constructor(id: string): RenderAdapter<T>;
```
创建一个适配器实例并自动注册到全局 `adapters` 集合中。
**示例:**
```typescript
const adapter = new RenderAdapter<HTMLElement>('ui-elements');
```
---
## 方法说明
### `add`
```typescript
function add(item: T): void;
```
向集合中添加一个元素。
**示例:**
```typescript
adapter.add(document.getElementById('box'));
```
### `remove`
```typescript
function remove(item: T): void;
```
从集合中移除一个元素。
**示例:**
```typescript
adapter.remove(document.getElementById('box'));
```
### `receiveGlobal`
```typescript
function receiveGlobal(
id: string,
fn: (...params: any[]) => Promise<any>
): void;
```
注册全局异步函数(不与具体元素绑定)。
**示例:**
```typescript
adapter.receiveGlobal('refresh', async () => {
await fetchData();
});
```
### `receive`
```typescript
function receive(
id: string,
fn: (item: T, ...params: any[]) => Promise<any>
): void;
```
注册元素的异步执行函数。
**示例:**
```typescript
adapter.receive('fadeOut', async (element: HTMLElement) => {
element.style.opacity = '0';
await new Promise(resolve => setTimeout(resolve, 1000));
});
```
### `receiveSync`
```typescript
function receiveSync(id: string, fn: (item: T, ...params: any[]) => any): void;
```
注册元素的同步执行函数。
**示例:**
```typescript
adapter.receiveSync('highlight', (element: HTMLElement) => {
element.style.backgroundColor = 'yellow';
});
```
### `all`
```typescript
function all<R = any>(fn: string, ...params: any[]): Promise<R[]>;
```
对所有元素执行异步函数,返回 `Promise.all` 结果。
**示例:**
```typescript
await adapter.all('fadeOut'); // 所有元素淡出
```
### `any`
```typescript
function any<R = any>(fn: string, ...params: any[]): Promise<R>;
```
对所有元素执行异步函数,返回 `Promise.any` 结果。
**示例:**
```typescript
await adapter.any('loadImage'); // 任一图片加载完成即继续
```
### `sync`
```typescript
function sync<R = any>(fn: string, ...params: any[]): R[];
```
对所有元素执行同步函数。
**示例:**
```typescript
adapter.sync('highlight'); // 所有元素高亮
```
### `global`
```typescript
function global<R = any>(id: string, ...params: any[]): Promise<R>;
```
调用全局异步函数。
**示例:**
```typescript
await adapter.global('refresh'); // 触发全局刷新
```
### `destroy`
```typescript
function destroy(): void;
```
销毁适配器实例并从全局 `adapters` 中移除。
**示例:**
```typescript
adapter.destroy();
```
---
## 静态方法说明
### `RenderAdapter.get`
```typescript
function get<T>(id: string): RenderAdapter<T> | undefined;
```
通过 ID 获取已注册的适配器实例。
**示例:**
```typescript
const adapter = RenderAdapter.get<HTMLElement>('ui-elements');
```
---
## 总使用示例
```typescript
// 创建适配器
const animationAdapter = new RenderAdapter<HTMLElement>('animations');
// 注册动画函数
animationAdapter.receive('slideLeft', async (element: HTMLElement) => {
element.style.transform = 'translateX(-100px)';
await new Promise(resolve => setTimeout(resolve, 500));
});
// 添加元素
const box = document.getElementById('box');
animationAdapter.add(box);
// 执行动画
animationAdapter.all('slideLeft').then(() => {
console.log('所有元素滑动完成');
});
// 销毁适配器
animationAdapter.destroy();
```

View File

@ -0,0 +1,477 @@
# RenderItem 类 API 文档
**需丰富**
本文档由 `DeepSeek R1` 模型生成并微调。
---
## 继承关系
```mermaid
graph LR
RenderItem --> EventEmitter
click EventEmitter "https://nodejs.org/api/events.html#class-eventemitter"
```
---
## 接口说明
### IRenderUpdater
```typescript
interface IRenderUpdater {
update(item?: RenderItem): void;
}
```
**描述**
定义元素更新能力的接口。`RenderItem` 通过 `update` 方法通知父元素需要重新渲染。
---
### IRenderAnchor
```typescript
interface IRenderAnchor {
anchorX: number;
anchorY: number;
setAnchor(x: number, y: number): void;
}
```
**描述**
管理元素锚点的接口。锚点用于定位元素的渲染基准点(如中心点、左上角等)。
---
### IRenderConfig
```typescript
interface IRenderConfig {
highResolution: boolean;
antiAliasing: boolean;
setHD(hd: boolean): void;
setAntiAliasing(anti: boolean): void;
}
```
**描述**
管理画布渲染配置的接口,控制高清模式和抗锯齿的开关。
---
### IRenderChildable
```typescript
interface IRenderChildable {
children: Set<RenderItem>;
appendChild(...child: RenderItem[]): void;
removeChild(...child: RenderItem[]): void;
requestSort(): void;
}
```
**描述**
管理子元素的接口。需在子类中实现具体逻辑(如 `Container` 元素)。
## 属性说明
| 属性名 | 类型 | 默认值 | 说明 |
| ---------------- | -------------------------- | --------------- | ---------------------------------------------------- |
| `uid` | `number` | 自动递增 | 元素的唯一标识符 |
| `id` | `string` | `''` | 元素 ID原则不可重复 |
| `zIndex` | `number` | `0` | 元素的纵深层级(决定遮挡关系) |
| `width` | `number` | `200` | 元素的逻辑宽度 |
| `height` | `number` | `200` | 元素的逻辑高度 |
| `anchorX` | `number` | `0` | 锚点横坐标(`0` 左端,`1` 右端) |
| `anchorY` | `number` | `0` | 锚点纵坐标(`0` 上端,`1` 下端) |
| `type` | `RenderItemPosition` | `'static'` | 渲染模式(`absolute` 绝对定位,`static` 跟随摄像机) |
| `highResolution` | `boolean` | `true` | 是否启用高清画布 |
| `antiAliasing` | `boolean` | `true` | 是否启用抗锯齿 |
| `hidden` | `boolean` | `false` | 元素是否隐藏 |
| `filter` | `string` | `'none'` | 元素的滤镜效果 |
| `composite` | `GlobalCompositeOperation` | `'source-over'` | 渲染混合模式 |
| `alpha` | `number` | `1` | 元素的不透明度(`0` 透明,`1` 不透明) |
| `cursor` | `string` | `'inherit'` | 鼠标悬停时的光标样式 |
| `noEvent` | `boolean` | `false` | 是否忽略交互事件 |
| `isRoot` | `boolean` | `false` | 是否为根元素(需实现 `IRenderTreeRoot` 接口) |
| `connected` | `boolean` | 自动计算 | 元素是否已连接到根元素 |
**特殊属性说明**
- `transform`: 元素的变换矩阵(`Transform` 实例),修改时会自动触发 `updateTransform`
---
## 构造方法
### `constructor(type: RenderItemPosition, enableCache: boolean = true, transformFallThrough: boolean = false)`
**参数**
- `type`: 渲染模式(`absolute` 或 `static`
- `enableCache`: 是否启用渲染缓存(默认启用)
- `transformFallThrough`: 是否启用变换矩阵下穿机制(默认关闭)
**示例**
```typescript
const item = new RenderItem('absolute');
```
---
## 方法说明
### `size`
```typescript
function size(width: number, height: number): void;
```
**描述**
设置元素的尺寸。
**示例**
```typescript
item.size(300, 200); // 设置宽度 300高度 200
```
---
### `pos`
```typescript
function pos(x: number, y: number): void;
```
**描述**
设置元素的坐标(等效于修改 `transform` 的平移量)。
**示例**
```typescript
item.pos(100, 50); // 设置坐标为 (100, 50)
```
---
### `append`
```typescript
function append(parent: RenderItem): void;
```
**描述**
将元素添加到指定父元素下。
**示例**
```typescript
const parent = new RenderItem('static');
item.append(parent); // 将 item 添加为 parent 的子元素
```
---
### `remove`
```typescript
function remove(): boolean;
```
**描述**
从父元素中移除当前元素。
**返回值**
- `true` 表示移除成功,`false` 表示失败。
**示例**
```typescript
item.remove(); // 从父元素中移除
```
---
### `hide`
```typescript
function hide(): void;
```
**描述**
隐藏元素。
**示例**
```typescript
item.hide(); // 隐藏元素
```
---
### `show`
```typescript
function show(): void;
```
**描述**
显示元素。
**示例**
```typescript
item.show(); // 显示元素
```
---
### `delegateTicker`
```typescript
function delegateTicker(fn: TickerFn, time?: number, end?: () => void): number;
```
**描述**
委托动画帧函数,持续执行指定时间。
**返回值**
- 委托 ID可用于移除。
**示例**
```typescript
const id = item.delegateTicker(() => {
console.log('每帧执行');
}, 1000); // 持续 1 秒
```
---
### `destroy`
```typescript
function destroy(): void;
```
**描述**
销毁元素,释放资源。
**示例**
```typescript
item.destroy(); // 销毁元素
```
### `getAbsolutePosition`
```typescript
function getAbsolutePosition(x?: number, y?: number): [number, number];
```
**描述**
获取元素在全局坐标系中的绝对坐标。
**示例**
```typescript
const [absX, absY] = item.getAbsolutePosition(); // 获取元素原点绝对坐标
```
---
### `getBoundingRect`
```typescript
function getBoundingRect(): DOMRectReadOnly;
```
**描述**
获取元素的包围矩形(相对于父元素坐标系)。
**示例**
```typescript
const rect = item.getBoundingRect();
console.log(rect.width, rect.height);
```
---
### `setZIndex`
```typescript
function setZIndex(zIndex: number): void;
```
**描述**
设置元素的纵深层级(`zIndex` 越大越靠前)。
**示例**
```typescript
item.setZIndex(5); // 置顶显示
```
---
### `requestRenderFrame`
```typescript
function requestRenderFrame(fn: () => void): void;
```
**描述**
在下一帧渲染时执行函数(适用于需要在渲染流程中更新的操作)。
**示例**
```typescript
item.requestRenderFrame(() => {
item.pos(item.x + 1, item.y); // 每帧右移 1 单位
});
```
---
### `setFilter`
```typescript
function setFilter(filter: string): void;
```
**描述**
设置元素的 CSS 滤镜效果(如模糊、灰度等)。
**示例**
```typescript
item.setFilter('blur(5px)'); // 添加模糊效果
```
---
## 受保护方法说明
### `render`
```typescript
protected abstract render(canvas: MotaOffscreenCanvas2D, transform: Transform): void;
```
**描述**
抽象渲染方法,子类必须实现此方法以定义具体渲染逻辑。
**示例**
```typescript
class CustomItem extends RenderItem {
protected render(canvas: MotaOffscreenCanvas2D) {
canvas.ctx.fillStyle = 'red';
canvas.ctx.fillRect(0, 0, this.width, this.height);
}
}
```
---
### `isActionInElement`
```typescript
protected isActionInElement(x: number, y: number): boolean;
```
**描述**
判断坐标点是否在元素范围内(可覆盖实现自定义碰撞检测)。
**默认行为**
检测坐标是否在 `[0, width] x [0, height]` 矩形内。
---
## 静态方法说明
### `RenderItem.ticker`
**类型**
```typescript
const ticker: Ticker;
```
**描述**
全局动画帧管理器,用于处理所有委托的动画帧函数。
---
## 事件说明
事件继承自 [ERenderItemActionEvent](./Event.md#erenderitemactionevent)
| 事件名 | 参数类型 | 说明 |
| -------------- | ------------------------- | ------------------ |
| `beforeRender` | `Transform` | 渲染前触发 |
| `afterRender` | `Transform` | 渲染后触发 |
| `destroy` | `[]` | 元素销毁时触发 |
| `transform` | `[RenderItem, Transform]` | 变换矩阵更新时触发 |
---
## 总使用示例
::: code-group
```typescript [基础操作]
// 创建元素(以 Sprite 为例)
const item = new Sprite('static');
// 设置属性
item.size(400, 300);
item.pos(100, 50);
item.setAnchor(0.5, 0.5); // 设置中心锚点
item.setZIndex(2);
// 监听渲染事件
item.on('beforeRender', transform => {
console.log('即将渲染,变换矩阵:', transform);
});
// 添加动画效果
const tickerId = item.delegateTicker(time => {
item.pos(Math.sin(time / 1000) * 100, 50);
});
// 销毁元素
setTimeout(() => {
item.destroy();
}, 5000);
```
```typescript [创建自定义元素]
// 创建自定义可交互元素
class Button extends RenderItem {
constructor() {
super('static');
this.size(100, 40);
this.on('click', ev => {
console.log('按钮被点击!坐标:', ev.offsetX, ev.offsetY);
});
}
protected render(canvas: MotaOffscreenCanvas2D) {
// 绘制圆角矩形按钮
const ctx = canvas.ctx;
ctx.fillStyle = '#4CAF50';
ctx.roundRect(0, 0, this.width, this.height, 8);
ctx.fill();
}
}
// 使用按钮
const button = new Button();
button.pos(200, 150);
button.append(parentElement);
// 添加鼠标悬停效果
button.on('enter', () => button.setFilter('brightness(1.2)'));
button.on('leave', () => button.setFilter('none'));
```
:::
# RenderItem 类 API 文档(补充部分)
本文档由 `DeepSeek R1` 模型生成并微调。
---

View File

@ -0,0 +1,12 @@
# Shader 类 API 文档
```mermaid
graph LR
Shader --> GL2 --> RenderItem --> EventEmitter
click GL2 "./GL2"
click RenderItem "./RenderItem"
click EventEmitter "https://nodejs.org/api/events.html#class-eventemitter"
```
用法同 [GL2](./GL2.md)

View File

@ -0,0 +1,11 @@
# Shader 类 API 文档
```mermaid
graph LR
ShaderProgram --> GL2Program --> EventEmitter
click GL2Program "./GL2Program"
click EventEmitter "https://nodejs.org/api/events.html#class-eventemitter"
```
用法同 [GL2Program](./GL2Program.md)

View File

@ -0,0 +1,121 @@
# Sprite 类 API 文档
本文档由 `DeepSeek R1` 模型生成并微调。
---
## 继承关系
```mermaid
graph LR
Sprite --> RenderItem --> EventEmitter
click RenderItem "./RenderItem"
click EventEmitter "https://nodejs.org/api/events.html#class-eventemitter"
```
---
## 属性说明
| 属性名 | 类型 | 默认值 | 说明 |
| ---------- | ---------------- | ---------- | -------------------------------------- |
| `renderFn` | `RenderFunction` | `() => {}` | 自定义渲染函数,用于定义精灵的绘制逻辑 |
---
## 构造方法
### `constructor`
**参数**
- `type`: 渲染模式(`absolute` 绝对定位 / `static` 跟随摄像机)
- `cache`: 是否启用渲染缓存(默认启用)
- `fall`: 是否启用变换矩阵下穿机制(默认关闭)
**示例**
```typescript
const sprite = new Sprite('static');
```
---
## 方法说明
### `setRenderFn`
```typescript
function setRenderFn(fn: RenderFunction): void;
```
**描述**
设置自定义渲染函数,用于定义精灵的具体绘制逻辑。
**参数**
- `fn`: 接收画布和变换矩阵的回调函数,格式为 `(canvas, transform) => void`
**示例**
```typescript
sprite.setRenderFn((canvas, transform) => {
// 绘制一个红色矩形
canvas.ctx.fillStyle = 'red';
canvas.ctx.fillRect(0, 0, sprite.width, sprite.height);
});
```
---
## 总使用示例
```typescript
// 创建精灵实例
const sprite = new Sprite('absolute');
sprite.size(100, 100); // 设置尺寸
sprite.pos(200, 150); // 设置坐标
// 定义渲染逻辑
sprite.setRenderFn(canvas => {
const ctx = canvas.ctx;
// 绘制渐变圆形
const gradient = ctx.createRadialGradient(50, 50, 0, 50, 50, 50);
gradient.addColorStop(0, 'yellow');
gradient.addColorStop(1, 'orange');
ctx.fillStyle = gradient;
ctx.beginPath();
ctx.arc(50, 50, 50, 0, Math.PI * 2);
ctx.fill();
});
// 添加到父容器
container.appendChild(sprite);
// 监听变换事件
sprite.on('transform', (item, transform) => {
console.log('精灵变换矩阵更新:', transform);
});
```
---
## 高级用法示例
```typescript
// 创建动态旋转精灵
const rotatingSprite = new Sprite('static');
rotatingSprite.size(80, 80);
rotatingSprite.setRenderFn((canvas, transform) => {
canvas.ctx.fillStyle = 'blue';
canvas.ctx.fillRect(0, 0, 80, 80);
});
// 每帧旋转
rotatingSprite.delegateTicker(time => {
rotatingSprite.transform.setRotate(time / 1000);
});
// 添加到场景
rootContainer.appendChild(rotatingSprite);
```

View File

@ -0,0 +1,332 @@
# Transform 类 API 文档
以下内容由 `DeepSeek R1` 模型生成并微调。
---
## 继承关系
```mermaid
graph LR
Transform --> EventEmitter
click EventEmitter "https://nodejs.org/api/events.html#class-eventemitter"
```
---
## 属性说明
| 属性名 | 类型 | 默认值 | 说明 |
| -------------- | --------------------- | ----------- | ----------------------------------------------------------- |
| `mat` | `mat3` | 单位矩阵 | 存储当前变换的 3x3 矩阵 |
| `x` | `number` | `0` | 水平平移量 |
| `y` | `number` | `0` | 垂直平移量 |
| `scaleX` | `number` | `1` | 水平缩放比例 |
| `scaleY` | `number` | `1` | 垂直缩放比例 |
| `rad` | `number` | `0` | 旋转弧度值(范围:`[0, 2π)` |
| `modified` | `boolean`(私有) | `false` | 标识变换是否被修改过 |
| `bindedObject` | `ITransformUpdatable` | `undefined` | 绑定的对象(当变换更新时自动调用其 `updateTransform` 方法) |
---
## 构造方法
### `constructor`
创建一个新的变换实例,初始化为单位矩阵。
```typescript
const transform = new Transform();
```
---
## 方法说明
### `bind`
```typescript
function bind(obj?: ITransformUpdatable): void;
```
**描述**
绑定一个对象,当变换更新时自动调用其 `updateTransform` 方法(若存在)。
**示例**
```typescript
const obj = { updateTransform: () => console.log('Transform updated!') };
transform.bind(obj);
```
---
### `reset`
```typescript
function reset(): void;
```
**描述**
重置所有参数到初始状态(单位矩阵)。
**示例**
```typescript
transform.reset(); // 重置为 x=0, y=0, scaleX=1, scaleY=1, rad=0
```
---
### `scale`
```typescript
function scale(x: number, y: number = x): this;
```
**描述**
叠加缩放变换(相对于当前状态)。
**参数**
- `x`: 水平缩放比例
- `y`: 垂直缩放比例(默认同 `x`
**示例**
```typescript
transform.scale(2); // 水平和垂直均放大2倍
transform.scale(1.5, 0.5); // 水平放大1.5倍垂直缩小到0.5倍
```
---
### `translate`
```typescript
function translate(x: number, y: number): this;
```
**描述**
叠加平移变换(相对于当前状态)。
**参数**
- `x`: 水平平移量
- `y`: 垂直平移量
**示例**
```typescript
transform.translate(100, 50); // 向右平移100单位向下平移50单位
```
---
### `rotate`
```typescript
function rotate(rad: number): this;
```
**描述**
叠加旋转变换(相对于当前状态)。
**参数**
- `rad`: 旋转弧度值
**示例**
```typescript
transform.rotate(Math.PI / 2); // 顺时针旋转90度
```
---
### `setScale`
```typescript
function setScale(x: number, y: number = x): this;
```
**描述**
直接设置缩放比例(非叠加,覆盖当前状态)。
**示例**
```typescript
transform.setScale(3, 2); // 设置水平缩放3倍垂直缩放2倍
```
---
### `setTranslate`
```typescript
function setTranslate(x: number, y: number): this;
```
**描述**
直接设置平移量(非叠加,覆盖当前状态)。
**示例**
```typescript
transform.setTranslate(200, 100); // 直接定位到(200, 100)
```
---
### `setRotate`
```typescript
function setRotate(rad: number): this;
```
**描述**
直接设置旋转角度(非叠加,覆盖当前状态)。
**示例**
```typescript
transform.setRotate(Math.PI); // 设置旋转180度
```
---
### `transformed`
```typescript
function transformed(x: number, y: number): vec3;
```
**描述**
将坐标点 `(x, y)` 应用当前变换矩阵,返回变换后的坐标。
**返回值**
- `vec3`: 变换后的三维坐标(`[x, y, 1]`
**示例**
```typescript
const point = transform.transformed(10, 20); // 应用变换后的坐标
```
---
### `untransformed`
```typescript
function untransformed(x: number, y: number): vec3;
```
**描述**
将坐标点 `(x, y)` 逆向应用当前变换矩阵,返回原坐标。
**示例**
```typescript
const origin = transform.untransformed(50, 30); // 逆向变换后的坐标
```
---
### `clone`
```typescript
function clone(): Transform;
```
**描述**
复制当前变换实例。
**示例**
```typescript
const cloned = transform.clone(); // 生成一个完全相同的副本
```
---
## 静态方法说明
### `Transform.transformed`
```typescript
function transformed(transform: Transform, x: number, y: number): vec3;
```
**描述**
静态方法,直接通过变换矩阵计算坐标点 `(x, y)` 的变换结果。
**示例**
```typescript
const result = Transform.transformed(transform, 5, 5);
```
---
### `Transform.untransformed`
```typescript
function untransformed(transform: Transform, x: number, y: number): vec3;
```
**描述**
静态方法,直接通过变换矩阵逆向计算坐标点 `(x, y)` 的原位置。
**示例**
```typescript
const origin = Transform.untransformed(transform, 100, 50);
```
---
## 接口说明
### `ITransformUpdatable`
```typescript
interface ITransformUpdatable {
updateTransform?(): void;
}
```
**描述**
可绑定对象的接口,当变换更新时触发 `updateTransform` 方法(可选)。
---
## 总使用示例
```typescript
// 创建变换实例
const transform = new Transform();
// 应用变换
transform
.translate(50, 30)
.scale(2)
.rotate(Math.PI / 4);
// 绑定对象
const obj = {
updateTransform: () => console.log('Transform updated!')
};
transform.bind(obj);
// 坐标转换
const transformedPoint = transform.transformed(10, 10);
console.log('Transformed point:', transformedPoint);
// 复制变换
const cloned = transform.clone();
// 静态方法使用
const staticResult = Transform.transformed(cloned, 5, 5);
```

View File

@ -0,0 +1,119 @@
# 函数 API 文档
本文档由 `DeepSeek R1` 模型生成并微调。
---
## 函数说明
### `isWebGLSupported`
**功能**
检测浏览器是否支持 WebGL 1.0
**返回值**
- `true`: 支持
- `false`: 不支持
**示例**
```typescript
if (isWebGLSupported()) {
// 初始化 WebGL 1.0 功能
}
```
---
### `isWebGL2Supported`
**功能**
检测浏览器是否支持 WebGL 2.0
**返回值**
- `true`: 支持
- `false`: 不支持
---
### `addTiming`
**功能**
组合两个缓动函数为加法函数
**数学表达**
`newTiming(p) = timing1(p) + timing2(p)`
**参数**
- `timing1`: 第一个缓动函数
- `timing2`: 第二个缓动函数
**示例**
```typescript
const linear = (p: number) => p;
const bounce = (p: number) => p * p;
const combined = addTiming(linear, bounce); // p + p²
```
---
### `multiplyTiming`
**功能**
组合两个缓动函数为乘法函数
**数学表达**
`newTiming(p) = timing1(p) * timing2(p)`
---
### `isSetEqual`
**功能**
判断两个集合是否相等(元素完全相同)
**实现逻辑**
1. 直接引用相同 → `true`
2. 大小不同 → `false`
3. 检查 set1 是否是 set2 的子集
---
### `transformCanvas`
**功能**
将变换矩阵应用到画布上下文
**实现逻辑**
```typescript
const mat = transform.mat; // 获取 3x3 矩阵
const [a, b, , c, d, , e, f] = mat; // 分解为 2D 变换参数
ctx.transform(a, b, c, d, e, f); // 应用变换
```
**参数**
- `canvas`: 目标画布对象
- `transform`: 变换矩阵
**示例**
```typescript
const transform = new Transform();
transform.translate(100, 50);
transformCanvas(myCanvas, transform); // 应用平移变换
```
---
## 工具函数关系图
```mermaid
graph LR
checkSupport --> isWebGLSupported
checkSupport --> isWebGL2Supported
addTiming --> 组合缓动函数
multiplyTiming --> 组合缓动函数
isSetEqual --> 集合操作
transformCanvas --> 矩阵变换
```

View File

@ -0,0 +1 @@
# @motajs/render-core

View File

@ -0,0 +1,369 @@
# BlockCacher API 文档
本文档由 `DeepSeek R1` 模型生成并微调。
---
```mermaid
graph LR
BlockCacher --> EventEmitter
click EventEmitter "https://nodejs.org/api/events.html#class-eventemitter"
```
_继承自 `EventEmitter<BlockCacherEvent>`支持事件监听。_
---
## 属性说明
| 属性名 | 类型 | 描述 |
| ------------ | ---------------- | ------------------------------------------------------------------- |
| `width` | `number` | 区域总宽度(元素单位) |
| `height` | `number` | 区域总高度(元素单位) |
| `blockSize` | `number` | 单个分块的大小(元素单位) |
| `blockData` | `BlockData` | 分块计算结果(包含分块数量、最后一个块的尺寸等信息) |
| `cacheDepth` | `number` | 缓存深度(每个分块可存储多个缓存层) |
| `cache` | `Map<number, T>` | 缓存存储结构,键为精确索引(`(x + y * blockWidth) * depth + deep` |
---
## 构造方法
### `constructor`
```typescript
function constructor(
width: number,
height: number,
size: number,
depth?: number
): BlockCacher<T>;
```
创建分块缓存管理器并自动计算初始分块。
**示例:**
```typescript
const cacher = new BlockCacher<ICanvasCacheItem>(800, 600, 64); // 800x600区域64为分块大小
```
---
## 方法说明
### `size`
```typescript
function size(width: number, height: number): void;
```
重置区域尺寸并重新分块(触发 `split` 事件)。
**示例:**
```typescript
cacher.size(1024, 768); // 重置为1024x768区域
```
### `setBlockSize`
```typescript
function setBlockSize(size: number): void;
```
修改分块尺寸并重新分块(触发 `split` 事件)。
**示例:**
```typescript
cacher.setBlockSize(128); // 分块大小改为128
```
### `setCacheDepth`
```typescript
function setCacheDepth(depth: number): void;
```
调整缓存深度(最大 31自动迁移旧缓存。
**示例:**
```typescript
cacher.setCacheDepth(3); // 每个分块支持3层缓存
```
### `split`
```typescript
function split(): void;
```
重新计算分块数据并触发 `'split'` 事件。
**示例:**
```typescript
cacher.split(); // 手动触发分块计算(一般无需调用)
```
### `clearCache`
```typescript
function clearCache(index: number, deep: number): void;
```
清除指定分块索引的缓存(按二进制掩码清除深度)。
**示例:**
```typescript
cacher.clearCache(5, 0b101); // 清除分块5的第0层和第2层缓存
```
### `clearCacheByIndex`
```typescript
function clearCacheByIndex(index: number): void;
```
直接按精确索引清除单个缓存。
**示例:**
```typescript
cacher.clearCacheByIndex(42); // 清除精确索引42对应的缓存
```
### `clearAllCache`
```typescript
function clearAllCache(): void;
```
清空所有缓存并销毁关联资源。
**示例:**
```typescript
cacher.clearAllCache(); // 完全重置缓存
```
### `getIndex`
```typescript
function getIndex(x: number, y: number): number;
```
根据分块坐标获取分块索引(分块坐标 -> 分块索引)。
**示例:**
```typescript
const index = cacher.getIndex(2, 3); // 获取(2,3)分块的索引
```
### `getIndexByLoc`
```typescript
function getIndexByLoc(x: number, y: number): number;
```
根据元素坐标获取所属分块索引(元素坐标 -> 分块索引)。
**示例:**
```typescript
const index = cacher.getIndexByLoc(150, 200); // 元素坐标(150,200)所在分块索引
```
### `getBlockXYByIndex`
```typescript
function getBlockXYByIndex(index: number): [number, number];
```
根据分块索引获取分块坐标(分块索引 -> 分块坐标)。
**示例:**
```typescript
const [x, y] = cacher.getBlockXYByIndex(5); // 分块5的坐标
```
### `getBlockXY`
```typescript
function getBlockXY(x: number, y: number): [number, number];
```
获取一个元素位置所在的分块位置(即使它不在任何分块内)(元素索引 -> 分块坐标)。
**示例:**
```typescript
const [x, y] = cacher.getBlockXY(11, 24); // 指定位置所在分块位置
```
### `getPreciseIndex`
```typescript
function getPreciseIndex(x: number, y: number, deep: number): number;
```
根据分块坐标与 `deep` 获取一个分块的精确索引(分块坐标 -> 分块索引)。
**示例:**
```typescript
const index = cacher.getPreciseIndex(2, 1, 3); // 指定分块的索引
```
### `getPreciseIndexByLoc`
```typescript
function getPreciseIndexByLoc(x: number, y: number, deep: number): number;
```
根据元素坐标及 `deep` 获取元素所在块的精确索引(元素坐标 -> 分块索引)。
**示例:**
```typescript
const index = cacher.getPreciseIndexByLoc(22, 11, 3); // 指定元素所在分块的索引
```
### `updateElementArea`
```typescript
function updateElementArea(
x: number,
y: number,
width: number,
height: number,
deep: number = 2 ** 31 - 1
): Set<number>;
```
根据元素区域清除相关分块缓存(返回受影响的分块索引集合)(元素坐标->分块清空)。
**示例:**
```typescript
const blocks = cacher.updateElementArea(100, 100, 200, 200); // 清除200x200区域内的缓存
```
### `updateArea`
```typescript
function updateArea(
x: number,
y: number,
width: number,
height: number,
deep: number = 2 ** 31 - 1
): Set<number>;
```
更新指定分块区域内的缓存(注意坐标是分块坐标,而非元素坐标)(分块坐标->分块清空)。
**示例:**
```typescript
const blocks = cacher.updateArea(1, 1, 1, 1); // 清除指定分块区域内的缓存
```
### `getIndexOf`
```typescript
function getIndexOf(
x: number,
y: number,
width: number,
height: number
): Set<number>;
```
传入分块坐标与范围,获取该区域内包含的所有分块索引(分块坐标->分块索引集合)。
**示例:**
```typescript
const blocks = cacher.getIndexOf(1, 1, 1, 1); // 清除指定分块区域内的缓存
```
### `getIndexOfElement`
```typescript
function getIndexOfElement(
x: number,
y: number,
width: number,
height: number
): Set<number>;
```
传入元素坐标与范围,获取该区域内包含的所有分块索引(元素坐标->分块索引集合)。
**示例:**
```typescript
const blocks = cacher.getIndexOfElement(3, 5, 12, 23); // 清除指定元素区域内的缓存
```
### `getRectOfIndex`
```typescript
function getRectOfIndex(block: number): [number, number, number, number];
```
获取分块索引对应的元素坐标范围(分块索引 -> 元素矩形坐标)。
**示例:**
```typescript
const [x1, y1, x2, y2] = cacher.getRectOfIndex(5); // 分块5的坐标范围
```
### `getRectOfBlockXY`
```typescript
function getRectOfBlockXY(
x: number,
y: number
): [number, number, number, number];
```
根据分块坐标,获取这个分块所在区域的元素矩形范围(左上角横纵坐标及右下角横纵坐标)(分块坐标 -> 元素矩形坐标)。
**示例:**
```typescript
const [x1, y1, x2, y2] = cacher.getRectOfIndex(5); // 分块5的坐标范围
```
### `destroy`
```typescript
function destroy(): void;
```
摧毁这个块缓存。
---
## 事件说明
| 事件名 | 参数 | 描述 |
| ------- | ---- | ------------------ |
| `split` | 无 | 分块参数变更时触发 |
---
## 总使用示例
```typescript
// 创建缓存管理器
const cacheManager = new BlockCacher<ICanvasCacheItem>(1024, 768, 64);
// 监听分块变化
cacheManager.on('split', () => {
console.log('分块已重新计算');
});
// 添加测试缓存项
const blockIndex = cacheManager.getIndex(2, 3);
const preciseIndex = cacheManager.getPreciseIndex(2, 3, 0);
cacheManager.cache.set(
preciseIndex,
new CanvasCacheItem(new MotaOffscreenCanvas2D(), 1)
);
// 清除特定区域缓存
cacheManager.updateElementArea(150, 150, 100, 100);
// 销毁管理器
cacheManager.destroy();
```

View File

@ -0,0 +1,386 @@
# Camera API 文档
本文档由 `DeepSeek R1` 模型生成并微调。
---
```mermaid
graph LR
Camera --> EventEmitter
click EventEmitter "https://nodejs.org/api/events.html#class-eventemitter"
```
_继承自 `EventEmitter<CameraEvent>`支持事件监听。_
---
## 属性说明
| 属性名 | 类型 | 描述 |
| --------------------- | ------------------- | ------------------------------------------------ |
| `readonly binded` | `RenderItem` | 当前绑定的渲染元素 |
| `transform` | `Transform` | 目标变换矩阵,默认与 `binded.transform` 共享引用 |
| `protected operation` | `CameraOperation[]` | 当前应用的变换操作列表(平移/旋转/缩放) |
---
## 构造方法
### `Camera.for`
```typescript
function for(item: RenderItem): Camera
```
获取或创建与渲染元素关联的摄像机实例。
**示例:**
```typescript
const item = new RenderItem();
const camera = Camera.for(item); // 获取或创建摄像机
```
### `constructor`
```typescript
function constructor(item: RenderItem): Camera;
```
直接创建摄像机实例(不会自动注册到全局映射)。
**注意:** 推荐优先使用 `Camera.for()` 方法。
---
## 方法说明
### `disable`
```typescript
function disable(): void;
```
禁用摄像机变换效果。
**示例:**
```typescript
camera.disable(); // 暂停所有摄像机变换
```
### `enable`
```typescript
function enable(): void;
```
启用摄像机变换效果。
### `requestUpdate`
```typescript
function requestUpdate(): void;
```
请求在下一帧强制更新变换矩阵。
### `removeOperation`
```typescript
function removeOperation(operation: CameraOperation): void;
```
移除一个变换操作。
**参数说明**
- `operation`: 要移除的操作
**示例**
```ts
const operation = camera.addTranslate();
camera.removeOperation(operation);
```
### `clearOperation`
```ts
function clearOperation(): void;
```
清空变换操作列表。
### `addTranslate`
```typescript
function addTranslate(): ICameraTranslate;
```
添加平移操作并返回操作对象。
**示例:**
```typescript
const translateOp = camera.addTranslate();
translateOp.x = 100; // 设置横向偏移
camera.requestUpdate();
```
### `addRotate`
```typescript
function addRotate(): ICameraRotate;
```
添加旋转操作并返回操作对象。
**示例:**
```typescript
const rotateOp = camera.addRotate();
rotateOp.angle = Math.PI / 2; // 设置90度旋转
camera.requestUpdate();
```
### `addScale`
```typescript
function addScale(): ICameraScale;
```
添加缩放操作并返回操作对象。
**示例:**
```typescript
const scaleOp = camera.addScale();
scaleOp.x = 2; // 横向放大2倍
camera.requestUpdate();
```
### `applyAnimation`
```ts
function applyAnimation(time: number, update: () => void): void;
```
施加动画。
**参数说明**
- `time`: 动画时长。
- `update`: 每帧执行的更新函数。
### `applyTranslateAnimation`
```typescript
function applyTranslateAnimation(
operation: ICameraTranslate,
animate: Animation,
time: number
): void;
```
为平移操作绑定动画。
**参数说明:**
- `animate`: 预定义的动画实例
- `time`: 动画持续时间(毫秒)
### `applyRotateAnimation`
```typescript
function applyRotateAnimation(
operation: ICameraRotate,
animate: Animation,
time: number
): void;
```
为旋转操作绑定动画。
### `applyScaleAnimation`
```typescript
function applyScaleAnimation(
operation: ICameraScale,
animate: Animation,
time: number
): void;
```
为缩放操作绑定动画。
### `applyTranslateTransition`
```typescript
function applyTranslateTransition(
operation: ICameraTranslate,
animate: Transition,
time: number
): void;
```
为平移操作绑定渐变。
**参数说明:**
- `animate`: 预定义的渐变实例
- `time`: 渐变持续时间(毫秒)
### `applyRotateTransition`
```typescript
function applyRotateTransition(
operation: ICameraRotate,
animate: Transition,
time: number
): void;
```
为旋转操作绑定渐变。
### `applyScaleTransition`
```typescript
function applyScaleTransition(
operation: ICameraScale,
animate: Transition,
time: number
): void;
```
为缩放操作绑定渐变。
### `stopAllAnimates`
```ts
function stopAllAnimates(): void;
```
停止所有动画。
### `destroy`
```typescript
function destroy(): void;
```
销毁摄像机并释放所有资源。
**示例:**
```typescript
camera.destroy(); // 解除绑定并清理动画
```
---
## 事件说明
| 事件名 | 参数 | 描述 |
| --------- | ---- | ------------------ |
| `destroy` | 无 | 摄像机被销毁时触发 |
---
## 总使用示例
::: code-group
```typescript [动画]
import { Animation, linear } from 'mutate-animate';
// 获取摄像机实例
const item = new Sprite();
const camera = Camera.for(item);
// 添加平移和缩放操作
const translate = camera.addTranslate();
const scale = camera.addScale();
// 创建动画实例
const anim = new Animation()
.mode(linear())
.time(1000)
.move(100, 100)
.time(800)
.scale(1.5);
// 绑定动画
camera.applyTranslateAnimation(translate, anim, 1000);
camera.applyScaleAnimation(scale, anim, 800);
// 启用摄像机
camera.enable();
// 销毁(当不再需要时)
setTimeout(() => camera.destroy(), 2000);
```
```typescript [渐变]
import { Transition, hyper } from 'mutate-animate';
// 获取摄像机实例
const item = new Sprite();
const camera = Camera.for(item);
// 添加平移和缩放操作
const translate = camera.addTranslate();
const scale = camera.addScale();
// 创建渐变实例,使用双曲正弦速率曲线
const tran = new Transition().mode(hyper('sin', 'out')).time(1000);
// 初始化参数,这一步不会执行渐变
tran.value.x = 0;
tran.value.y = 0;
tran.value.size = 0;
// 对参数执行渐变,直接设置即可
tran.value.x = 100;
tran.value.y = 200;
tran.time(800); // 设置渐变时长为 800 毫秒
tran.value.size = 1.5;
// 绑定动画
camera.applyTranslateTransition(translate, tran, 1000);
camera.applyScaleTransition(scale, tran, 800);
// 启用摄像机
camera.enable();
// 销毁(当不再需要时)
setTimeout(() => camera.destroy(), 2000);
```
:::
---
## 接口说明
### `ICameraTranslate`
```typescript
interface ICameraTranslate {
readonly type: 'translate';
readonly from: RenderItem;
x: number; // 横向偏移量
y: number; // 纵向偏移量
}
```
### `ICameraRotate`
```typescript
interface ICameraRotate {
readonly type: 'rotate';
readonly from: RenderItem;
angle: number; // 旋转弧度值
}
```
### `ICameraScale`
```typescript
interface ICameraScale {
readonly type: 'scale';
readonly from: RenderItem;
x: number; // 横向缩放比
y: number; // 纵向缩放比
}
```

View File

@ -0,0 +1,201 @@
# CameraAnimation API 文档
本文档由 `DeepSeek R1` 模型生成并微调。
---
```mermaid
graph LR
CameraAnimation --> EventEmitter
click EventEmitter "https://nodejs.org/api/events.html#class-eventemitter"
```
_继承自 `EventEmitter<CameraAnimationEvent>`支持事件监听。_
---
## 属性说明
| 属性名 | 类型 | 描述 |
| -------- | -------- | ---------------- |
| `camera` | `Camera` | 关联的摄像机实例 |
---
## 构造方法
### `constructor`
```typescript
function constructor(camera: Camera): CameraAnimation;
```
创建摄像机动画管理器,需绑定到特定 `Camera` 实例。
**示例:**
```typescript
const camera = Camera.for(renderItem);
const animation = new CameraAnimation(camera);
```
---
## 方法说明
### `translate`
```typescript
function translate(
operation: ICameraTranslate,
x: number,
y: number,
time: number,
start: number,
timing: TimingFn
): void;
```
为平移操作添加动画。
**参数说明:**
- `x`, `y`: 目标偏移量(格子坐标,自动乘以 `32`,之后可能改动)
- `time`: 动画持续时间(毫秒)
- `start`: 动画开始时间(相对于总动画开始的延迟)
- `timing`: 缓动函数(输入时间完成度,输出动画完成度)
### `rotate`
```typescript
function rotate(
operation: ICameraRotate,
angle: number,
time: number,
start: number,
timing: TimingFn
): void;
```
为旋转操作添加动画。
**参数说明:**
- `angle`: 目标旋转弧度(如 `Math.PI` 表示 `180` 度)
- 其余参考[`rotate`](#rotate)
### `scale`
```typescript
function scale(
operation: ICameraScale,
scale: number,
time: number,
start: number,
timing: TimingFn
): void;
```
为缩放操作添加动画。
**参数说明:**
- `scale`: 目标缩放倍率(如 `1.5` 表示放大 `1.5` 倍)
- 其余参考[`rotate`](#rotate)
### `start`
```typescript
function start(): void;
```
启动所有已添加的动画,按时间顺序执行。
**注意:** 调用后动画将按 `start` 参数定义的顺序触发。
### `destroy`
```typescript
function destroy(): void;
```
销毁动画管理器并释放所有资源(停止未完成的动画)。
---
## 事件说明
| 事件名 | 参数 | 描述 |
| --------- | -------------------------------------------------------------------------------------------------------- | ---------------------------- |
| `animate` | `operation: CameraOperation` <br> `execution: CameraAnimationExecution` <br> `item: CameraAnimationData` | 当某个动画片段开始执行时触发 |
---
## 总使用示例
```typescript
import { hyper, trigo } from 'mutate-animate';
// 创建渲染元素和摄像机
const renderItem = new Sprite();
const camera = Camera.for(renderItem);
// 添加平移和旋转操作
const translateOp = camera.addTranslate();
const rotateOp = camera.addRotate();
// 创建动画管理器
const animation = new CameraAnimation(camera);
// 添加平移动画1秒后开始持续2秒横向移动3格3*32像素
animation.translate(
translateOp,
3,
0, // x=3, y=0自动乘32
2000, // 动画时长2秒
1000, // 延迟1秒开始
hyper('sin', 'out') // 双曲正弦函数
);
// 添加旋转动画立即开始持续1.5秒旋转180度
animation.rotate(
rotateOp,
Math.PI, // 目标角度(弧度)
1500, // 动画时长1.5秒
0, // 无延迟
trigo('sin', 'out') // 正弦函数
);
// 启动动画
animation.start();
// 监听动画事件
animation.on('animate', (operation, execution, item) => {
console.log('动画片段开始:', item.type);
});
// 销毁(动画结束后)
setTimeout(() => {
animation.destroy();
camera.destroy();
}, 5000);
```
---
## 接口说明
### `CameraAnimationExecution`
```typescript
interface {
data: CameraAnimationData[]; // 动画片段列表
animation: Animation; // 关联的动画实例
}
```
### `CameraAnimationData`
```typescript
type CameraAnimationData =
| TranslateAnimation
| TranslateAsAnimation
| RotateAnimation
| ScaleAnimation;
```

View File

@ -0,0 +1,3 @@
# @motajs/render-elements
目录:

View File

@ -0,0 +1,186 @@
# Font API 文档
本文档由 `DeepSeek R1` 模型生成并微调。
---
```mermaid
graph LR
Font --> IFontConfig
```
_实现 `IFontConfig` 接口表示字体配置。_
---
## 接口说明
### `IFontConfig`
```typescript
interface IFontConfig {
family: string; // 字体名称(如 "Arial"
size: number; // 字号数值
sizeUnit: string; // 字号单位(推荐 "px"
weight: number; // 字重0-1000
italic: boolean; // 是否斜体
}
```
### `FontWeight` 枚举
```typescript
enum FontWeight {
Light = 300, // 细体
Normal = 400, // 常规
Bold = 700 // 粗体
}
```
---
## 属性说明
| 属性名 | 类型 | 描述 |
| ---------- | --------- | ------------------------- |
| `family` | `string` | 字体家族名称(只读) |
| `size` | `number` | 字号数值(只读) |
| `sizeUnit` | `string` | 字号单位(如 "px",只读) |
| `weight` | `number` | 字重数值(只读) |
| `italic` | `boolean` | 是否斜体(只读) |
---
## 构造方法
### `constructor`
```typescript
function constructor(
family?: string,
size?: number,
sizeUnit?: string,
weight?: number,
italic?: boolean
): Font;
```
创建字体实例,参数默认使用静态默认值。
**示例:**
```typescript
const font = new Font('Arial', 14, 'px', FontWeight.Bold, true);
```
---
## 方法说明
### `addFallback`
```typescript
function addFallback(...fallback: Font[]): void;
```
添加后备字体(当主字体不可用时使用)。
**注意:** 检测到递归添加时会触发 `logger.warn(62)` 警告。
**示例:**
```typescript
const mainFont = new Font('CustomFont');
const fallback1 = new Font('Arial');
const fallback2 = new Font('Helvetica');
mainFont.addFallback(fallback1, fallback2); // 添加两个后备
```
### `string`
```typescript
function string(): string;
```
生成 CSS 字体字符串,包含后备字体。
**示例:**
```typescript
console.log(font.string()); // 示例输出:"italic 700 14px CustomFont, 400 16px Arial"
```
---
## 静态方法说明
### `Font.parse`
```typescript
function parse(str: string): Font;
```
解析 CSS 字体字符串(支持多字体声明)。
**示例:**
```typescript
const parsed = Font.parse('italic 16px "Fira Sans", Arial');
// 主字体Fira Sans后备Arial
```
### `Font.setDefaults`
```typescript
function setDefaults(font: Font): void;
```
全局设置默认字体参数。
**示例:**
```typescript
Font.setDefaults(new Font('Segoe UI', 14, 'px', 400, false));
```
### `Font.clone`
```typescript
function clone(font: Font, options: Partial<IFontConfig>): Font;
```
克隆字体并修改指定属性。
**示例:**
```typescript
const cloned = Font.clone(baseFont, {
size: 18,
weight: FontWeight.Bold
});
```
---
## 总使用示例
```typescript
// 创建主字体
const mainFont = new Font('CustomFont', 16, 'px', FontWeight.Normal);
// 添加后备字体(注意避免循环引用)
const fallbackA = new Font('Arial');
const fallbackB = new Font('Helvetica');
fallbackA.addFallback(fallbackB);
// 错误示例触发警告62:
// fallbackB.addFallback(fallbackA);
mainFont.addFallback(fallbackA);
// 生成 CSS 字符串
console.log(mainFont.string());
// 输出: "400 16px CustomFont, 400 16px Arial, 400 16px Helvetica"
// 解析 CSS 字符串
const parsed = Font.parse('italic 700 24px Fantasy, "Comic Sans"');
parsed.addFallback(new Font('Verdana'));
// 克隆并修改
const boldFont = Font.clone(parsed, {
weight: FontWeight.Bold,
italic: false
});
```

View File

@ -0,0 +1,3 @@
# @motajs/render-style
目录:

View File

@ -0,0 +1,134 @@
# BaseProps 接口文档
本文档由 `DeepSeek R1` 模型生成并微调。
---
## 接口定义
```typescript
interface BaseProps {
// 基础定位
x?: number; // 横坐标(单位:像素)
y?: number; // 纵坐标(单位:像素)
anchorX?: number; // 横向锚点比例0~1默认 0
anchorY?: number; // 纵向锚点比例0~1默认 0
zIndex?: number; // 纵深层级(值越大越靠上)
// 尺寸控制
width?: number; // 元素宽度(单位:像素,默认 200
height?: number; // 元素高度(单位:像素,默认 200
// 渲染控制
filter?: string; // CSS滤镜如 "blur(5px)"
hd?: boolean; // 启用高清画布(默认 true
anti?: boolean; // 启用抗锯齿(默认 true
noanti?: boolean; // 强制禁用抗锯齿(优先级高于 anti
hidden?: boolean; // 隐藏元素(默认 false
// 变换与定位
transform?: Transform; // 变换矩阵对象
type?: RenderItemPosition; // 定位模式("static" | "absolute"
cache?: boolean; // 启用缓存优化(根据不同元素的特性有不同的值,多数情况下使用默认配置即可达到最优性能)
nocache?: boolean; // 强制禁用缓存(优先级高于 cache
fall?: boolean; // 继承父元素变换矩阵(默认 false不建议使用此参数可能很快就会被删除
// 交互与样式
id?: string; // 唯一标识符
alpha?: number; // 不透明度0~1默认 1
composite?: GlobalCompositeOperation; // 混合模式(如 "lighter"
cursor?: string; // 鼠标悬停样式(如 "pointer"
noevent?: boolean; // 禁用交互事件(默认 false
// 简写属性
loc?: ElementLocator /*
[x, y, width?, height?, anchorX?, anchorY?]
如果填写的话,两两一组要么都填要么都不填,也就是说元素数量需要是 2,4,6 个
*/;
anc?: ElementAnchor; // [anchorX, anchorY],如果填写的话,两项必填
scale?: ElementScale; // [scaleX, scaleY],如果填写的话,两项必填
rotate?: number; // 旋转弧度值(单位:弧度)
}
```
---
## 完整使用示例
```tsx
import { defineComponent } from 'vue';
import { Transform } from '@motajs/render-core';
// 注意,以下属性均可选,按照自己需要填写即可,不需要的可以不用填,简单需求一般只需要修改定位
// 而复杂需求可能需要填写更多的参数,但是基本不会出现所有参数都要填的场景
// 编写 UI 的流程参考深度指南中的 UI 编写
export const MyUI = defineComponent(() => {
return () => (
<sprite
// 基础定位
x={100}
y={200}
anchorX={0.5} // 中心锚点
anchorY={0.5}
zIndex={5} // 确保在最上层
// 尺寸控制
width={300}
height={200}
// 渲染控制
filter="drop-shadow(5px 5px 5px rgba(0,0,0,0.5))"
hd // 高清模式
noanti // 强制关闭抗锯齿(像素风格)
hidden={false} // 显示元素
// 变换与定位
transform={new Transform().translate(10, 20)}
type="static" // 绝对定位
nocache // 禁用缓存
fall // 继承父变换
// 交互与样式
id="hero-sprite"
alpha={0.8} // 80% 不透明
composite="lighter" // 叠加混合模式
cursor="move" // 拖动光标
noevent={false} // 允许交互
// 简写属性
loc={[50, 60, 150, 100]} // x=50, y=60, width=150, height=100
anc={[0.5, 1]} // 底部中心锚点
scale={[1.2, 0.8]} // 横向拉伸 20%,纵向压缩 20%
rotate={Math.PI / 4} // 旋转 45 度
></sprite>
);
});
```
---
## 属性效果说明
| 属性组 | 关键效果 |
| -------------- | -------------------------------------------------------------------------- |
| **基础定位** | 元素将出现在 (100,200) 坐标,以中心点(锚点 0.5)为基准定位 |
| **尺寸控制** | 元素尺寸固定为 300x200 像素 |
| **渲染控制** | 应用阴影滤镜,高清画质,关闭抗锯齿实现像素风格 |
| **变换与定位** | 附加额外平移变换,使用绝对定位模式,禁用缓存优化 |
| **交互与样式** | 元素半透明,叠加混合模式,显示"move"光标,响应交互事件 |
| **简写属性** | 通过 loc 覆盖坐标和尺寸anc 设置底部锚点scale 实现拉伸/压缩,旋转 45 度 |
---
## 注意事项
1. **优先级规则**
- `noanti` > `anti``nocache` > `cache`
- 显式属性(如 `x`)与简写属性(如 `loc` 中的 `x`)相比,谁最后被设置,就用谁的
2. **简写属性解析**
```ts
loc = [100, 200, 300, 200]; // → x=100, y=200, width=300, height=200
anc = [0.5, 0]; // → anchorX=0.5, anchorY=0
scale = [2]; // → scaleX=2, scaleY=2
```
3. **其他注意事项**
- `transform.translate``x` `y` 和简写定位属性的 `x` `y` 完全等效,设置后者也会让 `transform` 的平移量改变
- 如果不允许交互,那么光标也不会显示
- 同 `zIndex` 下,后插入的元素会在上层,但是这也意味着如果是动态插入的元素(例如由于响应式更改而插入了一个新元素),会显示在后面代码的元素之上
4. **常见问题**
- 参考 [指南](../../guide/ui-faq.md)

View File

@ -0,0 +1,167 @@
# GraphicBaseProps API 文档
本文档由 `DeepSeek R1` 模型生成并微调。
---
## 接口定义
```typescript
interface GraphicBaseProps extends BaseProps {
/** 是否填充(默认 false */
fill?: boolean;
/** 是否描边(默认 false */
stroke?: boolean;
/** 强制先描边后填充(优先级最高,默认 false */
strokeAndFill?: boolean;
/** 填充规则(默认 "evenodd" */
fillRule?: CanvasFillRule;
/** 填充样式(颜色/渐变/图案) */
fillStyle?: CanvasStyle;
/** 描边样式(颜色/渐变/图案) */
strokeStyle?: CanvasStyle;
/** 交互时是否仅检测描边区域(默认 false */
actionStroke?: boolean;
}
```
---
## 核心属性说明
| 属性 | 类型 | 默认值 | 说明 |
| --------------- | ----------------------------------------------- | ----------- | -------------------------------------------------------------- |
| `fill` | `boolean` | `false` | 启用填充(需设置 `fillStyle` |
| `stroke` | `boolean` | `false` | 启用描边(需设置 `strokeStyle``strokeWidth` |
| `strokeAndFill` | `boolean` | `false` | 强制先描边后填充(覆盖 `fill``stroke` 的设置) |
| `fillRule` | `"nonzero"` \| `"evenodd"` | `"evenodd"` | 填充路径计算规则(影响复杂图形的镂空效果) |
| `fillStyle` | `string` \| `CanvasGradient` \| `CanvasPattern` | - | 填充样式(支持 CSS 颜色、渐变对象等) |
| `strokeStyle` | `string` \| `CanvasGradient` \| `CanvasPattern` | - | 描边样式 |
| `actionStroke` | `boolean` | `false` | 设为 `true` 时,交互事件仅响应描边区域(需配合 `stroke` 使用) |
---
## 使用示例(以矩形为例)
### 示例 1仅填充模式
```tsx
<g-rect
loc={[100, 100, 200, 150]} // x,y,width,height
fill
fillStyle="#fff"
/>
```
**效果**
- 200x150 矩形
- 无描边效果
---
### 示例 2仅描边模式
```tsx
<g-rect
loc={[400, 200, 180, 120]}
stroke
strokeStyle="rgba(0,0,0,0.8)"
strokeWidth={4}
actionStroke // 点击时仅描边区域响应
/>
```
**交互特性**
- 4px 黑色半透明描边
- 鼠标悬停在描边区域才会触发事件
---
### 示例 3填充 + 描边(默认顺序)
```tsx
<g-rect
loc={[50, 300, 150, 100]}
fill
stroke
fillStyle="#ffe66d"
strokeStyle="#2d3436"
strokeWidth={2}
/>
```
**渲染顺序**
1. 填充黄色背景
2. 在填充层上绘制黑色描边
---
### 示例 4强制先描边后填充
```tsx
<g-rect
loc={[300, 400, 200, 200]}
strokeAndFill
fillStyle="#a29bfe"
strokeStyle="#6c5ce7"
strokeWidth={8}
/>
```
**渲染顺序**
1. 绘制紫色描边
2. 在描边层上填充浅紫色
**视觉效果**:描边被填充色覆盖一部分
---
## 最佳实践
### 交互增强技巧
```tsx
import { ref } from 'vue';
// 高亮描边交互反馈
const hovered = ref(false);
// 使用 void 关键字屏蔽返回值,避免返回值泄漏
const enter = () => void (hovered.value = true);
const leave = () => void (hovered.value = false);
<g-rect
loc={[100, 100, 200, 80]}
fill
fillStyle="#ffffff"
stroke={hovered.value}
strokeStyle="#e84393"
strokeWidth={3}
onEnter={enter}
onLeave={leave}
/>;
```
---
## 注意事项
1. **样式覆盖顺序**
`strokeAndFill` 会强制按 **描边 → 填充** 顺序渲染,忽略 `fill``stroke` 的独立设置。
2. **路径闭合规则**
`fillRule="evenodd"` 适用于以下场景:
```tsx
// 五角星镂空效果
<path
fill={true}
fillRule="evenodd"
path={starPath} // 交替重叠的路径
/>
```
3. **性能问题**
多数情况下,图形的性能很好,不需要单独优化,但是如果你使用 `path` 标签,且内容复杂,建议添加 `cache` 属性来启用缓存,避免频繁的复杂图形绘制。

View File

@ -0,0 +1,149 @@
# use.ts API 文档
本文档由 `DeepSeek R1` 模型生成并微调。
---
## 函数说明
### `onTick`
```typescript
function onTick(fn: (time: number) => void): void;
```
**功能**:注册每帧执行的回调(自动管理生命周期)
**推荐使用场景**:替代 `ticker`
**参数说明**
- `fn`: 接收当前时间戳的帧回调函数
**示例**
```typescript
// Vue 组件中
onTick(time => {
console.log('当前帧时间:', time);
});
```
---
### `useAnimation`
```typescript
function useAnimation(): [Animation];
```
**功能**:创建动画实例(自动销毁资源)
**返回值**:包含动画实例的元组
**推荐使用场景**:替代直接 `new Animation()`
**示例**
```typescript
const [anim] = useAnimation();
anim.time(1000).move(100, 200);
```
---
### `useTransition`
```typescript
function useTransition(): [Transition];
```
**功能**:创建渐变实例(自动销毁资源)
**返回值**:包含渐变实例的元组
**推荐使用场景**:替代直接 `new Transition()`
**示例**
```typescript
const [transition] = useTransition();
transition.value.x = 10;
transition.time(500);
transition.value.x = 100;
```
---
### `useKey`
```typescript
function useKey(noScope?: boolean): [Hotkey, symbol];
```
**功能**:管理按键作用域(自动注销绑定)
**参数说明**
- `noScope`: 是否使用全局作用域(默认创建新作用域)
**返回值**:元组 [热键实例, 作用域标识]
**推荐使用场景**:替代直接操作全局热键实例
**示例**
```typescript
const [hotkey, scope] = useKey();
hotkey.realize('mykey_id', () => console.log('mykey_id emitted.'));
```
---
### `onEvent`
```typescript
function onEvent<
T extends ERenderItemEvent,
K extends EventEmitter.EventNames<T>
>(
item: RenderItem<T>,
key: K,
listener: EventEmitter.EventListener<T, K>
): void;
```
**功能**:自动管理事件监听生命周期
**推荐使用场景**:替代直接 `item.on()` + 手动注销
**示例**
```typescript
onEvent(sprite, 'click', event => {
console.log('元素被点击', event);
});
```
---
## 总使用示例
```tsx
import { defineComponent } from 'vue';
import { useAnimation, onTick, useKey } from '@motajs/render-vue';
export const MyComponent = defineComponent(() => {
// 动画控制
const [anim] = useAnimation();
anim.time(1000).rotate(Math.PI);
// 帧循环
onTick(time => {
console.log('当前游戏运行时间:', time);
});
// 按键控制
const [hotkey, scope] = useKey();
hotkey.realize('mykey_id', () => console.log('mykey_id emitted.'));
return () => <sprite />;
});
```
---
## 注意事项
1. **资源管理**:所有通过这些接口创建的资源(动画/渐变/事件)都会在组件卸载时自动销毁
2. **内存安全**:使用原生接口可能导致内存泄漏,这些封装接口确保:
- 自动注销事件监听
- 自动停止动画/渐变
- 自动清理按键绑定
3. **类型安全**:所有接口均包含完整的类型推断(如 `onEvent` 的事件类型检查)
4. **框架适配**:专为 Vue3 组合式 API 设计,不可用于其他框架环境

View File

@ -0,0 +1,3 @@
# @motajs/render-vue
目录:

View File

@ -0,0 +1,139 @@
# ContainerProps API 文档
本文档由 `DeepSeek R1` 模型生成并微调。
---
```mermaid
graph LR
ContainerProps --> BaseProps
click BaseProps "./BaseProps"
```
---
## 接口定义
```typescript
interface ContainerProps extends BaseProps {} // 无新增属性,完全继承 BaseProps
```
---
## 核心能力
1. **嵌套结构**:支持多层容器嵌套,构建复杂 UI 层级
2. **批量更新**:通过容器隔离高频/低频更新内容
3. **虚拟化支持**:推荐结合 `Scroll`/`Page` 组件处理大数据量场景
---
## 完整示例集
### 示例 1基础容器静态内容优化
```tsx
import { ref } from 'vue';
import { Font } from '@motajs/render-style';
const count = ref(0);
const boldFont = new Font('Verdana', 18, 'px', 700);
// 静态容器(启用缓存)
<container cache loc={[0, 0, 200, 200]}>
{/* 静态背景 */}
<sprite />
{/* 动态计数器 */}
<container x={100} y={100}>
<text text={count.value.toString()} font={boldFont} />
</container>
</container>;
```
**优化策略**
- 背景层缓存,避免重复绘制
- 计数器单独放置在独立容器,避免高频内容污染致使低频内容也需要高频更新
---
### 示例 2条件渲染 + 循环渲染
```tsx
import { ref } from 'vue';
// 根据状态显示不同内容
const tab = ref<'list' | 'detail'>('list');
const item = [{ id: 0, name: '第一个元素' }];
return () => (
<container>
{/* 选项卡导航 */}
<container x={20} y={20}>
<text text="列表" />
<text text="详情" />
</container>
{/* 条件内容区 */}
{tab === 'list' ? (
{/* 循环渲染 */}
<container cache={true} y={60}>
{items.map((item, i) => (
<text key={item.id} x={0} y={i * 40} text={`列表元素${item.name}`} />
))}
</container>
) : (
<container y={60}>
<text text="详情内容" />
</container>
)}
</container>
);
```
---
### 示例 3动态布局嵌套
```tsx
// 自适应居中布局
<container anc={[0.5, 0.5]} loc={[0, 0, 200, 200]}>
{/* 主内容卡片 */}
<container>
<text x={20} y={20} text="自适应内容" />
</container>
{/* 控制栏 */}
<container loc={[20, 20, 200, 40]}>
<text text="控制栏" />
</container>
</container>
```
---
## 性能优化指南
### 缓存策略对比
| 场景 | 配置 | 重绘频率 | 适用场景 |
| ---------------- | -------------- | -------- | --------------- |
| 不频繁更新的内容 | `cache=true` | 偶尔重绘 | 背景/图标等 |
| 高频更新内容 | `nocache=true` | 每帧重绘 | 动画/计数器 |
| 混合内容 | 分层容器 | 按需更新 | 带静态背景的 UI |
### 大数据量处理方案
考虑使用[滚动条](../user-client-modules/Scroll.md)或[分页](../user-client-modules/Page.md)组件。
---
## 注意事项
1. **缓存失效条件**:当任意子元素及自身发生变化时,将会自动触发更新
2. **嵌套层级**:推荐使用容器嵌套提高缓存能力,但是并建议不嵌套过多
3. **子元素更新**:修改容器子元素时会触发整个容器的缓存重建
4. **内存管理**:超大缓存容器(如 4096x4096可能触发浏览器纹理限制

View File

@ -0,0 +1,88 @@
# ContainerCustomProps API 文档
本文档由 `DeepSeek R1` 模型生成并微调。
---
```mermaid
graph LR
ContainerCustomProps --> ContainerProps --> BaseProps
click ContainerProps "./ContainerProps"
click BaseProps "./BaseProps"
```
---
## 接口定义
```typescript
interface ContainerCustomProps extends ContainerProps {
/**
* 自定义容器渲染函数
* @param canvas - 离屏画布对象(已应用容器的变换矩阵)
* @param children - 所有子元素(未经过滤,按照 zIndex 从小到大排列)
* @param transform - 容器自身相对于父元素的变换矩阵
*/
render?: (
canvas: MotaOffscreenCanvas2D,
children: RenderItem[],
transform: Transform
) => void;
}
```
---
## 核心能力
1. **虚拟化渲染**:通过自定义筛选逻辑实现仅渲染想要渲染的内容
2. **渲染劫持**:完全接管子元素的绘制流程
---
## 完整示例集
### 示例 1默认渲染模式等同普通容器
```tsx
// 不传 render 参数时,自动渲染全部子元素
<container-custom>
<sprite x={0} render={drawBackground} />
<text x={20} y={20} text="Default Render" />
<text x={200} text="Click Me" />
</container-custom>
```
---
### 示例 2部分渲染仅显示可见区域
```tsx
const render = (
canvas: MotaOffscreenCanvas2D,
children: RenderItem[],
transform: Transform
) => {
// 在 [0, 0, 200, 200] 之外的内容不渲染
children.forEach(child => {
const rect = child.getBoundingRect();
// 不在范围内的排除
if (
rect.right < 0 ||
rect.bottom < 0 ||
rect.left > 200 ||
rect.top > 200
)
return;
child.renderContent(canvas, transform);
});
};
<container-custom render={render}>
{/* 循环渲染 */}
{items.map((item, i) => (
<sprite x={i * 60} y={0} />
))}
</container-custom>;
```

View File

@ -0,0 +1,202 @@
# g-bezier 标签 API 文档
本文档由 `DeepSeek R1` 模型生成并微调。
---
```mermaid
graph LR
BezierProps --> GraphicBaseProps --> BaseProps
click GraphicBaseProps "./GraphicBaseProps"
click BaseProps "./BaseProps"
```
---
## 接口定义
```typescript
interface BezierProps extends GraphicBaseProps {
sx?: number; // 起点X坐标
sy?: number; // 起点Y坐标
cp1x?: number; // 第一控制点X坐标
cp1y?: number; // 第一控制点Y坐标
cp2x?: number; // 第二控制点X坐标
cp2y?: number; // 第二控制点Y坐标
ex?: number; // 终点X坐标
ey?: number; // 终点Y坐标
curve?: BezierParams; // 简写属性 [sx, sy, cp1x, cp1y, cp2x, cp2y, ex, ey]
}
```
---
## 核心属性说明
| 属性 | 类型 | 默认值 | 说明 |
| ------- | ------------------------------------------ | ------ | ------------------------------------- |
| `sx` | `number` | - | 曲线起点 X 坐标(单位:像素) |
| `sy` | `number` | - | 曲线起点 Y 坐标(单位:像素) |
| `cp1x` | `number` | - | 第一控制点 X 坐标(影响曲线起始方向) |
| `cp1y` | `number` | - | 第一控制点 Y 坐标 |
| `cp2x` | `number` | - | 第二控制点 X 坐标(影响曲线结束方向) |
| `cp2y` | `number` | - | 第二控制点 Y 坐标 |
| `ex` | `number` | - | 曲线终点 X 坐标 |
| `ey` | `number` | - | 曲线终点 Y 坐标 |
| `curve` | `[sx, sy, cp1x, cp1y, cp2x, cp2y, ex, ey]` | - | 简写属性:一次性定义全部坐标点 |
---
## 完整示例集
### 示例 1基础三次贝塞尔曲线
```tsx
// 曲线默认仅描边,不需要单独设置 stroke 属性
<g-bezier
sx={100} // 起点 (100, 300)
sy={300}
cp1x={200} // 第一控制点 (200, 100)
cp1y={100}
cp2x={400} // 第二控制点 (400, 500)
cp2y={500}
ex={500} // 终点 (500, 300)
ey={300}
strokeStyle="#e74c3c"
strokeWidth={3}
/>
```
---
### 示例 2虚线波浪线
```tsx
<g-bezier
curve={[50, 200, 150, 50, 250, 350, 350, 200]} // 简写属性定义
stroke={true}
strokeStyle="#3498db"
strokeWidth={2}
lineDash={[10, 5]} // 虚线样式
lineCap="round" // 圆角端点
/>
```
**曲线形态**
- 起点 (50,200) → 第一控制点 (150,50)
- 第二控制点 (250,350) → 终点 (350,200)
- 形成"S"型波浪线
---
### 示例 3动态流体效果
```tsx
import { ref } from 'vue';
const offset = ref(0);
// 每帧更新控制点位置
onTick(() => {
offset.value += 0.02;
});
<g-bezier
sx={100}
sy={400}
cp1x={200 + Math.sin(offset.value) * 30} // 水平波动
cp1y={300 + Math.cos(offset.value) * 50} // 垂直波动
cp2x={400}
cp2y={500}
ex={500}
ey={400}
strokeStyle={`hsl(${offset * 50}, 70%, 50%)`} // 变化的颜色
strokeWidth={4}
/>;
```
---
## 控制点行为说明
### 控制点影响示意图
```typescript
/*
(cp1)
|
(start)●━━╋━━━━━━━━━━━┓
┃ ┃
┃ (cp2) ┃
┃ ▼ ┃
┗━━━━━━━●━━(end)
*/
```
- **第一控制点** (`cp1`):控制曲线起始方向的弯曲程度
- **第二控制点** (`cp2`):控制曲线结束方向的弯曲程度
### 特殊形态案例
| 控制点布局 | 曲线形态描述 |
| ------------------------------------ | ----------------- |
| `cp1`靠近起点,`cp2`靠近终点 | 近似直线 |
| `cp1`与`cp2`对称分布 | 形成对称波浪 |
| `cp1`在起点正上方,`cp2`在终点正下方 | 创建垂直"S"型曲线 |
---
## 高级用法示例
### 复杂路径组合
```tsx
// 组合多条贝塞尔曲线形成花瓣造型
<container x={400} y={300}>
{Array.from({ length: 5 }).map((_, i) => (
<g-bezier
key={i}
curve={[
0,
0, // 起点(中心)
Math.cos(angle) * 80, // cp1外层控制点
Math.sin(angle) * 80,
Math.cos(angle + Math.PI / 5) * 120, // cp2花瓣尖端控制点
Math.sin(angle + Math.PI / 5) * 120,
Math.cos(angle + Math.PI / 2.5) * 80, // 终点(对称点)
Math.sin(angle + Math.PI / 2.5) * 80
]}
fill
stroke
strokeStyle="#e84393"
fillStyle="rgba(232,67,147,0.3)"
rotate={((Math.PI * 2) / 5) * i} // 旋转复制
/>
))}
</container>
```
---
## 注意事项
1. **闭合路径**
三次贝塞尔曲线默认不闭合,如需闭合需手动连接到起点:
```tsx
<g-bezier
curve={[100, 100, 200, 50, 300, 150, 100, 100]} // 终点回到起点
fill // 自动闭合填充
/>
```
2. **控制点极值**
当控制点距离起点/终点过远时可能产生剧烈弯曲:
```tsx
// 可能产生非预期锐角
<g-bezier cp1x={sx + 500} .../>
```

View File

@ -0,0 +1,182 @@
# g-circle 标签 API 文档
本文档由 `DeepSeek R1` 模型生成并微调。
---
```mermaid
graph LR
CircleProps --> GraphicBaseProps --> BaseProps
click GraphicBaseProps "./GraphicBaseProps"
click BaseProps "./BaseProps"
```
---
## 接口定义
```typescript
interface CircleProps extends GraphicBaseProps {
radius?: number; // 圆的半径
start?: number; // 起始角度(单位:弧度)
end?: number; // 结束角度(单位:弧度)
circle?: CircleParams; // 简写属性 [x, y, radius, start?, end?],后两项要么都填,要么都不填
}
```
---
## 核心属性说明
| 属性 | 类型 | 默认值 | 说明 |
| -------- | ------------------------- | ------ | ---------------------------------------------------------- |
| `radius` | `number` | - | 圆的半径(单位:像素) |
| `start` | `number` | `0` | 起始角度弧度0 弧度 = 3 点钟方向(水平向右) |
| `end` | `number` | `2π` | 结束角度(弧度),默认完整圆 |
| `circle` | `[x, y, r, start?, end?]` | - | 简写属性:<br>`[圆心x, 圆心y, 半径, 起始角度?, 结束角度?]` |
---
## 完整示例集
### 示例 1基础圆形填充
```tsx
<g-circle
x={100} // 圆心x坐标
y={100} // 圆心y坐标
radius={50} // 半径50px
fill // 启用填充
fillStyle="#ff7675" // 珊瑚红色
/>
```
---
### 示例 2描边圆形
```tsx
<g-circle
circle={[300, 200, 60]} // 简写属性 [x,y,radius]
stroke // 启用描边
strokeStyle="#0984e3" // 蓝色描边
strokeWidth={5} // 5px宽描边
/>
```
---
### 示例 3弓形填充闭合
```tsx
<g-circle
// 起始角度90度12点钟方向 结束角度180度9点钟方向
circle={[500, 300, 80, Math.PI / 2, Math.PI]}
fill
fillStyle="#55efc4" // 薄荷绿填充
/>
```
**角度说明**
- 绘制方向:**顺时针**(从 12 点走向 9 点)
- 自动闭合路径形成扇形
---
### 示例 4圆弧非闭合
```tsx
<g-circle
circle={[200, 400, 70, Math.PI / 4, Math.PI * 1.5]} // [x,y,r,start,end]
stroke // 仅描边
strokeStyle="#d63031" // 红色描边
strokeWidth={3}
/>
```
**路径特征**
- 起始角度45 度(右上对角线方向)
- 结束角度270 度12 点钟方向)
- 开环不闭合,形成月牙形弧线
---
## 角度系统详解
### 坐标系与方向
```typescript
// 0弧度基准点与绘制方向示意图
/*
Math.PI / 2 (90°)
|
|
Math.PI (180°) ——+—— 0 (0°)
|
|
Math.PI * 3 / 2 (270°)
*/
```
- **0 弧度基准**3 点钟方向(与浏览器 Canvas API 完全一致)
- **绘制方向**:角度递增为顺时针方向(`start=0, end=Math.PI/2` 绘制右下四分之一圆)
### 特殊角度对照表
| 弧度值 | 角度值 | 方向 |
| ------------- | ------ | ------ |
| `0` | 0° | 正右 → |
| `Math.PI/2` | 90° | 正上 ↑ |
| `Math.PI` | 180° | 正左 ← |
| `3*Math.PI/2` | 270° | 正下 ↓ |
---
## 高级用法示例
### 动态进度环
```tsx
import { ref } from 'vue';
import { onTick } from '@motajs/render-vue';
const progress = ref(0);
// 每帧更新进度
onTick(() => {
progress.value += 0.01;
});
<g-circle
circle={[400, 400, 100]}
start={-Math.PI / 2} // 从12点开始
end={-Math.PI / 2 + progress.value * Math.PI * 2} // 顺时针增长
stroke
strokeStyle="#00b894"
strokeWidth={15}
lineCap="round" // 圆角端点
/>;
```
**效果**
- 0%时从顶部开始
- 进度条顺时针增长
- 圆角端点消除锯齿
---
## 注意事项
1. **简写属性优先级**
```tsx
// 谁最后设置用谁的
<g-circle
x={100} // 被覆盖
circle={[200, 300, 50]} // 实际生效坐标 (200,300)
/>
```

View File

@ -0,0 +1,175 @@
# g-ellipse 标签 API 文档
本文档由 `DeepSeek R1` 模型生成并微调。
---
```mermaid
graph LR
EllipseProps --> GraphicBaseProps --> BaseProps
click GraphicBaseProps "./GraphicBaseProps"
click BaseProps "./BaseProps"
```
---
## 接口定义
```typescript
interface EllipseProps extends GraphicBaseProps {
radiusX?: number; // 椭圆X轴半径
radiusY?: number; // 椭圆Y轴半径
start?: number; // 起始角度(单位:弧度)
end?: number; // 结束角度(单位:弧度)
ellipse?: EllipseParams; // 简写属性 [x, y, rx, ry, start?, end?]
}
```
---
## 核心属性说明
| 属性 | 类型 | 默认值 | 说明 |
| --------- | ------------------------------ | ------ | ------------------------------------------------------------------ |
| `radiusX` | `number` | - | 椭圆 X 轴半径(单位:像素) |
| `radiusY` | `number` | - | 椭圆 Y 轴半径(单位:像素) |
| `start` | `number` | `0` | 起始角度弧度0 弧度 = 3 点钟方向 |
| `end` | `number` | `2π` | 结束角度(弧度),默认完整椭圆 |
| `ellipse` | `[x, y, rx, ry, start?, end?]` | - | 简写属性:<br>`[圆心x, 圆心y, X半径, Y半径, 起始角度?, 结束角度?]` |
---
## 完整示例集
### 示例 1基础椭圆填充
```tsx
<g-ellipse
ellipse={[200, 150, 100, 60]} // X轴半径100px Y轴半径60px
fill // 启用填充
fillStyle="#a55eea" // 紫色填充
/>
```
---
### 示例 2描边椭圆
```tsx
<g-ellipse
ellipse={[400, 300, 80, 40]} // 简写属性 [x,y,rx,ry]
stroke // 启用描边
strokeStyle="#2d98da" // 蓝色描边
strokeWidth={3} // 3px宽描边
lineDash={[10, 5]} // 虚线样式
/>
```
---
### 示例 3椭圆弓形闭合
```tsx
<g-ellipse
ellipse={[600, 200, 120, 80, Math.PI / 4, Math.PI * 1.25]}
fill
fillStyle="#fd9644" // 橙色填充
/>
```
**角度说明**
- 绘制方向:**顺时针**(从 45 度到 225 度)
- 自动闭合路径形成扇形
- 若路径自相交,`evenodd` 规则会生成镂空
---
### 示例 4椭圆弧线非闭合
```tsx
<g-ellipse
ellipse={[300, 400, 150, 50, -Math.PI / 2, Math.PI / 2]} // 从12点到6点
stroke
strokeStyle="#eb3b5a" // 红色描边
strokeWidth={5}
lineCap="round" // 圆角端点
/>
```
**路径特征**
- 垂直方向椭圆弧X 半径 > Y 半径)
- 起始角度:-90 度12 点方向)
- 结束角度90 度6 点方向)
- 开环形成对称弧线
---
## 角度系统详解
### 坐标系与方向
```typescript
// 角度系统与圆形一致,但受半径比例影响:
/*
radiusY
|
radiusX +---→
*/
```
- **0 弧度基准**3 点钟方向(与浏览器 Canvas API 一致)
- **半径影响**:当 `radiusX ≠ radiusY` 时,相同角度对应的端点位置会拉伸
- **绘制方向**:角度递增为顺时针方向
### 特殊角度效果
| 参数组合 | 效果描述 |
| ---------------------------------- | ------------------------ |
| `radiusX=radiusY` | 退化为标准圆形 |
| `start=0, end=Math.PI` | 右半椭圆(水平方向半圆) |
| `start=Math.PI/2, end=3*Math.PI/2` | 上半椭圆(垂直方向半圆) |
---
## 高级用法示例
### 动态仪表盘
```tsx
import { ref } from 'vue';
const value = ref(0.3);
<g-ellipse
ellipse={[500, 500, 200, 100]}
start={-Math.PI / 2 - Math.PI / 4} // 起始角度:-135度左上方
end={-Math.PI / 2 - Math.PI / 4 + value.value * Math.PI * 1.5} // 按比例延伸
stroke
strokeStyle="#4b7bec"
strokeWidth={20}
lineCap="round"
/>;
```
**效果**
- 椭圆弧仪表盘,从左上方向右侧延伸
- 进度值 `0.3` 时覆盖 30%路径
---
## 注意事项
1. **简写属性优先级**
```tsx
// 谁最后被设置用谁的
<g-ellipse
radiusX={100} // 被覆盖
ellipse={[200, 200, 150, 80]} // 实际生效 rx=150, ry=80
/>
```

View File

@ -0,0 +1,125 @@
# g-line 标签 API 文档
本文档由 `DeepSeek R1` 模型生成并微调。
---
```mermaid
graph LR
LineProps --> GraphicBaseProps --> BaseProps
click GraphicBaseProps "./GraphicBaseProps"
click BaseProps "./BaseProps"
```
---
## 接口定义
```typescript
interface LineProps extends GraphicBaseProps {
x1?: number; // 起点X坐标
y1?: number; // 起点Y坐标
x2?: number; // 终点X坐标
y2?: number; // 终点Y坐标
line?: LineParams; // 简写属性 [x1, y1, x2, y2]
}
```
---
## 核心属性说明
| 属性 | 类型 | 默认值 | 说明 |
| ---------- | ----------------------------------- | -------- | ---------------------------------------------- |
| `x1` | `number` | - | 线段起点 X 坐标(单位:像素) |
| `y1` | `number` | - | 线段起点 Y 坐标(单位:像素) |
| `x2` | `number` | - | 线段终点 X 坐标(单位:像素) |
| `y2` | `number` | - | 线段终点 Y 坐标(单位:像素) |
| `line` | `[x1, y1, x2, y2]` | - | 简写属性:一次性定义起点和终点坐标 |
| `lineDash` | `number[]` | - | 虚线模式(如 `[5, 3]` 表示 5px 实线+3px 间隙) |
| `lineCap` | `"butt"` \| `"round"` \| `"square"` | `"butt"` | 线段端点样式 |
---
## 完整示例集
### 示例 1基础实线
```tsx
// 线段默认就是仅描边,因此不需要单独设置 stroke 属性
<g-line
line={[100, 50, 300, 50]} // 起点坐标 (100, 50) 终点坐标 (300, 50)
strokeStyle="#2d98da" // 蓝色
strokeWidth={3} // 3px宽度
/>
```
---
### 示例 2虚线线段
```tsx
<g-line
line={[50, 150, 400, 150]} // 简写属性定义起点终点
strokeStyle="#eb3b5a" // 红色
strokeWidth={2}
lineDash={[10, 5]} // 10px实线 + 5px间隙
lineCap="round" // 圆角端点
/>
```
**效果说明**
- 水平红色虚线
- 线段端点呈圆形
---
### 示例 3动态线段动画
```tsx
import { transitioned } from '@user/client-modules';
// 创建渐变
const x2 = transitioned(100, 2000, linear());
x2.set(400); // 终点横坐标从 100 变到 400
return () => (
<g-line
line={[100, 300, x2.ref.value, 300]}
strokeStyle="#10ac84"
strokeWidth={4}
/>
);
```
**动态效果**
- 线段从 100px 位置向右延伸至 400px
- 2 秒完成动画
---
## 线段样式对照表
| 样式组合 | 效果图示 |
| --------------------- | ----------------- |
| `lineCap="butt"` | 平头端点:⎯ |
| `lineCap="round"` | 圆头端点:⭘―――――⭘ |
| `lineCap="square"` | 方头端点:▯―――――▯ |
| `lineDash=[20,5,5,5]` | 复杂虚线:━━⧀┄⧀┄ |
---
## 注意事项
1. **坐标系差异**
线段坐标基于父容器坐标系,如需相对定位建议嵌套在`container`中:
```tsx
<container x={100} y={100}>
{/* 实际坐标为 (100,100)→(150,150) */}
<g-line line={[0, 0, 50, 50]} />
</container>
```

View File

@ -0,0 +1,173 @@
# g-path 标签 API 文档
本文档由 `DeepSeek R1` 模型生成并微调。
---
```mermaid
graph LR
PathProps --> GraphicBaseProps --> BaseProps
click GraphicBaseProps "./GraphicBaseProps"
click BaseProps "./BaseProps"
```
---
## 接口定义
```typescript
interface PathProps extends GraphicBaseProps {
path?: Path2D; // 自定义路径对象
}
```
---
## 核心属性说明
| 属性 | 类型 | 默认值 | 说明 |
| -------------- | -------------------------- | ----------- | -------------------------------------------------- |
| `path` | `Path2D` | - | 自定义矢量路径(支持多路径、贝塞尔曲线等复杂形状) |
| `fillRule` | `"nonzero"` \| `"evenodd"` | `"evenodd"` | 填充规则(影响路径重叠区域的渲染) |
| `actionStroke` | `boolean` | `false` | 设为 `true` 时,交互事件仅检测描边区域 |
---
## 完整示例集
### 示例 1复杂星形路径
```tsx
// 创建五角星路径
const starPath = new Path2D();
for (let i = 0; i < 5; i++) {
const angle = (i * 2 * Math.PI) / 5 - Math.PI / 2;
const x = 100 + Math.cos(angle) * 50;
const y = 100 + Math.sin(angle) * 50;
if (i === 0) starPath.moveTo(x, y);
else starPath.lineTo(x, y);
}
starPath.closePath();
<g-path
x={200}
y={200}
path={starPath}
fill
stroke
fillStyle="#f1c40f"
fillRule="evenodd" // 使用奇偶环绕原则,使中心镂空
strokeStyle="#e67e22"
strokeWidth={3}
/>;
```
**效果说明**
- 使用`evenodd`规则自动产生星形镂空效果
- 金色填充+橙色描边的五角星
---
### 示例 2交互式描边检测
```tsx
import { ref } from 'vue';
const [clicked, setClicked] = useState(false);
const clicked = ref(false);
// 创建对话气泡路径
const bubblePath = new Path2D();
bubblePath.moveTo(50, 20);
bubblePath.quadraticCurveTo(25, 0, 0, 20);
bubblePath.quadraticCurveTo(25, 40, 50, 20);
bubblePath.rect(0, 20, 200, 100);
const click = () => void (clicked.value = !click.value);
<g-path
path={bubblePath}
fillStyle={clicked.value ? '#ffffff' : '#ecf0f1'}
strokeStyle="#bdc3c7"
strokeWidth={2}
actionStroke // 仅描边区域可交互
onClick={click}
/>;
```
**交互特性**
- 点击描边区域切换填充颜色
- 内部区域不响应点击事件
---
### 示例 3组合路径齿轮造型
```tsx
const gearPath = new Path2D();
// 主体圆形
gearPath.arc(100, 100, 80, 0, Math.PI * 2);
// 添加8个齿牙
for (let i = 0; i < 8; i++) {
const angle = ((Math.PI * 2) / 8) * i;
gearPath.moveTo(100 + Math.cos(angle) * 90, 100 + Math.sin(angle) * 90);
gearPath.lineTo(
100 + Math.cos(angle + Math.PI / 8) * 110,
100 + Math.sin(angle + Math.PI / 8) * 110
);
gearPath.lineTo(
100 + Math.cos(angle - Math.PI / 8) * 110,
100 + Math.sin(angle - Math.PI / 8) * 110
);
}
<g-path
path={gearPath}
fill
stroke
fillStyle="#2c3e50"
fillRule="nonzero" // 非零规则填充
strokeStyle="#34495e"
strokeWidth={5}
lineJoin="miter" // 尖角连接
/>;
```
---
## 高级用法示例
### SVG 路径转换
```tsx
// 将SVG路径转换为Path2D
const svgPath = 'M10 80 C 40 10, 65 10, 95 80 S 150 150, 180 80';
const path = new Path2D(svgPath);
<g-path
path={path}
stroke
strokeStyle="#e74c3c"
strokeWidth={3}
lineDash={[10, 5]}
lineCap="round"
/>;
```
---
## 注意事项
1. **路径闭合**
```tsx
// 必须显式闭合路径才能正确填充
const path = new Path2D();
path.moveTo(0, 0);
path.lineTo(100, 0);
path.lineTo(100, 100);
path.closePath(); // 关键闭合操作
```

View File

@ -0,0 +1,119 @@
# g-quad 标签 API 文档
本文档由 `DeepSeek R1` 模型生成并微调。
---
```mermaid
graph LR
QuadraticProps --> GraphicBaseProps --> BaseProps
click GraphicBaseProps "./GraphicBaseProps"
click BaseProps "./BaseProps"
```
---
## 接口定义
```typescript
interface QuadraticProps extends GraphicBaseProps {
sx?: number; // 起点X坐标
sy?: number; // 起点Y坐标
cpx?: number; // 控制点X坐标
cpy?: number; // 控制点Y坐标
ex?: number; // 终点X坐标
ey?: number; // 终点Y坐标
curve?: QuadParams; // 简写属性 [sx, sy, cpx, cpy, ex, ey]
}
```
---
## 核心属性说明
| 属性 | 类型 | 默认值 | 说明 |
| ------- | ---------------------------- | ------ | --------------------------------------- |
| `sx` | `number` | - | 曲线起点 X 坐标(单位:像素) |
| `sy` | `number` | - | 曲线起点 Y 坐标(单位:像素) |
| `cpx` | `number` | - | 控制点 X 坐标(决定曲线弯曲方向和程度) |
| `cpy` | `number` | - | 控制点 Y 坐标 |
| `ex` | `number` | - | 曲线终点 X 坐标 |
| `ey` | `number` | - | 曲线终点 Y 坐标 |
| `curve` | `[sx, sy, cpx, cpy, ex, ey]` | - | 简写属性:一次性定义全部坐标点 |
---
## 完整示例集
### 示例 1基础二次贝塞尔曲线
```tsx
<g-quad
sx={100} // 起点 (100, 300)
sy={300}
cpx={300} // 控制点 (300, 100)
cpy={100}
ex={500} // 终点 (500, 300)
ey={300}
strokeStyle="#2ecc71" // 绿色
strokeWidth={3}
/>
```
---
### 示例 2虚线抛物线
```tsx
<g-quad
curve={[50, 400, 250, 100, 450, 400]} // 简写属性定义
strokeStyle="#f1c40f" // 黄色
strokeWidth={2}
lineDash={[15, 5]} // 长虚线样式
/>
```
**曲线形态**
- 起点 (50,400) → 控制点 (250,100) → 终点 (450,400)
- 形成对称的类似抛物线形状的曲线
---
## 控制点行为说明
### 控制点影响示意图
```typescript
/*
(cpx,cpy)
/ \
/ \
(start) ●-----●(end)
*/
```
- **单控制点**:二次贝塞尔曲线仅有一个控制点,同时影响曲线的起始和结束方向
- **对称性**:控制点距离起点/终点的垂直距离越大,曲线弯曲越明显
### 特殊形态案例
| 控制点布局 | 曲线形态描述 |
| ------------------------ | ------------- |
| 控制点在起点终点连线中点 | 退化为直线 |
| 控制点在起点正上方 | 形成"U"型曲线 |
| 控制点在终点右侧 | 形成"C"型曲线 |
---
## 注意事项
1. **控制点极限值**
当控制点与起点/终点距离过大时可能产生锐角:
```tsx
// 可能产生非预期的尖角形态
<g-quad cpx={sx + 1000} .../>
```

View File

@ -0,0 +1,91 @@
# g-rect 标签 API 文档
本文档由 `DeepSeek R1` 模型生成并微调。
---
```mermaid
graph LR
RectProps --> GraphicBaseProps --> BaseProps
click GraphicBaseProps "./GraphicBaseProps"
click BaseProps "./BaseProps"
```
---
## 使用示例
### 示例 1仅填充模式
```tsx
<g-rect
loc={[100, 100, 200, 150]} // x,y,width,height
fill
fillStyle="#fff"
/>
```
**效果**
- 200x150 矩形
- 无描边效果
---
### 示例 2仅描边模式
```tsx
<g-rect
loc={[400, 200, 180, 120]}
stroke
strokeStyle="rgba(0,0,0,0.8)"
strokeWidth={4}
actionStroke // 点击时仅描边区域响应
/>
```
**交互特性**
- 4px 黑色半透明描边
- 鼠标悬停在描边区域才会触发事件
---
### 示例 3填充 + 描边(默认顺序)
```tsx
<g-rect
loc={[50, 300, 150, 100]}
fill
stroke
fillStyle="#ffe66d"
strokeStyle="#2d3436"
strokeWidth={2}
/>
```
**渲染顺序**
1. 填充黄色背景
2. 在填充层上绘制黑色描边
---
### 示例 4强制先描边后填充
```tsx
<g-rect
loc={[300, 400, 200, 200]}
strokeAndFill
fillStyle="#a29bfe"
strokeStyle="#6c5ce7"
strokeWidth={8}
/>
```
**渲染顺序**
1. 绘制紫色描边
2. 在描边层上填充浅紫色
**视觉效果**:描边被填充色覆盖一部分

View File

@ -0,0 +1,167 @@
# g-rectr 标签 API 文档
本文档由 `DeepSeek R1` 模型生成并微调。
---
```mermaid
graph LR
RectRProps --> GraphicBaseProps --> BaseProps
click GraphicBaseProps "./GraphicBaseProps"
click BaseProps "./BaseProps"
```
---
## 接口定义
```typescript
interface RectRProps extends GraphicBaseProps {
/**
* 圆形圆角参数 [左上, 右上, 右下, 左下]
* - 1个值全角相同
* - 2个值左上+右下 / 右上+左下
* - 3个值左上 / 右上+左下 / 右下
* - 4个值分别设置四个角 左上、右上、左下、右下
*/
circle?: RectRCircleParams;
/**
* 椭圆圆角参数 [x半径, y半径, ...]
* - 1组全角相同
* - 2组左上+右下 / 右上+左下
* - 3组左上 / 右上+左下 / 右下
* - 4组分别设置四个角 左上、右上、左下、右下
*/
ellipse?: RectREllipseParams;
}
```
---
## 核心行为规则
- **参数限制**:若圆角值超过 `width/height` 的 50% 或为负数,将自动修正:
- 负值 → 修正为 0
- 超过 50% → 修正为 50%
- **参数优先级**`ellipse` 优先级高于 `circle`
---
## 完整示例集
### 示例 1统一圆形圆角
```tsx
<g-rectr
loc={[100, 100, 300, 200]} // x,y,width,height
circle={[20]} // 所有角20px半径
fill
fillStyle="#3498db"
/>
```
---
### 示例 2差异圆形圆角
```tsx
<g-rectr
loc={[500, 200, 250, 150]}
circle={[30, 15, 50, 0]} // 左上30px, 右上15px, 右下50px, 左下0px
stroke
strokeStyle="#2c3e50"
strokeWidth={4}
/>
```
---
### 示例 3椭圆圆角
```tsx
<g-rectr
loc={[100, 400, 200, 100]}
ellipse={[30, 20, 10, 40]} // 左上+右下(30,20), 右上+左下(10,40)
fillStyle="#e74c3c"
fillRule="nonzero"
/>
```
---
### 示例 4混合椭圆圆角
```tsx
<g-rectr
loc={[500, 400, 300, 200]}
ellipse={[
80,
50, // 左上水平80px 垂直50px
40,
100, // 右上水平40px 垂直100px
120,
30, // 右下水平120px 垂直30px
60,
80 // 左下水平60px 垂直80px
]}
fillStyle="#2ecc71"
strokeWidth={2}
/>
```
---
## 参数对照表
### 圆形圆角circle参数规则
| 参数数量 | 生效规则 |
| -------- | -------------------------------------------- |
| 1 | 全角相同:`[20] → [20,20,20,20]` |
| 2 | 对角对称:`[10,30] → [10,30,30,10]` |
| 3 | 左上/对角/右下:`[10,20,30] → [10,20,30,20]` |
| 4 | 独立设置四个角:`[10,20,30,40]` |
### 椭圆圆角ellipse参数规则
| 参数组数 | 生效规则 |
| -------- | ---------------------------------------------- |
| 1 | 全角相同:`[15,20] → 四角均为15x20` |
| 2 | 对角对称:`[10,5,20,10] → 左上+右下/右上+左下` |
| 3 | 左上/对角/右下:`[10,20,15,5,20,10]` |
| 4 | 独立设置四个角:`[10,20,15,25,20,30,5,10]` |
---
## 错误处理示例
```tsx
// 危险参数示例
<g-rectr
loc={[0, 0, 100, 50]}
circle={[-10, 200]} // 输入 [-10, 200]
stroke={true}
/>
```
**实际生效值**
- 负值修正:`-10 → 0`
- 超限修正:`200 → min(200, 50/2=25) → 25px`
- 最终参数:`[0,25] → [0,25,25,0]`
---
## 最佳实践建议
1. **响应式圆角**
```tsx
// 圆角随尺寸变化
<g-rectr
loc={[x, y, width.value, height]}
circle={[width.value * 0.1]} // 圆角为宽度的10%
/>
```

View File

@ -0,0 +1,121 @@
# icon 标签 API 文档
本文档由 `DeepSeek R1` 模型生成并微调。
---
```mermaid
graph LR
IconProps --> BaseProps
click BaseProps "./BaseProps"
```
---
## 接口定义
```typescript
interface IconProps extends BaseProps {
icon: AllNumbers | AllIds; // 图标ID或数字标识
frame?: number; // 显示指定帧从0开始计数
animate?: boolean; // 是否启用帧动画循环默认false
}
```
---
## 核心属性说明
| 属性 | 类型 | 默认值 | 说明 |
| --------- | -------------------- | -------- | ------------------------------------------------------ |
| `icon` | `number` \| `string` | **必填** | 图标资源标识符(对应素材库中的图块 ID 或预设数字编码) |
| `frame` | `number` | `0` | 指定显示的帧序号(当`animate=false`时生效) |
| `animate` | `boolean` | `false` | 启用自动播放帧动画(优先级高于`frame`参数) |
---
## 完整示例集
### 示例 1静态显示指定帧
```tsx
// 显示图块ID为"greenSlime"的第3帧索引从0开始
<icon
loc={[100, 200]}
icon="greenSlime" // 图标资源ID
frame={2} // 显示第3帧
/>
```
---
### 示例 2动态帧动画
```tsx
// 自动播放4帧循环动画
<icon
loc={[300, 150]} // x=300, y=150
icon={100} // 数字编码图标
animate // 启用自动播放
/>
```
**动画行为**
- 播放图标自带的 4 帧动画序列0→1→2→3→0...
- 动画速度由素材预设帧率决定
---
### 示例 3交互控制动画
```tsx
import { ref } from 'vue';
const animating = ref(false);
const click = () => void (animating.value = false);
// 点击切换动画状态
<icon
loc={[500, 300]}
icon="yellowDoor"
animate={animating.value}
frame={0} // 动画停止时显示第1帧
cursor="pointer"
onClick={click}
/>;
```
**交互逻辑**
- 初始状态显示第 1 帧(门关闭)
- 点击后播放开门动画
---
## 帧动画系统规则
### 帧索引定义
```typescript
// 图块素材帧结构示例
/*
[0] [1] [2] [3]
+---+---+---+---+
| | | | | // 4帧水平排列的图块素材
+---+---+---+---+
*/
```
- **播放方向**:始终从 `0` 帧开始正向循环
- **循环模式**:播放到最后一帧后回到第 `0`
### 参数限制
| 场景 | 系统行为 |
| ----------------------------- | ------------------------------------- |
| `frame` 超过最大帧数 | 报错 |
| `frame` 为负数 | 报错 |
| `animate=true` 时修改 `frame` | `frame` 参数被忽略,始终从 0 开始播放 |

View File

@ -0,0 +1,103 @@
# image 标签 API 文档
本文档由 `DeepSeek R1` 模型生成并微调。
---
```mermaid
graph LR
ImageProps --> BaseProps
click BaseProps "./BaseProps"
```
---
## 接口定义
```typescript
interface ImageProps extends BaseProps {
/** 必填 - 图片对象CanvasImageSource 类型) */
image: CanvasImageSource;
}
```
---
## 核心功能
- **尺寸控制**:通过 `width/height``loc` 简写属性定义图片尺寸(默认 200x200
- **像素风支持**:通过 `noanti=true` 禁用抗锯齿
---
## 使用示例
### 示例 1基础图片显示
```tsx
const image = core.material.images.images['myimage.webp'];
// 显示 200x200 的默认尺寸图片
<image x={100} y={50} image={image} />;
```
**等效简写**
```tsx
const image = core.material.images.images['myimage.webp'];
<image
loc={[100, 50]} // width/height 使用默认 200x200
image={image}
/>;
```
---
### 示例 2自定义尺寸
```tsx
const image = core.material.images.images['myimage.webp'];
// 方式一:直接设置宽高
<image
x={300}
y={200}
width={150} // 覆盖默认宽度
height={80} // 覆盖默认高度
image={image}
/>;
// 方式二:通过 loc 简写属性
<image
loc={[500, 200, 120, 120]} // [x, y, width, height]
image={image}
/>;
```
---
### 示例 3像素风渲染禁用抗锯齿
```tsx
const pixelImage = core.material.images.images['myimage.webp'];
// 硬核像素风格配置
<image
loc={[50, 50, 64, 64]}
image={pixelImage}
noanti // 关键配置:关闭抗锯齿
/>;
```
**效果说明**
- 原始 32x32 像素图 → 放大为 64x64 像素
- 每个像素块保持锐利边缘
---
## 属性配置表
| 属性 | 类型 | 默认值 | 说明 |
| ------- | ------------------- | -------- | ------------------------------------------- |
| `image` | `CanvasImageSource` | **必填** | 图片资源ImageBitmap/HTMLImageElement 等) |

View File

@ -0,0 +1,148 @@
# sprite 标签 API 文档
本文档由 `DeepSeek R1` 模型生成并微调。
---
```mermaid
graph LR
SpriteProps --> BaseProps
click BaseProps "./BaseProps"
```
---
## 接口定义
```typescript
interface SpriteProps extends BaseProps {
/**
* 自定义渲染函数
* @param canvas - 离屏画布对象
* @param transform - 当前元素相对于父元素的变换矩阵
*/
render?: (canvas: MotaOffscreenCanvas2D, transform: Transform) => void;
}
```
---
## 核心能力
通过 `render` 函数实现 **动态绘制**,可结合:
- 基础定位/变换参数(继承 `BaseProps`
- 动画系统(`useAnimation`
- 帧回调(`onTick`
- 自定义图形绘制(路径/滤镜/混合模式)
**注意**,这个标签虽然非常基础,但是应该并不常用,因为很多内容都有对应的标签可以实现(例如线可以使用 `g-line` 标签等),因此如果你在考虑使用此标签,请确认你必须使用它,或是你的场景对性能非常敏感。
---
## 使用示例
以下的示例代码均应该在**组件内部**编写,哪里是组件内部请参考[指南](../../guide/ui.md)。
### 示例 1基础图形
```tsx
import { MotaOffscreenCanvas2D } from '@motajs/render-core';
// 绘制旋转了 45 度的彩色方块
const render = (canvas: MotaOffscreenCanvas2D) => {
const ctx = canvas.ctx;
ctx.fillStyle = 'rgba(255,0,0,0.8)';
ctx.strokeStyle = 'blue';
ctx.lineWidth = 3;
ctx.beginPath();
ctx.rect(0, 0, 200, 200);
ctx.fill();
ctx.stroke();
};
<sprite x={200} y={200} rotate={Math.PI / 4} render={render} />;
```
**效果**
- 100x100 红色方块,中心点位于 (200,200)
- 45 度旋转,蓝色描边
- 80% 不透明度
---
### 示例 2结合动画系统
```tsx
import { ref } from 'vue';
import { useAnimation } from '@motajs/render-vue';
// 平移动画 + 动态缩放
const [anim] = useAnimation();
anim.time(2000).move(100, 0).scale(1.5);
const loc = ref<ElementLocator>([0, 0]);
const scale = ref<ElementScaler>([1, 1]);
onTick(() => {
loc.value = [anim.x, anim.y];
scale.value = [anim.size, anim.size];
});
const render = canvas => {
const ctx = canvas.ctx;
ctx.rect(0, 0, 200, 200);
ctx.fill();
};
return () => <sprite loc={loc.value} scale={scale.value} render={render} />;
```
**效果**
- 矩形横向放大 1.5 倍,横向位置移动 100px
- 2 秒线性动画
---
### 示例 3交互事件 + 滤镜
```tsx
import { ref } from 'vue';
// 悬浮模糊
const filter = ref('none');
const enter = () => {
filter.value = 'blur(2px)';
};
const leave = () => {
filter.value = 'none';
};
return () => (
<sprite
x={300}
y={200}
cursor="pointer"
filter={filter.value}
render={}
onEnter={enter}
onLeave={leave}
/>
);
```
**效果**
- 鼠标悬浮时添加模糊滤镜
- 鼠标悬浮显示指针光标
---
## 注意事项
1. **坐标系**`render` 函数内使用 **局部坐标系**,锚点变换已自动处理
2. **循环更新**:避免在 `render` 中循环更新自身

View File

@ -0,0 +1,160 @@
# TextProps API 文档
本文档由 `DeepSeek R1` 模型生成并微调。
---
```mermaid
graph LR
TextProps --> BaseProps
click BaseProps "./BaseProps"
```
---
## 接口定义
```typescript
interface TextProps extends BaseProps {
text?: string; // 显示的文字内容
fillStyle?: CanvasStyle; // 文字填充样式(颜色/渐变/图案)
strokeStyle?: CanvasStyle; // 文字描边样式
font?: Font; // 字体配置对象
strokeWidth?: number; // 描边宽度(单位:像素)
}
```
---
## 使用示例
### 1. 基本文本渲染
```tsx
import { Font } from '@motajs/render-style';
<text
loc={[100, 50]}
text="Hello World"
fillStyle="blue"
font={new Font('Arial', 24, 'px', 700)}
/>;
```
**效果**
- 在 (100,50) 位置显示蓝色 "Hello World"
- 使用 24px 粗体 Arial 字体
- 无描边效果
---
### 2. 描边文字 + 填充组合
```tsx
import { Font } from '@motajs/render-style';
<text
loc={[200, 300]} // x=200, y=300
text="MOTA Engine"
fillStyle="gold"
strokeStyle="rgba(0,0,0,0.8)"
strokeWidth={2}
font={new Font('Verdana', 32, 'px', 900, true)} // 斜体
/>;
```
**效果**
- 金色文字带黑色半透明描边
- 32px 加粗斜体 Verdana
- 2px 描边宽度
---
### 3. 动态更新文本
```tsx
import { ref } from 'vue';
import { Font } from '@motajs/render-style';
// Vue3 组件示例
const count = ref(0);
onTick(() => {
count.value++;
});
return () => (
<text
loc={[400, 100]}
text={`计时: ${count.value} 帧`}
fillStyle="#333"
font={new Font('Consolas', 28)}
/>
);
```
---
## 高级用法示例
### 文字路径动画
```tsx
import { ref } from 'vue';
import { Font, onTick } from '@motajs/render';
const offset = ref(0);
onTick(() => {
offset.value = (offset.value + 1) % 100;
});
<text
x={100 + Math.sin(offset.value * 0.1) * 50} // X轴波动
y={200 + offset.value}
text="动态文字"
fillStyle={`hsl(${offset.value * 3.6}, 80%, 50%)`} // 彩虹色
font={new Font('Comic Sans MS', 32)}
/>;
```
---
### 文字阴影 + 滤镜
```tsx
import { Font } from '@motajs/render-style';
<text
x={300}
y={400}
text="特效文字"
fillStyle="white"
font={new Font('Arial Black', 40)}
filter="drop-shadow(5px 5px 2px rgba(0,0,0,0.5)) blur(1px)"
strokeStyle="#333"
strokeWidth={1}
/>;
```
---
## 属性兼容性表
| 属性 | 是否继承 BaseProps | 动态更新支持 | 性能影响等级 |
| ------------- | ------------------ | ------------ | ------------ |
| `text` | 否 | ✔️ | 中 |
| `fillStyle` | 否 | ✔️ | 中 |
| `strokeStyle` | 否 | ✔️ | 中 |
| `font` | 否 | ✔️ | 高 |
| `strokeWidth` | 否 | ✔️ | 低 |
---
## 注意事项
1. 如果需要显示多行文本,考虑使用 [TextContent](../user-client-modules/TextContent.md)
2. 考虑到浏览器兼容性,不建议在颜色中填写一些新标准的语法,例如 `rgb(0.3, 0.6, 0.8 / 0.6)` `#rgba`

View File

@ -0,0 +1,117 @@
# winskin 标签 API 文档
本文档由 `DeepSeek R1` 模型生成并微调。
---
```mermaid
graph LR
WinskinProps --> BaseProps
click BaseProps "./BaseProps"
```
---
## 接口定义
```typescript
interface WinskinProps extends BaseProps {
/**
* 窗口皮肤图片资源ID
*/
image: ImageIds;
/**
* 边框粗细
* - 设置为 32 时表示原始大小16 像素宽度),默认为 32
* - 设为0时仅显示中心内容区
*/
borderSize?: number;
}
```
---
## 核心功能演示
### 示例 1基础窗口皮肤
```tsx
// 使用默认边框borderSize=32
<container>
<winskin
loc={[100, 100, 400, 300]} // x,y,width,height
image="winskin.png" // 预加载的皮肤图片ID
/>
<text x={120} y={120} text="对话框标题" />
<text x={130} y={160} text="这里是正文内容区域..." />
</container>
```
---
### 示例 2不同边框粗细对比
```tsx
// 细边框borderSize=16
<winskin loc={[50, 50, 200, 150]} image="winskin.png" borderSize={16} />;
// 粗边框borderSize=32
<winskin loc={[300, 50, 200, 150]} image="winskin.png" borderSize={32} />;
// 无边框borderSize=0
<winskin loc={[550, 50, 200, 150]} image="winskin.png" borderSize={0} />;
```
**效果差异**
- 细边框:内容区域更大,适合信息密集场景
- 粗边框:装饰性更强,适合标题窗口
- 无边框:仅保留中心纹理,适合全屏背景
---
## 九宫格原理示意图
```typescript
/*
+-------------------+
| 1 top 2 | ← borderSize
| |
| |
left | 4 center 3 | right
| |
| |
| 5 bottom 6 |
+-------------------+
*/
```
---
## 高级用法示例
### 动态边框动画
```tsx
import { hyper } from 'mutate-animate';
import { transitioned } from '@user/client-modules';
import { onTick } from '@motajs/render-vue';
const border = transitioned(16, 1000, hyper('sin', 'in-out'));
onTick(() => {
if (border.value === 16) border.set(32);
if (border.value === 32) border.set(16)
})
<container>
<winskin
loc={[200, 300, 400, 300]}
image="winskin.png"
borderSize={border.ref.value} // 边框呼吸动画效果
composite="lighter" // 发光混合模式
/>
<text x={20} y={20} text="魔法结界" font={magicFont} />
</container>;
```

View File

@ -0,0 +1,16 @@
# @motajs/render
此模块包含如下模块的内容,可以直接引用:
- [@motajs/render-core](../motajs-render-core/)
- [@motajs/render-elements](../motajs-render-elements/)
- [@motajs/render-style](../motajs-render-style/)
- [@motajs/render-vue](../motajs-render-vue/)
引入示例:
```ts
import { Container } from '@motajs/render';
// 二者等价,不需要单独使用一个量来接收,注意与 @motajs/client 引入方式区分
import { Container } from '@motajs/render-core';
```

View File

@ -0,0 +1,311 @@
# Hotkey API 文档
本文档由 `DeepSeek R1` 模型生成并微调。
```mermaid
graph LR
Hotkey --> EventEmitter
click EventEmitter "https://nodejs.org/api/events.html#class-eventemitter"
```
## 类描述
`Hotkey` 是按键系统的核心类,用于管理按键绑定、辅助键状态、按键分组及事件触发逻辑。继承自 `EventEmitter`,支持自定义事件监听。主要用于实现复杂的快捷键系统。
---
## 属性说明
| 属性名 | 类型 | 描述 |
| -------------- | ---------------------------- | -------------------------------------------- |
| `id` | `string` | 控制器的唯一标识符 |
| `name` | `string` | 控制器的显示名称 |
| `data` | `Record<string, HotkeyData>` | 存储所有已注册的按键配置 |
| `keyMap` | `Map<KeyCode, HotkeyData[]>` | 按键代码到配置的映射(支持多键绑定同一操作) |
| `enabled` | `boolean` | 当前控制器是否启用(默认 `false` |
| `list`(静态) | `Hotkey[]` | 静态属性,存储所有已创建的控制器实例 |
---
## 构造方法
```typescript
function constructor(id: string, name: string): Hotkey;
```
- **参数**
- `id`: 控制器的唯一标识符
- `name`: 控制器的显示名称
**示例**
```typescript
const editorHotkey = new Hotkey('editor', '编辑器快捷键');
```
---
## 方法说明
### `register`
```typescript
function register(data: RegisterHotkeyData): this;
```
注册一个按键配置。
- **参数**
```typescript
interface RegisterHotkeyData {
id: string; // 按键唯一标识(可含数字后缀,如 "copy_1"
name: string; // 显示名称(如 "复制"
defaults: KeyCode; // 默认按键代码
ctrl?: boolean; // 是否默认需要 Ctrl 辅助键
shift?: boolean; // 是否默认需要 Shift 辅助键
alt?: boolean; // 是否默认需要 Alt 辅助键
}
```
**示例**
```typescript
editorHotkey.register({
id: 'copy',
name: '复制',
defaults: KeyCode.KeyC,
ctrl: true
});
```
---
### `realize`
```typescript
function realize(id: string, func: HotkeyFunc, config?: HotkeyEmitConfig): this;
```
为按键绑定触发逻辑。
- **参数**
- `id`: 目标按键 ID无需后缀
- `func`: 触发时执行的函数
- `config`: 触发类型配置(节流/超时等)
**示例**
```typescript
editorHotkey.realize(
'copy',
(id, key, ev) => {
console.log('执行复制操作');
},
{ type: 'down-throttle', throttle: 500 }
);
```
---
### `group`
```typescript
function group(id: string, name: string, keys?: RegisterHotkeyData[]): this;
```
创建按键分组,后续注册的按键自动加入该组。
- **参数**
- `id`: 分组唯一标识
- `name`: 分组显示名称
- `keys`: 可选,预注册的按键列表
---
### `set`
```typescript
function set(id: string, key: KeyCode, assist: number, emit?: boolean): void;
```
动态修改按键绑定。
- **参数**
- `id`: 目标按键 ID
- `key`: 新按键代码
- `assist`: 辅助键状态二进制位Ctrl=1<<0, Shift=1<<1, Alt=1<<2
- `emit`: 是否触发 `set` 事件(默认 `true`
---
### `when`
```typescript
function when(fn: () => boolean): this;
```
为当前作用域的按键绑定添加触发条件。
- **参数**
- `fn`: 条件函数,返回 `true` 时允许触发按键逻辑
**示例**
```typescript
// 仅在游戏处于运行状态时允许触发
controller.when(() => gameState === 'running');
```
---
### `enable`
```typescript
function enable(): void;
```
### `disable`
```typescript
function disable(): void;
```
启用/禁用整个按键控制器(禁用后所有按键事件将被忽略)。
**示例**
```typescript
// 暂停游戏时禁用按键
controller.disable();
```
---
### `use`
```typescript
function use(symbol: symbol): void;
```
切换当前作用域,后续 `realize` 方法绑定的逻辑将关联到该作用域。
- **参数**
- `symbol`: 唯一作用域标识符
---
### `dispose`
```typescript
function dispose(symbol?: symbol): void;
```
释放指定作用域及其绑定的所有按键逻辑。
- **参数**
- `symbol`(可选): 要释放的作用域(默认释放当前作用域)
**示例**
```typescript
const scope = Symbol();
controller.use(scope);
// ...绑定操作...
controller.dispose(scope); // 释放该作用域
```
---
### `emitKey`
```typescript
function emitKey(
key: KeyCode,
assist: number,
type: KeyEventType,
ev: KeyboardEvent
): boolean;
```
手动触发按键事件(可用于模拟按键操作)。
- **参数**
- `key`: 按键代码
- `assist`: 辅助键状态二进制位Ctrl=1<<0, Shift=1<<1, Alt=1<<2
- `type`: 事件类型(`'up'` 或 `'down'`
- `ev`: 原始键盘事件对象
- **返回值**
`true` 表示事件被成功处理,`false` 表示无匹配逻辑
**示例**
```typescript
// 模拟触发 Ctrl+S 保存操作
controller.emitKey(
KeyCode.KeyS,
1 << 0, // Ctrl 激活
'down',
new KeyboardEvent('keydown')
);
```
---
## 静态方法说明
### `Hotkey.get`
```typescript
function get(id: string): Hotkey | undefined;
```
**静态方法**:根据 ID 获取控制器实例。
---
## 事件说明
| 事件名 | 参数类型 | 触发时机 |
| --------- | --------------------------------------------------- | ---------------- |
| `set` | `[id: string, key: KeyCode, assist: number]` | 按键绑定被修改时 |
| `emit` | `[key: KeyCode, assist: number, type: KeyEmitType]` | 按键被触发时 |
| `press` | `[key: KeyCode]` | 按键被按下时 |
| `release` | `[key: KeyCode]` | 按键被释放时 |
**事件监听示例**
```typescript
editorHotkey.on('emit', (key, assist) => {
console.log(`按键 ${KeyCode[key]} 触发,辅助键状态:${assist}`);
});
```
---
## 总使用示例
::: code-group
```typescript [注册]
import { gameKey } from '@motajs/system-action';
gameKey.register({
id: 'jump',
name: '跳跃',
defaults: KeyCode.Space
});
```
```typescript [实现]
import { useKey } from '@motajs/render-vue';
const [gameKey] = useKey();
// 绑定跳跃逻辑
gameKey.realize('jump', () => {
player.jump();
});
```
:::

View File

@ -0,0 +1,221 @@
# Keyboard API 文档
本文档由 `DeepSeek R1` 模型生成并微调。
```mermaid
graph LR
Keyboard --> EventEmitter
```
## 类描述
`Keyboard` 是虚拟键盘的核心类,用于管理动态按键布局、处理按键事件及辅助键状态。继承自 `EventEmitter`,支持自定义事件监听。
---
## 属性说明
| 属性名 | 类型 | 描述 |
| -------------- | ---------------- | ----------------------------------------------------------- |
| `id` | `string` | 键盘的唯一标识符 |
| `keys` | `KeyboardItem[]` | 当前键盘包含的按键列表(响应式数组) |
| `assist` | `number` | 辅助键状态二进制位表示Ctrl=1<<0, Shift=1<<1, Alt=1<<2 |
| `fontSize` | `number` | 按键文本字体大小(默认 18 |
| `list`(静态) | `Keyboard[]` | 静态属性,存储所有已创建的键盘实例 |
**KeyboardItem 结构**
```typescript
interface KeyboardItem {
key: KeyCode; // 按键代码
text?: string; // 显示文本(可选)
x: number; // X 坐标
y: number; // Y 坐标
width: number; // 宽度
height: number; // 高度
}
```
---
## 构造方法
```typescript
function constructor(id: string): Keyboard;
```
- **参数**
- `id`: 键盘的唯一标识符
**示例**
```typescript
const numpad = new Keyboard('numpad');
```
---
## 方法说明
### `add`
```typescript
function add(item: KeyboardItem): Keyboard;
```
### `remove`
```typescript
function remove(item: KeyboardItem): Keyboard;
```
添加/移除按键,返回当前实例以便链式调用。
**示例**
```typescript
// 添加数字键 1
numpad.add({
key: KeyCode.Digit1,
text: '1',
x: 0,
y: 0,
width: 60,
height: 60
});
// 移除按键
numpad.remove(existingKey);
```
---
### `extend`
```typescript
function extend(
keyboard: Keyboard,
offsetX?: number,
offsetY?: number
): Keyboard;
```
继承其他键盘的按键布局并添加偏移量。
**示例**
```typescript
const extendedKB = new Keyboard('extended');
extendedKB.extend(numpad, 100, 0); // 向右偏移 100px
```
---
### `emitKey`
```typescript
function emitKey(key: KeyboardItem, index: number): void;
```
模拟触发按键事件(自动处理辅助键状态)。
---
### `createScope`
```typescript
function createScope(): symbol;
```
### `disposeScope`
```typescript
function disposeScope(): void;
```
管理事件监听作用域:
- `createScope`: 创建新作用域(返回唯一标识符)
- `disposeScope`: 释放当前作用域
---
### `withAssist`
```typescript
function withAssist(assist: number): symbol;
```
创建预设辅助键状态的作用域(如 `Ctrl+Shift`)。
---
### `Keyboard.get`
```typescript
function get(id: string): Keyboard | undefined;
```
**静态方法**:根据 ID 获取键盘实例。
---
## 事件说明
| 事件名 | 参数类型 | 触发时机 |
| -------------- | ------------------------- | ------------------ |
| `add` | `KeyboardItem` | 新增按键时 |
| `remove` | `KeyboardItem` | 移除按键时 |
| `extend` | `Keyboard` | 继承其他键盘布局时 |
| `emit` | `item, assist, index, ev` | 触发按键时 |
| `scopeCreate` | `symbol` | 创建作用域时 |
| `scopeDispose` | `symbol` | 释放作用域时 |
**事件监听示例**
```typescript
numpad.on('emit', (item, assist) => {
console.log(`按键 ${item.key} 触发,辅助键状态:${assist}`);
});
```
---
## 总使用示例
```typescript
import { KeyCode } from '@motajs/client-base';
import { Keyboard } from '@motajs/system-action';
// 创建数字键盘
const numpad = new Keyboard('numpad');
// 添加基础按键
numpad
.add({ key: KeyCode.Digit1, x: 0, y: 0, width: 60, height: 60 })
.add({ key: KeyCode.Digit2, x: 60, y: 0, width: 60, height: 60 });
// 添加功能键(带辅助状态)
const ctrlScope = numpad.withAssist(1 << 0); // Ctrl 激活
numpad.add({
key: KeyCode.KeyC,
text: '复制',
x: 120,
y: 0,
width: 120,
height: 60
});
// 监听复制键
numpad.on('emit', item => {
if (item.key === KeyCode.KeyC) {
console.log('执行复制操作');
}
});
// 触发按键
numpad.emitKey(numpad.keys[0], 0); // 模拟按下数字 1
// 获取键盘实例
const foundKB = Keyboard.get('numpad');
```

View File

@ -0,0 +1,3 @@
# @motajs/system-action
目录:

View File

@ -0,0 +1,97 @@
# GameUI API 文档
本文档由 `DeepSeek R1` 模型生成并微调。
```mermaid
graph LR
GameUI --> IGameUI
```
_实现 `IGameUI` 接口_
## 接口描述
`IGameUI<C>` 是 UI 系统的核心接口,定义了 UI 实例的基础结构和静态操作方法。
---
## 属性说明
| 属性名 | 类型 | 描述 |
| -------------- | ---------------------------------- | ------------------------------------------------------------------- |
| `name` | `string` | 只读UI 的唯一标识名称 |
| `component` | `C extends UIComponent` | 只读,关联的 Vue 组件实例 |
| `list`(静态) | `Map<string, GameUI<UIComponent>>` | 静态属性,存储所有已注册的 UI 实例,键为 `name`,值为 `GameUI` 实例 |
---
## 构造方法
### `consturctor`
```typescript
function constructor(name: string, component: C): GameUI;
```
- **参数**
- `name`: UI 的唯一标识名称
- `component`: 关联的 Vue 组件实例
**示例**
```typescript
import { defineComponent } from 'vue';
export const MyComponent = defineComponent(...);
// 创建 UI 实例并自动注册到静态列表
export const MyUI = new GameUI('my-ui', MyComponent);
```
---
## 方法说明
### `GameUI.get`
```typescript
function get<T extends UIComponent>(id: string): GameUI<T> | null;
```
**静态方法**:根据 UI 名称从静态列表获取实例。
- **参数**
- `id`: UI 的唯一标识名称
- **返回值**
匹配的 `GameUI` 实例,未找到时返回 `null`
**示例**
```typescript
// 获取名为 "home" 的 UI 实例
const ui = GameUI.get<MyComponent>('my-ui');
if (ui) {
console.log(ui.component); // 输出关联的 Vue 组件
}
```
---
## 总使用示例
```tsx
import { defineComponent } from 'vue';
import { GameUI } from '@motajs/system-ui';
// 定义组件
export const MyCom = defineComponent(() => {
return () => (
<container>
<text text="自定义组件 UI" />
</container>
);
});
// 定义 UI 实例
export const MyUI = new GameUI('my-ui', MyCom);
```

View File

@ -0,0 +1,284 @@
# UIController API 文档
本文档由 `DeepSeek R1` 模型生成并微调。
```mermaid
graph LR
UIController --> EventEmitter
click EventEmitter "https://nodejs.org/api/events.html#class-eventemitter"
```
## 类描述
`UIController` 是 UI 控制系统的核心类,负责管理 UI 实例的显示栈、背景控制以及多种显示模式。继承自 `EventEmitter`,支持事件监听。想要编写 UI 请参考[深度指南](../../guide/ui.md)。
---
## 属性说明
| 属性名 | 类型 | 描述 |
| --------------------- | ---------------------------- | --------------------------------------------------------------- |
| `stack` | `IUIInstance[]` (响应式数组) | 当前管理的 UI 实例栈 |
| `mode` | `UIMode` | UI 显示模式,默认为 `LastOnlyStack` |
| `background` | `IGameUI` | 背景 UI 的配置实例 |
| `backIns` | `ShallowRef<IUIInstance>` | 背景 UI 实例的响应式引用 |
| `showBack` | `ComputedRef<boolean>` | 当前是否显示背景(用户设置与系统状态共同决定) |
| `active`(只读) | `boolean` | 系统是否显示背景 UI等价于 `sysShowBack.value` |
| `controllers`(静态) | `Map<string, UIController>` | 静态属性,存储所有已创建的控制器实例,键为 `id`,值为控制器实例 |
---
## 构造方法
### `constructor`
```typescript
function constructor(id: string): UIController;
```
- **参数**
- `id`: 控制器的唯一标识符(若重复会触发警告日志)
**示例**
```typescript
const mainController = new UIController('main');
```
---
## 方法说明
### `render`
```typescript
function render(): VNode;
```
渲染 UI 容器组件(用于 Vue 挂载)。
**示例**
```tsx
import { defineComponent } from 'vue';
import { UIController } from '@motajs/system-ui';
export const myController = new UIController('my-controller');
export const MyCom = defineComponent(() => {
return () => <container>{myController.render()}</container>;
});
```
---
### `setBackground`
```typescript
function setBackground<T extends UIComponent>(
back: IGameUI<T>,
vBind: UIProps<T>
): void;
```
设置背景 UI 并初始化其实例。
- **参数**
- `back`: 背景 UI 配置实例
- `vBind`: 传递给背景组件的 Props 对象
**示例**
```typescript
import { BackgroundUI } from './background';
// 显示背景组件,并传入参数 theme='dark'
mainController.setBackground(BackgroundUI, { theme: 'dark' });
```
---
### `hideBackground`
```typescript
function hideBackground(): void;
```
隐藏背景 UI (不影响系统状态)。
---
### `showBackground`
```typescript
function showBackground(): void;
```
显示背景 UI不影响系统状态
---
### `keep`
```typescript
function keep(): IKeepController;
```
维持背景显示(防闪烁),返回控制器对象:
```typescript
interface IKeepController {
safelyUnload(): void; // 安全卸载(仅在栈为空时关闭)
unload(): void; // 强制立即卸载
}
```
**示例**
```typescript
const keeper = mainController.keep();
// 执行某些操作后...
keeper.safelyUnload();
```
---
### `open`
```typescript
function open<T extends UIComponent>(
ui: IGameUI<T>,
vBind: UIProps<T>,
alwaysShow?: boolean
): IUIInstance<T>;
```
打开一个新 UI 实例并加入栈中。
- **参数**
- `ui`: UI 配置实例
- `vBind`: 组件 Props
- `alwaysShow`: 是否强制显示(默认 `false`
- **返回值**
打开的 UI 实例,可以用于关闭等操作
**示例**
```typescript
import { MyUI } from './myUI';
const instance = mainController.open(MyUI, { param: 80 });
```
---
### `close`
```typescript
function close(ui: IUIInstance): void;
```
关闭指定 UI 实例(根据当前模式可能影响其他实例)。
---
### `closeAll`
```typescript
function closeAll(ui?: IGameUI): void;
```
关闭所有或指定类型的所有 UI 实例。
- **参数**
- `ui`(可选): 指定要关闭的 UI 类型,不填时表示关闭所有 UI
---
### `lastOnly`
```typescript
function lastOnly(stack?: boolean): void;
```
切换显示模式:仅显示最后一个 UI可设置为栈模式
---
### `showAll`
```typescript
function showAll(stack?: boolean): void;
```
切换显示模式:显示所有非隐藏 UI可设置为栈模式
---
### `showCustom`
```typescript
function showCustom(config: IUICustomConfig): void;
```
切换显示模式:使用自定义模式(需实现 `IUICustomConfig`),参考[指南](../../guide/ui-system.md#自定义显示模式)
---
### `UIController.getController`
```typescript
function getController(id: string): UIController | null;
```
**静态方法**:根据 ID 获取控制器实例。
**示例**
```typescript
const ctrl = UIController.getController('main');
```
---
## 事件说明
| 事件名 | 参数类型 | 触发时机 |
| ------- | ------------------------------- | ------------------ |
| `open` | `ui: IGameUI, ins: IUIInstance` | 新 UI 实例被打开时 |
| `close` | `ins: IUIInstance` | UI 实例被关闭时 |
**事件监听示例**
```typescript
mainController.on('open', (ui, ins) => {
console.log(`Opened UI: ${ui.name}`);
});
```
---
## 总使用示例
```typescript
import { BackgroundUI, DialogUI } from './myUI';
import { mainController } from '@user/client-modules';
// 事件监听
mainController.on('close', ins => {
console.log('UI closed:', ins.ui.name);
});
// 设置背景
mainController.setBackground(BackgroundUI, { color: '#333' });
// 打开 UI
const dialogIns = mainController.open(DialogUI, { title: '提示' });
// 切换显示模式,仅显示最后一个,启用栈模式
mainController.lastOnly(true);
// 关闭 UI
mainController.close(dialogIns);
```

View File

@ -0,0 +1,121 @@
# UIInstance API 文档
本文档由 `DeepSeek R1` 模型生成并微调。
```mermaid
graph LR
UIInstance --> IUIInstance
```
_实现 `IUIInstance` 接口_
## 类描述
`UIInstance` 表示通过 `GameUI` 模板创建的具体 UI 实例,用于管理单个 UI 实例的状态和数据绑定。实现了 `IUIInstance` 接口。
---
## 属性说明
| 属性名 | 类型 | 描述 |
| ------------ | ------------ | -------------------------------------------------------- |
| `key` | `number` | 只读,实例的唯一标识(用于 Vue 的 `key` 属性) |
| `ui` | `IGameUI<C>` | 只读,关联的 UI 配置实例(即创建该实例的 `GameUI` 模板) |
| `vBind` | `UIProps<C>` | 只读,传递给 UI 组件的响应式 Props 对象 |
| `hidden` | `boolean` | 当前实例是否处于隐藏状态 |
| `alwaysShow` | `boolean` | 是否强制保持显示(不受显示模式影响) |
---
## 构造方法
```typescript
function constructor(
ui: IGameUI<C>,
vBind: UIProps<C>,
alwaysShow: boolean = false
): UIInstance;
```
- **参数**
- `ui`: 关联的 `GameUI` 配置实例
- `vBind`: 初始化的组件 Props 对象
- `alwaysShow`: 是否强制保持显示(默认 `false`
**注意事项**:一般不需要手动创建 `UIInstance` 实例,请使用 [`UIController.open`](./UIController.md#open) 打开 UI 并创建实例。
---
## 方法说明
### `setVBind`
```typescript
function setVBind(data: Partial<Props<C>>, merge?: boolean): void;
```
更新组件的响应式 Props。
- **参数**
- `data`: 需要更新的数据(部分 Props
- `merge`: 是否与现有数据合并(默认 `true`),若为 `false` 则完全覆盖
**示例**
```typescript
// 合并更新音量值
instance.setVBind({ volume: 60 });
// 覆盖所有 Props
instance.setVBind({ theme: 'dark' }, false);
```
---
### `hide`
```typescript
function hide(): void;
```
控制实例的显示状态(直接操作 `hidden` 属性)。
**示例**
```typescript
instance.hide(); // 隐藏 UI
setTimeout(() => instance.show(), 1000); // 1 秒后显示
```
---
### `show`
```typescript
function show(): void;
```
控制实例的显示状态(直接操作 `hidden` 属性)。
**示例**
```typescript
instance.show(); // 隐藏 UI
setTimeout(() => instance.show(), 1000); // 1 秒后显示
```
---
## 总使用示例
```typescript
import { myController, MyUI } from './myUI';
const myIns = myController.open(MyUI, { title: '警告' });
// 动态更新 props
myIns.setVBind({ title: '错误' });
// 设置显示状态
myIns.show();
```

View File

@ -0,0 +1,3 @@
# @motajs/system-ui
目录:

View File

@ -0,0 +1,25 @@
# @motajs/system
包含两个模块:
- [`@motajs/system-action`](../motajs-system-action/index.md)
- [`@motajs/system-ui`](../motajs-system-ui/index.md)
## 引入示例
```ts
import { gameKey, UIController } from '@motajs/system';
gameKey.register(...);
const myController = new UIController('my-controller');
```
等效于:
```ts
import { gameKey } from '@motajs/system-action';
import { UIController } from '@motajs/system-ui';
gameKey.register(...);
const myController = new UIController('my-controller');
```

View File

@ -0,0 +1,3 @@
# @motajs/types
目录:

View File

@ -0,0 +1,142 @@
# AudioDecoder API 文档
本文档由 `DeepSeek R1` 模型生成并微调。
---
## 类描述
音频解码系统的核心抽象类,为不同音频格式提供统一的解码接口。主要处理浏览器原生不支持音频格式的解码任务(如 iOS 平台的 Ogg 格式)。
---
## 静态成员说明
### `decoderMap`
```typescript
declare const decoderMap: Map<AudioType, new () => AudioDecoder>;
```
解码器注册表,存储格式类型与解码器类的映射关系
---
## 静态方法说明
### `AudioDecoder.registerDecoder`
```typescript
function registerDecoder(
type: AudioType,
decoder: new () => AudioDecoder
): void;
```
注册自定义解码器到全局解码器系统
| 参数 | 类型 | 说明 |
| ------- | ------------------------ | -------------- |
| type | `AudioType` | 音频格式类型 |
| decoder | `new () => AudioDecoder` | 解码器构造函数 |
---
### `AudioDecoder.decodeAudioData`
```typescript
function decodeAudioData(
data: Uint8Array,
player: AudioPlayer
): Promise<AudioBuffer | null>;
```
核心解码入口方法,自动选择最佳解码方案
| 参数 | 类型 | 说明 |
| ------ | ------------- | ---------------- |
| data | `Uint8Array` | 原始音频字节数据 |
| player | `AudioPlayer` | 音频播放器实例 |
**处理流程**
1. 通过文件头检测音频类型
2. 优先使用浏览器原生解码能力
3. 无原生支持时查找注册的自定义解码器
4. 返回标准 `AudioBuffer` 格式数据
---
## 抽象方法说明
### `abstract create`
```typescript
function create(): Promise<void>;
```
初始化解码器实例(需分配 WASM 内存等资源)
---
### `abstract destroy`
```typescript
function destroy(): void;
```
销毁解码器实例(需释放资源)
---
### `abstract decode`
```typescript
function decode(data: Uint8Array): Promise<IAudioDecodeData | undefined>;
```
流式解码方法(分块处理)
| 参数 | 类型 | 说明 |
| ---- | ------------ | ------------ |
| data | `Uint8Array` | 音频数据分块 |
---
### `abstract decodeAll`
```typescript
function decodeAll(data: Uint8Array): Promise<IAudioDecodeData | undefined>;
```
全量解码方法(单次处理完整文件)
---
### `abstract flush`
```typescript
function flush(): Promise<IAudioDecodeData | undefined>;
```
冲刷解码器缓冲区,获取残留数据
---
## 数据结构
### IAudioDecodeData
```typescript
interface IAudioDecodeData {
channelData: Float32Array[]; // 各声道 PCM 数据
samplesDecoded: number; // 已解码采样数
sampleRate: number; // 采样率 (Hz)
errors: IAudioDecodeError[]; // 解码错误集合
}
```
## 内置解码器
- `VorbisDecoder`: 解码 ogg vorbis 音频。
- `OpusDecoder`: 解码 ogg opus 音频。

View File

@ -0,0 +1,207 @@
# AudioEffect API 文档
本文档由 `DeepSeek R1` 模型生成并微调。
---
## 类描述
音频处理管道的核心抽象类,为构建音频效果链提供基础框架。所有效果器通过输入/输出节点串联,形成可定制的音频处理流水线。
---
## 核心架构
音频播放流程:
```mermaid
graph LR
Source --> Effect1
Effect1 --> Effect2[...]
Effect2 --> GainNode
GainNode --> Destination
```
---
## 抽象成员说明
| 成员 | 类型 | 说明 |
| -------- | ----------- | -------------------------- |
| `input` | `AudioNode` | 效果器输入节点(必须实现) |
| `output` | `AudioNode` | 效果器输出节点(必须实现) |
---
## 核心方法说明
### `connect`
```typescript
function connect(target: IAudioInput, output?: number, input?: number): void;
```
连接至下游音频节点
| 参数 | 类型 | 说明 |
| ------ | ------------- | -------------------------- |
| target | `IAudioInput` | 目标效果器/节点 |
| output | `number` | 当前效果器输出通道(可选) |
| input | `number` | 目标效果器输入通道(可选) |
---
### `disconnect`
```typescript
function disconnect(
target?: IAudioInput,
output?: number,
input?: number
): void;
```
断开与下游节点的连接
---
### `abstract start`
```typescript
function start(): void;
```
效果器激活时调用(可用于初始化参数)
---
### `abstract end`
```typescript
function end(): void;
```
效果器停用时调用(可用于资源回收)
---
## 自定义效果器示例
### 混响效果器实现
```typescript
export class ReverbEffect extends AudioEffect {
private convolver: ConvolverNode;
private dryGain: GainNode;
private wetGain: GainNode;
constructor(ac: AudioContext) {
super(ac);
// 创建节点网络
this.dryGain = ac.createGain();
this.wetGain = ac.createGain();
this.convolver = ac.createConvolver();
// 定义输入输出
this.input = this.dryGain;
this.output = this.ac.createGain();
// 构建处理链
this.dryGain.connect(this.output);
this.dryGain.connect(this.convolver);
this.convolver.connect(this.wetGain);
this.wetGain.connect(this.output);
}
/** 设置混响强度 */
setMix(value: number) {
this.dryGain.gain.value = 1 - value;
this.wetGain.gain.value = value;
}
/** 加载脉冲响应 */
async loadImpulse(url: string) {
const response = await fetch(url);
const buffer = await this.ac.decodeAudioData(
await response.arrayBuffer()
);
this.convolver.buffer = buffer;
}
start() {
this.output.gain.value = 1;
}
end() {
this.output.gain.value = 0;
}
}
```
---
## 内置效果器说明
### StereoEffect立体声控制
```mermaid
graph LR
Input --> Panner[PannerNode]
Panner --> Output
```
- 控制声相/3D 空间定位
- 支持设置声音方位和位置
### VolumeEffect音量控制
```mermaid
graph LR
Input --> Gain[GainNode]
Gain --> Output
```
- 全局音量调节
- 支持实时音量渐变
### ChannelVolumeEffect多声道控制
```mermaid
graph LR
Input --> Splitter[ChannelSplitter]
Splitter --> Gain1
Splitter --> Gain2
Gain1 --> Merger
Gain2 --> Merger
Merger --> Output
```
- 6 声道独立音量控制
- 支持环绕声场调节
### DelayEffect延迟效果
```mermaid
graph LR
Input --> Delay[DelayNode]
Delay --> Output
```
- 基础延迟效果
- 精确到采样级的延迟控制
### EchoEffect回声效果
```mermaid
graph LR
Input --> Gain
Gain --> Delay
Delay --> Gain[反馈循环]
Gain --> Output
```
- 带反馈的延迟效果
- 自动渐弱回声处理
---

View File

@ -0,0 +1,172 @@
# AudioPlayer API 文档
本文档由 `DeepSeek R1` 模型生成并微调。
---
## 类描述
音频系统的核心控制器,负责管理音频上下文、路由系统、效果器工厂和全局音频参数。支持多音轨管理和 3D 音频空间化配置。
```mermaid
graph LR
AudioPlayer --> EventEmitter
click EventEmitter "https://nodejs.org/api/events.html#class-eventemitter"
```
---
## 核心架构
```mermaid
graph TD
Player[AudioPlayer] --> Sources[音频源工厂]
Player --> Effects[效果器工厂]
Player --> Routes[路由系统]
Player --> Listener[3D 听者配置]
```
---
## 属性说明
| 属性名 | 类型 | 说明 |
| ------------- | ------------------------- | ------------------------ |
| `ac` | `AudioContext` | Web Audio API 上下文实例 |
| `audioRoutes` | `Map<string, AudioRoute>` | 已注册的音频路由表 |
| `gain` | `GainNode` | 全局音量控制节点 |
---
## 方法说明
此处暂时只列出方法的简易说明。方法理解难度不高,如果需要可以自行查看代码以及其相关注释来查看如何使用。
### 音频源工厂方法
| 方法名 | 返回值 | 说明 |
| ----------------------- | -------------------- | ----------------------------- |
| `createSource(Source)` | `AudioSource` | 创建自定义音频源 |
| `createStreamSource()` | `AudioStreamSource` | 创建流式音频源(直播/长音频) |
| `createElementSource()` | `AudioElementSource` | 基于 HTML5 Audio 元素的音源 |
| `createBufferSource()` | `AudioBufferSource` | 基于 AudioBuffer 的静态音源 |
### 效果器工厂方法
| 方法名 | 返回值 | 说明 |
| ----------------------------- | --------------------- | ---------------------------- |
| `createEffect(Effect)` | `AudioEffect` | 创建自定义效果器 |
| `createVolumeEffect()` | `VolumeEffect` | 全局音量控制器 |
| `createStereoEffect()` | `StereoEffect` | 立体声场控制器 |
| `createChannelVolumeEffect()` | `ChannelVolumeEffect` | 多声道独立音量控制6 声道) |
| `createDelayEffect()` | `DelayEffect` | 精确延迟效果器 |
| `createEchoEffect()` | `EchoEffect` | 回声效果器(带反馈循环) |
### 路由管理方法
| 方法名 | 参数 | 说明 |
| --------------------- | -------------------- | -------------- |
| `createRoute(source)` | `AudioSource` | 创建新播放路由 |
| `addRoute(id, route)` | `string, AudioRoute` | 注册命名路由 |
| `getRoute(id)` | `string` | 获取已注册路由 |
| `removeRoute(id)` | `string` | 移除指定路由 |
### 全局控制方法
| 方法名 | 参数 | 说明 |
| ------------------------------- | ------------------------ | -------------------- |
| `setVolume(volume)` | `number` (0.0-1.0) | 设置全局音量 |
| `getVolume()` | - | 获取当前全局音量 |
| `setListenerPosition(x,y,z)` | `number, number, number` | 设置听者 3D 空间坐标 |
| `setListenerOrientation(x,y,z)` | `number, number, number` | 设置听者朝向 |
| `setListenerUp(x,y,z)` | `number, number, number` | 设置听者头顶朝向 |
---
## 使用示例
### 基础音乐播放
```typescript
import { audioPlayer } from '@user/client-modules';
// 创建音频源(以音频缓冲为例)
const bgmSource = audioPlayer.createBufferSource();
// 创建播放路由
const bgmRoute = audioPlayer.createRoute(bgmSource);
// 添加效果链
bgmRoute.addEffect([
audioPlayer.createStereoEffect(),
audioPlayer.createVolumeEffect()
]);
// 播放控制
audioPlayer.play('bgm');
audioPlayer.pause('bgm');
```
### 3D 环境音效
```typescript
import { audioPlayer } from '@user/client-modules';
// 配置3D听者
audioPlayer.setListenerPosition(0, 0, 0); // 听者在原点
audioPlayer.setListenerOrientation(0, 0, -1); // 面朝屏幕内
// 创建环境音源
const ambientSource = audioPlayer.createBufferSource();
await ambientSource.setBuffer(/* 这里填写音频缓冲 */);
// 配置3D音效路由
const ambientRoute = audioPlayer.createRoute(ambientSource);
const stereo = audioPlayer.createStereoEffect();
stereo.setPosition(5, 2, -3); // 音源位于右前方高处
ambientRoute.addEffect(stereo);
// 循环播放
ambientRoute.setLoop(true);
audioPlayer.addRoute('ambient', ambientRoute);
audioPlayer.play('ambient');
```
---
## 生命周期管理
```mermaid
sequenceDiagram
participant User
participant AudioPlayer
participant AudioContext
User->>AudioPlayer: new AudioPlayer()
AudioPlayer->>AudioContext: 创建音频上下文
User->>AudioPlayer: createRoute()
AudioPlayer->>AudioRoute: 实例化路由
User->>AudioPlayer: play()
AudioPlayer->>AudioContext: 启动音频时钟
loop 播放周期
AudioPlayer->>AudioRoute: 更新状态
end
User->>AudioPlayer: stop()
AudioPlayer->>AudioRoute: 释放资源
AudioPlayer->>AudioContext: 关闭上下文
```
---
## 注意事项
1. **空间音频配置**
3D 效果需统一坐标系:
```txt
(0,0,0) 屏幕中心
X+ → 右
Y+ ↑ 上
Z+ ⊙ 朝向用户
```

View File

@ -0,0 +1,221 @@
# AudioRoute 音频播放路由 API 文档
本文档由 `DeepSeek R1` 模型生成并微调。
---
## 类描述
音频播放控制的核心类,负责管理音频源与效果器的连接关系,协调播放状态转换,并处理音频管线生命周期。
```mermaid
graph LR
AudioRoute --> EventEmitter
click EventEmitter "https://nodejs.org/api/events.html#class-eventemitter"
```
---
## 属性说明
| 属性名 | 类型 | 说明 |
| ------------- | ------------------ | ------------------------------------------------ |
| `output` | `AudioNode` | 最终输出节点(继承自 IAudioOutput |
| `effectRoute` | `AudioEffect[]` | 效果器链数组(按顺序存储已连接的效果器实例) |
| `endTime` | `number` | 淡出过渡时长(单位:秒),默认 0 |
| `status` | `AudioStatus` | 当前播放状态(见下方枚举定义) |
| `duration` | `number` (getter) | 音频总时长(单位:秒) |
| `currentTime` | `number` (get/set) | 当前播放进度(单位:秒),设置时会触发 seek 操作 |
---
### AudioStatus 枚举
```typescript
enum AudioStatus {
Playing, // 正在播放
Pausing, // 淡出暂停过程中
Paused, // 已暂停
Stoping, // 淡出停止过程中
Stoped // 已停止
}
```
---
## 方法说明
### `setEndTime`
```typescript
function setEndTime(time: number): void;
```
设置淡出过渡时长
| 参数 | 类型 | 说明 |
| ---- | -------- | ------------------------ |
| time | `number` | 淡出动画时长(单位:秒) |
---
### `onStart`
```typescript
function onStart(fn?: (route: AudioRoute) => void): void;
```
注册播放开始钩子函数
| 参数 | 类型 | 说明 |
| ---- | ----------------- | ------------------------ |
| `fn` | `(route) => void` | 播放开始时触发的回调函数 |
---
### `onEnd`
```typescript
function onEnd(fn?: (time: number, route: AudioRoute) => void): void;
```
注册播放结束钩子函数
| 参数 | 类型 | 说明 |
| ---- | --------------------------- | --------------------------------------------- |
| `fn` | `(duration, route) => void` | 淡出阶段开始时触发的回调duration 为淡出时长 |
---
### `play`
```typescript
function play(when?: number = 0): Promise<void>;
```
启动/恢复音频播放
| 参数 | 类型 | 说明 |
| ------ | -------- | -------------------------------------- |
| `when` | `number` | 基于 AudioContext 时间的启动时刻(秒) |
---
### `pause`
```typescript
function pause(): Promise<void>;
```
触发暂停流程(执行淡出过渡)
---
### `resume`
```typescript
function resume(): void;
```
从暂停状态恢复播放(执行淡入过渡)
---
### `stop`
```typescript
function stop(): Promise<void>;
```
完全停止播放并释放资源
---
### `addEffect`
```typescript
function addEffect(effect: AudioEffect | AudioEffect[], index?: number): void;
```
添加效果器到处理链
| 参数 | 类型 | 说明 |
| -------- | ------------------ | ------------------------------ |
| `effect` | `AudioEffect`/数组 | 要添加的效果器实例 |
| `index` | `number` (可选) | 插入位置,负数表示从末尾倒计数 |
---
### `removeEffect`
```typescript
function removeEffect(effect: AudioEffect): void;
```
从处理链移除效果器
| 参数 | 类型 | 说明 |
| -------- | ------------- | ------------------ |
| `effect` | `AudioEffect` | 要移除的效果器实例 |
---
## 事件说明
| 事件名 | 参数 | 触发时机 |
| -------------- | ---- | ------------------ |
| `updateEffect` | - | 效果器链发生变更时 |
| `play` | - | 开始/恢复播放时 |
| `stop` | - | 完全停止播放后 |
| `pause` | - | 进入暂停状态后 |
| `resume` | - | 从暂停状态恢复时 |
---
## 总使用示例
```typescript
import { audioPlayer } from '@user/client-modules';
// 创建音频播放器和路由
const source = audioPlayer.createBufferSource();
const route = audioPlayer.createRoute(audioSource);
// 配置效果链
const stereo = audioPlayer.createStereoEffect();
const echo = audioPlayer.createEchoEffect();
const volume = audioPlayer.createVolumeEffect();
route.addEffect([stereo, echo], 0); // 插入到链首
route.addEffect(volume); // 音量控制放到链尾
// 播放暂停
await route.play();
await route.pause();
route.resume(); // 继续操作不是异步,不需要 await
await route.stop();
```
---
## 处理流程示意图
```mermaid
sequenceDiagram
participant User
participant AudioRoute
participant Effects
User->>AudioRoute: play()
AudioRoute->>Effects: 启动所有效果器
Effects-->>AudioRoute: 准备完成
AudioRoute->>Source: 开始播放
loop 播放中
AudioRoute->>Effects: 实时音频处理
end
User->>AudioRoute: pause()
AudioRoute->>Effects: 启动淡出过渡
Effects-->>AudioRoute: 过渡完成
AudioRoute->>Source: 暂停播放
```

View File

@ -0,0 +1,184 @@
# AudioSource API 文档
本文档由 `DeepSeek R1` 模型生成并微调。
---
## 类描述
音频系统的源头抽象类定义了音频播放的核心控制接口。支持多种音频源类型包括流媒体、HTML 音频元素和静态音频缓冲。
```mermaid
graph LR
AudioPlayer --> EventEmitter
click EventEmitter "https://nodejs.org/api/events.html#class-eventemitter"
```
---
## 抽象成员说明
| 成员 | 类型 | 说明 |
| ------------- | ----------- | ------------------------ |
| `output` | `AudioNode` | 音频输出节点(必须实现) |
| `duration` | `number` | 音频总时长(秒) |
| `currentTime` | `number` | 当前播放时间(秒) |
| `playing` | `boolean` | 播放状态标识 |
---
## 核心方法说明
### `abstract play`
```typescript
function play(when?: number): void;
```
启动音频播放时序
| 参数 | 类型 | 说明 |
| ---- | -------- | ----------------------------------------------- |
| when | `number` | 预定播放时间(基于 `AudioContext.currentTime` |
---
### `abstract stop`
```typescript
function stop(): number;
```
停止播放并返回停止时刻
---
### `abstract connect`
```typescript
function connect(target: IAudioInput): void;
```
连接至音频处理管线
| 参数 | 类型 | 说明 |
| ------ | ------------- | ------------------- |
| target | `IAudioInput` | 下游处理节点/效果器 |
---
### `abstract setLoop`
```typescript
function setLoop(loop: boolean): void;
```
设置循环播放模式
---
## 事件系统
| 事件名 | 参数 | 触发时机 |
| ------ | ---- | -------------- |
| `play` | - | 开始播放时 |
| `end` | - | 自然播放结束时 |
---
## 自定义音频源示例
### 网络实时通话源
```typescript
class WebRTCAudioSource extends AudioSource {
private mediaStream: MediaStreamAudioSourceNode;
output: AudioNode;
constructor(ac: AudioContext, stream: MediaStream) {
super(ac);
this.mediaStream = ac.createMediaStreamSource(stream);
this.output = this.mediaStream;
}
get duration() {
return Infinity;
} // 实时流无固定时长
get currentTime() {
return this.ac.currentTime;
}
play() {
this.mediaStream.connect(this.output);
this.playing = true;
this.emit('play');
}
stop() {
this.mediaStream.disconnect();
this.playing = false;
return this.ac.currentTime;
}
connect(target: IAudioInput) {
this.output.connect(target.input);
}
setLoop() {} // 实时流不支持循环
}
// 使用示例
navigator.mediaDevices.getUserMedia({ audio: true }).then(stream => {
const source = new WebRTCAudioSource(audioContext, stream);
source.connect(effectsChain);
source.play();
});
```
---
## 内置实现说明
### AudioStreamSource流媒体源
```mermaid
graph LR
Network[网络数据流] --> Buffer[缓冲区]
Buffer --> Decoder[音频解码器]
Decoder --> Output[实时音频节点]
```
- 支持渐进式加载
- 动态缓冲管理
- 适用于浏览器自身不支持的音频类型
### AudioElementSourceHTML 音频元素源)
```mermaid
graph LR
AudioTag[audio 元素] -->|音频流| Output[媒体元素源节点]
```
- 基于 HTML5 Audio 元素
- 支持跨域资源
- 自动处理音频格式兼容
### AudioBufferSource静态音频缓冲源
```mermaid
graph LR
File[音频文件] --> Decode[解码为 AudioBuffer]
Decode --> Output[缓冲源节点]
```
- 完整音频数据预加载
- 精确播放控制
- 支持内存音频播放
---
## 注意事项
1. **时间精度**
所有时间参数均以 `AudioContext.currentTime` 为基准,精度可达 0.01 秒

View File

@ -0,0 +1,158 @@
# BgmController API 文档
本文档由 `DeepSeek R1` 模型生成并微调。
```mermaid
graph LR
BgmController --> EventEmitter
click EventEmitter "https://nodejs.org/api/events.html#class-eventemitter"
```
## 类描述
`BgmController` 是背景音乐系统的核心控制器,支持多 BGM 的加载、音量控制、渐变切换和播放状态管理。继承自 `EventEmitter`,提供完整的音频事件监听机制。
---
## 泛型说明
- `T extends string`: BGM 的唯一标识符类型(默认为项目预定义的 `BgmIds`
---
## 属性说明
| 属性名 | 类型 | 描述 |
| ---------------- | --------- | ----------------------------------------- |
| `prefix` | `string` | BGM 资源路径前缀(默认 `bgms.` |
| `playingBgm` | `T` | 当前正在播放的 BGM ID |
| `enabled` | `boolean` | 是否启用音频控制(默认 true |
| `transitionTime` | `number` | 音频切换渐变时长(单位:毫秒,默认 2000 |
---
## 核心方法说明
### `setTransitionTime`
```typescript
function setTransitionTime(time: number): void;
```
设置所有 BGM 的渐变切换时长。
- **参数**
- `time`: 渐变时长(毫秒)
---
### `blockChange`
```typescript
function blockChange(): void;
```
### `unblockChange`
```typescript
function unblockChange(): void;
```
屏蔽/解除屏蔽 BGM 切换(用于特殊场景)。
---
### `setVolume`
```typescript
function setVolume(volume: number): void;
```
### `getVolume`
```typescript
function getVolume(): number;
```
控制全局音量(范围 0-1
---
### `setEnabled`
```typescript
function setEnabled(enabled: boolean): void;
```
启用/禁用整个 BGM 系统(禁用时停止所有播放)。
---
### `addBgm`
```typescript
function addBgm(id: T, url?: string): void;
```
加载并注册 BGM 资源。
- **参数**
- `id`: BGM 唯一标识
- `url`: 自定义资源路径(默认 `project/bgms/${id}`
---
### `removeBgm`
```typescript
function removeBgm(id: T): void;
```
移除已注册的 BGM 资源。
---
### 播放控制方法
```typescript
function play(id: T, when?: number): void; // 播放指定 BGM带渐变
function pause(): void; // 暂停当前 BGM保留进度
function resume(): void; // 继续播放当前 BGM
function stop(): void; // 停止当前 BGM重置进度
```
---
## 事件说明
| 事件名 | 参数 | 触发时机 |
| -------- | ---- | ----------------- |
| `play` | `[]` | 开始播放新 BGM 时 |
| `pause` | `[]` | 暂停播放时 |
| `resume` | `[]` | 继续播放时 |
| `stop` | `[]` | 完全停止播放时 |
---
## 总使用示例
```typescript
import { bgmController } from '@user/client-modules';
// 设置全局参数
bgmCtrl.setTransitionTime(1500);
bgmCtrl.setVolume(0.8);
// 播放控制
bgmCtrl.play('battle.mp3'); // 播放战斗BGM
bgmCtrl.pause(); // 暂停(如打开菜单)
bgmCtrl.resume(); // 继续播放
bgmCtrl.play('boss_battle.mp3'); // 切换至BOSS战BGM
bgmCtrl.stop(); // 完全停止(如战斗结束)
// 事件监听
bgmCtrl.on('play', () => {
console.log('BGM 开始播放:', bgmCtrl.playingBgm);
});
```

View File

@ -0,0 +1,147 @@
# HeroKeyMover API 文档
本文档由 `DeepSeek R1` 模型生成并微调。
## 类描述
`HeroKeyMover` 是勇士按键移动的核心控制器,负责将热键系统与勇士移动逻辑结合,实现基于键盘输入的连续移动控制。支持多方向优先级处理和移动中断机制。
---
## 属性说明
| 属性名 | 类型 | 描述 |
| ------------ | ----------- | ---------------------------------------- |
| `hotkey` | `Hotkey` | 关联的热键控制器实例 |
| `mover` | `HeroMover` | 勇士移动逻辑执行器 |
| `scope` | `symbol` | 当前移动触发的作用域(默认使用主作用域) |
| `hotkeyData` | `MoveKey` | 移动方向与热键的映射配置 |
---
## 构造方法
```typescript
function constructor(
hotkey: Hotkey,
mover: HeroMover,
config?: MoveKeyConfig
): HeroKeyMover;
```
- **参数**
- `hotkey`: 已配置的热键控制器实例
- `mover`: 勇士移动逻辑实例
- `config`: 自定义方向键映射配置(可选)
**默认按键映射**
```typescript
const map = {
left: 'moveLeft',
right: 'moveRight',
up: 'moveUp',
down: 'moveDown'
};
```
---
## 方法说明
### `setScope`
```typescript
function setScope(scope: symbol): void;
```
设置当前移动控制的作用域(用于多场景隔离)。
- **参数**
- `scope`: 唯一作用域标识符
---
### `press`
```typescript
function press(dir: Dir): void;
```
触发指定方向的移动按键按下状态。
- **参数**
- `dir`: 移动方向(`'left' | 'right' | 'up' | 'down'`
---
### `release`
```typescript
function release(dir: Dir): void;
```
解除指定方向的移动按键按下状态。
- **参数**
- `dir`: 要释放的移动方向
---
### `tryStartMove`
```typescript
function tryStartMove(): boolean;
```
尝试启动移动逻辑(自动根据当前方向键状态判断)。
- **返回值**
`true` 表示移动成功启动,`false` 表示条件不满足
---
### `endMove`
```typescript
function endMove(): void;
```
立即终止当前移动过程。
---
### `destroy`
```typescript
function destroy(): void;
```
销毁控制器实例(自动解除所有事件监听)。
---
## 总使用示例
```typescript
import { gameKey, mainScope } from '@motajs/system-action';
// 初始化移动控制器
const keyMover = new HeroKeyMover(
gameKey,
heroMover,
{ left: 'moveLeft', right: 'moveRight' } // 自定义部分按键映射
);
// 设置允许触发的作用域
keyMover.setScope(mainScope);
// 销毁控制器
keyMover.destroy();
```
## 移动优先级机制
1. **最后按下优先**:当同时按下多个方向键时,以后按下的方向为准
2. **队列延续**:在移动过程中持续检测按键状态,自动延续移动队列
3. **作用域隔离**:只有当前作用域匹配时才会响应按键事件

View File

@ -0,0 +1,197 @@
# SoundPlayer API 文档
本文档由 `DeepSeek R1` 模型生成并微调。
---
## 类描述
音效管理核心类,提供短音频的加载、播放和空间化控制功能。推荐通过全局单例 `soundPlayer` 使用。
```mermaid
graph LR
AudioPlayer --> EventEmitter
click EventEmitter "https://nodejs.org/api/events.html#class-eventemitter"
```
---
## 属性说明
| 属性名 | 类型 | 说明 |
| --------- | --------------------- | ---------------------- |
| `enabled` | `boolean` | 总开关状态(默认启用) |
| `buffer` | `Map<T, AudioBuffer>` | 已加载音效缓冲存储池 |
| `playing` | `Set<number>` | 当前活跃音效 ID 集合 |
| `gain` | `VolumeEffect` | 全局音量控制器 |
---
## 方法说明
### 基础控制
#### setEnabled
```typescript
function setEnabled(enabled: boolean): void;
```
启用/禁用音效系统(禁用时立即停止所有音效)
| 参数 | 类型 | 说明 |
| ------- | --------- | ------------ |
| enabled | `boolean` | 是否启用音效 |
---
#### setVolume / getVolume
```typescript
function setVolume(volume: number): void;
function getVolume(): number;
```
全局音量控制(范围 0.0~1.0
---
### 资源管理
#### add
```typescript
async function add(id: T, data: Uint8Array): Promise<void>;
```
加载并缓存音效资源
| 参数 | 类型 | 说明 |
| ---- | ------------ | ---------------- |
| id | `T` | 音效唯一标识符 |
| data | `Uint8Array` | 原始音频字节数据 |
---
### 播放控制
#### play
```typescript
function play(
id: T,
position?: [number, number, number],
orientation?: [number, number, number]
): number;
```
播放指定音效(返回音效实例 ID
| 参数 | 类型 | 默认值 | 说明 |
| ----------- | ----------- | --------- | ------------------------- |
| id | `T` | - | 音效标识符 |
| position | `[x, y, z]` | `[0,0,0]` | 3D 空间坐标(右手坐标系) |
| orientation | `[x, y, z]` | `[1,0,0]` | 声音传播方向向量 |
**坐标系说明**
```txt
(0,0,0) 听者位置
X+ → 右
Y+ ↑ 上
Z+ ⊙ 朝向听者正前方
```
---
#### stop
```typescript
function stop(num: number): void;
```
停止指定音效实例
| 参数 | 类型 | 说明 |
| ---- | -------- | -------------------- |
| num | `number` | play() 返回的实例 ID |
---
#### stopAllSounds
```typescript
function stopAllSounds(): void;
```
立即停止所有正在播放的音效
---
## 使用示例
### 基础音效系统
```typescript
import { soundPlayer } from '@user/client-modules';
// 播放射击音效(右侧声场)
const shotId = soundPlayer.play('shoot', [2, 0, 0]);
// 播放爆炸音效(左后方)
soundPlayer.play('explosion', [-3, 0, -2], [-1, 0, -1]);
// 停止特定音效
soundPlayer.stop(shotId);
// 全局音量控制
soundPlayer.setVolume(0.7);
```
### 3D 环境音效
```typescript
// 汽车引擎循环音效
let engineSoundId = -1;
function startEngine() {
engineSoundId = soundPlayer.play('engine', [0, 0, -5]);
}
function updateCarPosition(x: number, z: number) {
const route = audioPlayer.getRoute(`sounds.${engineSoundId}`);
const stereo = route?.effectRoute[0] as StereoEffect;
stereo?.setPosition(x, 0, z);
}
```
---
## 生命周期管理
```mermaid
sequenceDiagram
participant User
participant SoundPlayer
participant AudioPlayer
User->>SoundPlayer: add('explosion', data)
SoundPlayer->>AudioPlayer: decodeAudioData()
AudioPlayer-->>SoundPlayer: AudioBuffer
User->>SoundPlayer: play('explosion')
SoundPlayer->>AudioPlayer: 创建路由/效果器
AudioPlayer-->>SoundPlayer: 音效ID
loop 播放周期
SoundPlayer->>AudioPlayer: 更新空间参数
end
User->>SoundPlayer: stop(id)
SoundPlayer->>AudioPlayer: 释放路由资源
```
---
## 注意事项
1. **实例数量限制**
同时播放音效建议不超过 32 个,可通过优先级系统管理

View File

@ -0,0 +1,208 @@
# StreamLoader API 文档
本文档由 `DeepSeek R1` 模型生成并微调。
```mermaid
graph LR
StreamLoader --> EventEmitter
click EventEmitter "https://nodejs.org/api/events.html#class-eventemitter"
```
## 类描述
`StreamLoader` 是流式加载大文件的核心类,支持分块读取网络资源并通过事件机制传递数据。继承自 `EventEmitter`,实现 `IStreamController` 接口,提供流传输控制能力。
---
## 属性说明
| 属性名 | 类型 | 描述 |
| --------- | --------- | ---------------------- |
| `url` | `string` | 只读,要加载的资源 URL |
| `loading` | `boolean` | 当前是否处于加载状态 |
---
## 构造方法
```typescript
function constructor(url: string): StreamLoader;
```
- **参数**
- `url`: 要加载的资源地址
**示例**
```typescript
const loader = new StreamLoader('/api/large-file');
```
---
## 方法说明
### `pipe`
```typescript
function pipe(reader: IStreamReader): this;
```
将流数据管道传递给读取器对象。
- **参数**
- `reader`: 实现 `IStreamReader` 接口的对象
**示例**
```typescript
class MyReader implements IStreamReader {
async pump(data, done) {
console.log('收到数据块:', data);
}
// ... 还有一些其他需要实现的方法,参考总是用示例
}
loader.pipe(new MyReader());
```
---
### `start`
```typescript
function start(): Promise<void>;
```
启动流传输流程(自动处理分块读取与分发)。
---
### `cancel`
```typescript
function cancel(reason?: string): void;
```
终止当前流传输。
- **参数**
- `reason`: 终止原因描述(可选)
**示例**
```typescript
// 用户取消加载
loader.cancel('用户手动取消');
```
---
## 事件说明
| 事件名 | 参数类型 | 触发时机 |
| ------ | --------------------------------- | ------------------------ |
| `data` | `data: Uint8Array, done: boolean` | 每接收到一个数据块时触发 |
**事件监听示例**
```typescript
loader.on('data', (data, done) => {
if (done) console.log('传输完成');
});
```
---
## 相关接口说明
### IStreamReader
```typescript
export interface IStreamReader<T = any> {
/**
* 接受字节流流传输的数据
* @param data 传入的字节流数据,只包含本分块的内容
* @param done 是否传输完成
*/
pump(
data: Uint8Array | undefined,
done: boolean,
response: Response
): Promise<void>;
/**
* 当前对象被传递给加载流时执行的函数
* @param controller 传输流控制对象
*/
piped(controller: IStreamController<T>): void;
/**
* 开始流传输
* @param stream 传输流对象
* @param controller 传输流控制对象
*/
start(
stream: ReadableStream,
controller: IStreamController<T>,
response: Response
): Promise<void>;
/**
* 结束流传输
* @param done 是否传输完成,如果为 false 的话,说明可能是由于出现错误导致的终止
* @param reason 如果没有传输完成,那么表示失败的原因
*/
end(done: boolean, reason?: string): void;
}
```
- `pump`: 处理每个数据块
- `piped`: 当读取器被绑定到流时调用
- `start`: 流传输开始时调用
- `end`: 流传输结束时调用
---
## 总使用示例
```typescript
// 创建流加载器
const loader = new StreamLoader('/api/video-stream');
const videoElement = document.createElement('video');
// 实现自定义读取器
class VideoStreamReader implements IStreamReader {
async pump(data, done) {
if (data) videoElement.appendBuffer(data);
if (done) videoElement.play();
}
piped(controller) {
console.log('流传输管道连接成功');
}
start() {
console.log('开始流式加载');
}
end() {
console.log('流式加载结束');
}
}
const reader = new VideoStreamReader();
// 绑定读取器并启动
loader.pipe(reader);
loader.start();
// 监听进度
loader.on('data', (_, done) => {
if (!done) updateProgressBar();
});
// 错误处理
videoElement.onerror = () => loader.cancel('视频解码错误');
```

View File

@ -0,0 +1,157 @@
# TextContentParser API 文档
本文档由 `DeepSeek R1` 模型生成并微调。
## 类描述
`TextContentParser` 是文字解析核心工具,用于处理文本排版、转义字符解析及动态样式管理。支持自动分词换行、图标嵌入和样式栈控制。
---
## 方法说明
### `parse`
```typescript
function parse(text: string, width: number): ITextContentRenderObject;
```
解析文本并生成渲染数据对象:
```typescript
interface ITextContentRenderObject {
lineHeights: number[]; // 每行高度
lineWidths: number[]; // 每行宽度
data: ITextContentRenderable[]; // 渲染元素集合
}
```
---
## 转义字符语法说明
### 1. 颜色控制 `\r[color]`
- **语法**`\r[颜色值]`
- **栈模式**:支持嵌套,用`\r`恢复上一级颜色
- **颜色格式**:支持 CSS 颜色字符串
```typescript
// 示例:红→黄→红→默认
'\\r[red]危险!\\r[yellow]警告\\r恢复红色\\r默认';
```
### 2. 字号控制 `\c[size]`
- **语法**`\c[字号(px)]`
- **栈模式**:用`\c`恢复上一级字号
```typescript
// 示例24px→32px→24px
'普通\\c[24]标题\\c[32]超大标题\\c恢复';
```
### 3. 字体家族 `\g[family]`
- **语法**`\g[字体名称]`
- **栈模式**:用`\g`恢复上一级字体
```typescript
'默认\\g[黑体]中文黑体\\g恢复默认';
```
### 4. 粗体切换 `\d`
- **语法**`\d`(开关模式)
```typescript
'正常\\d粗体\\d正常';
```
### 5. 斜体切换 `\e`
- **语法**`\e`(开关模式)
```typescript
'正常\\e斜体\\e正常';
```
### 6. 等待间隔 `\z[wait]`
- **语法**`\z[等待字符数]`
- **计算规则**`间隔时间 = 字符数 * 当前interval配置`
```typescript
'开始对话\\z[10]暂停500ms继续';
```
### 7. 图标嵌入 `\i[icon]`
- **语法**`\i[图标ID]`
- **图标规范**:需预加载到资源管理器
```typescript
'攻击\\i[sword]造成伤害';
```
### 8. 表达式 `${}`
- **语法**:与模板字符串语法一致,不过是在渲染的时候实时计算,而非字符串声明时计算
```typescript
'${core.status.hero.atk * 10}'; // 显示勇士攻击乘 10
'${core.status.hero.atk > 100 ? "高攻击" : "低攻击"}'; // 条件表达式
'${(() => { if (a > 10) return 100; else return 10; })()}'; // 嵌入函数
```
---
## 综合使用示例
### 战斗伤害提示
```typescript
const text =
'\\r[#ff0000]\\c[24]\\d敌人\\i[monster]对你造成\\c[32]\\r[yellow]500\\c\\r伤害\\z[5]\\d\\e按空格跳过';
const result = parser.parse(text, 400);
/* 解析结果:
[
{ type: 'text', color: '#ff0000', size:24, bold:true, text:'敌人' },
{ type: 'icon', id:'monster' },
{ type: 'text', color:'#ff0000', size:24, text:'对你造成' },
{ type: 'text', color:'yellow', size:32, text:'500' },
{ type: 'text', color:'#ff0000', size:24, text:'伤害!' },
{ type: 'wait', duration:250 }, // 假设 interval=50
{ type: 'text', bold:false, italic:true, text:'(按空格跳过)' }
]
*/
```
### 多语言混合排版
```typescript
const multiLangText =
'\\g[Times New Roman]Hello\\g[宋体]你好\\i[globe]\\z[3]\\g切换为\\r[blue]Français';
// 效果:英文→中文+地球图标→等待→蓝色法文
```
---
## 注意事项
1. **转义字符格式**
- 必须使用 **双反斜杠**`\\`)表示转义
- 错误示例:`\r[red]`(单反斜杠 `\r` 可能会被识别为换行)
- 正确示例:`\\r[red]`
2. **栈操作规则**
```typescript
// 颜色栈示例
'默认\\r[red]红\\r[blue]蓝\\r恢复红\\r恢复默认';
// 等效于push(默认)→push(红)→push(蓝)→pop→pop
```

View File

@ -0,0 +1,245 @@
# TextContentTyper API 文档
本文档由 `DeepSeek R1` 模型生成并微调。
```mermaid
graph LR
TextContentTyper --> EventEmitter
click EventEmitter "https://nodejs.org/api/events.html#class-eventemitter"
```
## 类描述
`TextContentTyper` 是文字逐字输出(打字机效果)的核心控制器,继承自 `EventEmitter`。用于管理文字排版、渲染时序及样式配置,支持动态修改文本内容和样式。
---
## 核心属性说明
| 属性名 | 类型 | 描述 |
| -------- | ----------------------- | ---------------------------------------------- |
| `config` | `Required<TyperConfig>` | 当前文字渲染配置(包含字体、行高、对齐等参数) |
| `parser` | `TextContentParser` | 文字解析器实例(负责分词、分行等底层处理) |
---
## 核心方法说明
### `constructor`
```typescript
function constructor(config: Partial<ITextContentConfig>): TextContentTyper;
```
初始化打字机实例,接受文字配置参数:
```typescript
interface ITextContentConfig {
/** 字体 */
font: Font;
/** 是否持续上一次的文本,开启后,如果修改后的文本以修改前的文本为开头,那么会继续播放而不会从头播放(暂未实现,后续更新) */
keepLast: boolean;
/** 打字机时间间隔,即两个字出现之间相隔多长时间 */
interval: number;
/** 行高 */
lineHeight: number;
/** 分词规则 */
wordBreak: WordBreak;
/** 文字对齐方式 */
textAlign: TextAlign;
/** 行首忽略字符,即不会出现在行首的字符 */
ignoreLineStart: Iterable<string>;
/** 行尾忽略字符,即不会出现在行尾的字符 */
ignoreLineEnd: Iterable<string>;
/** 会被分词规则识别的分词字符 */
breakChars: Iterable<string>;
/** 填充样式 */
fillStyle: CanvasStyle;
/** 描边样式 */
strokeStyle: CanvasStyle;
/** 线宽 */
strokeWidth: number;
/** 文字宽度,到达这么宽之后换行 */
width: number;
}
```
---
### `setConfig`
```typescript
function setConfig(config: Partial<ITextContentConfig>): void;
```
动态更新配置参数(支持部分更新)
---
### `setText`
```typescript
function setText(text: string): void;
```
设置要显示的文本内容(自动重置播放进度)
---
### `type`
```typescript
function type(): void;
```
启动逐字显示效果
---
### `typeAll`
```typescript
function typeAll(): void;
```
立即完整显示所有文字
---
### `setRender`
```typescript
function setRender(render: TyperFunction): void;
```
设置自定义渲染逻辑:
```typescript
type TyperFunction = (
data: TyperRenderable[], // 待渲染元素
typing: boolean // 是否正在播放中
) => void;
```
---
## 事件说明
| 事件名 | 参数 | 触发时机 |
| ----------- | ---- | ------------------ |
| `typeStart` | `[]` | 开始逐字显示时 |
| `typeEnd` | `[]` | 全部文字显示完成时 |
---
## 使用示例
### 基础用法 - 对话框文字
```typescript
// 初始化配置
const typer = new TextContentTyper({
font: new Font('黑体', 18),
interval: 50,
lineHeight: 1.2,
width: 400
});
// 设置文本内容
typer.setText(`「这是逐字显示的文字效果...
第二行会自动换行」`);
// 注册渲染逻辑
typer.setRender((elements, isTyping) => {
elements.forEach(element => {
if (element.type === TextContentType.Text) {
drawText(element.x, element.y, element.text);
}
});
});
// 开始播放
typer.type();
```
### 动态样式修改
```typescript
// 修改为红色斜体
typer.setConfig({
font: new Font('楷体', 20),
fillStyle: '#ff0000'
});
// 修改播放速度
typer.setConfig({ interval: 30 });
```
---
## 底层数据结构
### 渲染元素类型
```typescript
type TyperRenderable =
| TyperTextRenderable // 文本元素
| TyperIconRenderable // 图标元素
| TyperWaitRenderable; // 等待间隔
```
::: code-group
```ts [TyperTextRenderable]
interface TyperTextRenderable {
type: TextContentType.Text;
x: number;
y: number;
text: string;
font: string;
fillStyle: CanvasStyle;
strokeStyle: CanvasStyle;
/** 文字画到哪个索引 */
pointer: number;
/** 这段文字的总高度 */
height: number;
}
```
```ts [TyperIconRenderable]
interface TyperIconRenderable {
type: TextContentType.Icon;
x: number;
y: number;
width: number;
height: number;
renderable: RenderableData | AutotileRenderable;
}
```
```ts [TyperWaitRenderable]
interface TyperWaitRenderable {
type: TextContentType.Wait;
wait: number;
waited: number;
}
```
:::
---
## 注意事项
1. **性能优化**
当处理长文本(>1000 字)时,建议预调用 `parser.parse()` 进行分页
2. **坐标系统**
所有坐标基于初始化时设置的 `width` 参数进行相对计算
3. **动态修改限制**
在播放过程中修改配置可能导致渲染异常,建议在 `typeEnd` 事件后操作
4. **使用场景**
本接口的使用场景并不多,建议使用 `TextContent` 组件。如果必须使用的话,可以直接阅读源码来看一些实现细节。

View File

@ -0,0 +1,166 @@
# TextboxStore API 文档
本文档由 `DeepSeek R1` 模型生成并微调。
---
```mermaid
graph LR
TextboxStore --> EventEmitter
click EventEmitter "https://nodejs.org/api/events.html#class-eventemitter"
```
---
## 类描述
`TextboxStore` 是文本框的集中管理器,继承自 `EventEmitter`。所有 `Textbox` 组件实例化时会自动注册到该类的静态 `list` 中,支持通过 ID 精准控制特定文本框。
---
## 核心方法说明
### `TextboxStore.get`
```typescript
function get(id: string): TextboxStore | undefined;
```
**静态方法**:通过 ID 获取已注册的文本框控制器
- **参数**
`id`: 文本框的唯一标识符
- **返回值**
找到返回实例,否则返回 `undefined`
---
### `setText`
```typescript
function setText(text: string): void;
```
**动态更新文本内容**
- **特性**
- 自动重置打字机进度
- 触发重新排版计算
---
### `modify`
```typescript
function modify(data: Partial<TextboxProps>): void;
```
**动态修改文本框配置**
- **参数**
`data`: 需更新的属性(支持所有 `TextboxProps` 属性)
---
### `endType`
```typescript
function endType(): void;
```
**立即结束打字机动画**
- **特性**
- 强制显示全部文本
- 触发 `typeEnd` 事件
---
### `show`
```ts
function show(): void;
```
### `hide`
```ts
function hide(): void;
```
控制文本框的显示和隐藏。
---
## 使用示例
### 跨场景更新对话内容
```typescript
// 在剧情管理器中的调用
const updateChapterDialog = (chapterId: string) => {
const store = TextboxStore.get(`chapter_${chapterId}`);
store?.setText(getChapterText(chapterId));
store?.modify({ title: `第 ${chapterId} 章` });
};
```
### 紧急提示打断当前动画
```typescript
// 强制显示关键信息
const showEmergencyAlert = () => {
const alertBox = TextboxStore.get('system_alert');
alertBox?.setText('警告!基地即将爆炸!');
alertBox?.endType(); // 跳过打字动画
alertBox?.show();
};
```
### 动态样式调整
```typescript
// 根据昼夜切换对话框样式
const updateDialogStyle = (isNight: boolean) => {
TextboxStore.list.forEach(store => {
store.modify({
backColor: isNight ? '#1A1A32' : '#F0F0FF',
titleFill: isNight ? '#E6E6FA' : '#2F4F4F'
});
});
};
```
---
## 注意事项
1. **ID 管理规范**
建议显式指定可预测的 ID 格式:
```tsx
// 创建时指定可追踪 ID
<Textbox id={`npc_${npcId}_dialog`} ... />
```
2. **未找到实例处理**
调用前需做空值检测:
```typescript
const store = TextboxStore.get('custom_id');
if (!store) {
console.warn('文本框未注册: custom_id');
return;
}
```
3. **生命周期匹配**
在组件卸载时自动注销实例,请勿持有长期引用
4. **批量操作优化**
同时操作多个实例时建议使用迭代器:
```typescript
// 隐藏所有对话框
TextboxStore.list.forEach(store => store.hide());
```

View File

@ -0,0 +1,147 @@
# TipStore API 文档
本文档由 `DeepSeek R1` 模型生成并微调。
---
## 类描述
`TipStore` 是提示框的集中管理器,提供全局访问和控制提示组件的能力。所有通过 `<Tip>` 组件注册的实例会自动加入静态 `list` 容器,支持通过 ID 精准控制特定提示框。
---
## 核心方法说明
### `TipStore.get`
```typescript
function get(id: string): TipStore | undefined;
```
**静态方法**:通过 ID 获取已注册的提示框控制器
| 参数 | 类型 | 必填 | 说明 |
| ---- | -------- | ---- | ---------------- |
| `id` | `string` | 是 | 提示框的唯一标识 |
**返回值**:找到返回实例,否则返回 `undefined`
---
### `TipStore.use`
```typescript
function use(id: string, data: TipExpose): TipStore;
```
**静态方法**:注册提示框实例到全局管理器(通常在组件内部使用)
| 参数 | 类型 | 必填 | 说明 |
| ------ | ----------- | ---- | ----------------------- |
| `id` | `string` | 是 | 提示框的唯一标识 |
| `data` | `TipExpose` | 是 | 来自 Tip 组件的暴露接口 |
---
### `drawTip`
```typescript
function drawTip(text: string, icon?: AllIds | AllNumbers): void;
```
**显示提示内容**(支持带图标的提示)
| 参数 | 类型 | 必填 | 说明 |
| ------ | ---------------------- | ---- | ------------------------------- |
| `text` | `string` | 是 | 提示文字内容 |
| `icon` | `AllIds \| AllNumbers` | 否 | 图标资源 ID字符串或数字形式 |
**特性**
- 自动触发淡入动画
- 3 秒无操作后自动淡出
- 重复调用会重置计时器
---
## 使用示例
### 基础提示
```typescript
// 获取预先注册的提示框
const tip = TipStore.get('item-get-tip');
// 显示纯文本提示
tip?.drawTip('获得金币 x100');
// 显示带图标的提示
tip?.drawTip('获得 传说之剑', 'legend_sword');
```
### 全局广播提示
```typescript
// 向所有提示框发送通知
TipStore.list.forEach(store => {
store.drawTip('系统将在5分钟后维护', 'warning');
});
```
### 动态内容提示
```typescript
// 组合动态内容
const showDamageTip = (damage: number) => {
TipStore.get('combat-tip')?.drawTip(
`造成 ${damage} 点伤害`,
damage > 1000 ? 'critical_hit' : 'normal_hit'
);
};
```
---
## 生命周期管理
### 组件注册流程
```tsx
// 在组件定义时注册实例
<Tip id="quest-tip" loc={[20, 20, 400, 40]}></Tip>;
// 在业务逻辑中调用
const showQuestComplete = () => {
TipStore.get('quest-tip')?.drawTip('任务「勇者的试炼」完成!');
};
```
---
## 注意事项
1. **自动清理机制**
组件卸载时自动注销实例,跨场景访问时需确保目标组件已挂载
2. **错误处理**
建议封装安全访问方法:
```typescript
const safeDrawTip = (id: string, text: string) => {
const instance = TipStore.get(id);
if (!instance) {
console.error(`Tip ${id} not registered`);
return;
}
instance.drawTip(text);
};
```
3. **动画队列**
连续调用时会中断当前动画,建议重要提示添加延迟:
```typescript
tip.drawTip('第一条提示');
setTimeout(() => {
tip.drawTip('第二条重要提示');
}, 3200); // 等待淡出动画结束
```

View File

@ -0,0 +1,217 @@
# WeatherController API 文档
本文档由 `DeepSeek R1` 模型生成并微调。
```mermaid
graph LR
WeatherController --> IWeather
```
_实现 `IWeather` 接口_
## 类描述
`WeatherController` 是天气系统的核心控制器,支持动态管理多种天气效果(如雨、雪、雾等),可将天气效果绑定到任意渲染元素上,实现多场景独立天气控制。
---
## 属性说明
| 属性名 | 类型 | 描述 |
| -------------- | -------------------------------- | ----------------------------------------------------------------- |
| `id` | `string` | 只读,控制器的唯一标识符 |
| `active` | `Set<IWeather>` | 当前激活的天气实例集合 |
| `list`(静态) | `Map<string, Weather>` | 静态属性,存储所有注册的天气类型(键为天气 ID值为天气构造函数 |
| `map`(静态) | `Map<string, WeatherController>` | 静态属性,存储所有控制器实例 |
---
## 构造方法
```typescript
function constructor(id: string): WeatherController;
```
- **参数**
- `id`: 控制器的标识符
## 方法说明
### `activate`
```typescript
function activate(id: string, level?: number): IWeather | undefined;
```
激活指定天气。
- **参数**
- `id`: 已注册的天气 ID
- `level`: 天气强度等级(可选)
---
### `bind`
```typescript
function bind(item?: RenderItem): void;
```
绑定/解绑渲染元素。
- **参数**
- `item`: 要绑定的渲染元素(不传则解绑)
---
### `deactivate`
```typescript
function deactivate(weather: IWeather): void;
```
关闭指定天气效果。
---
### `clearWeather`
```typescript
function clearWeather(): void;
```
清空所有天气效果。
---
### `getWeather`
```typescript
function getWeather<T extends IWeather = IWeather>(
weather: new (level?: number) => T
): T | null;
```
获取指定天气实例。
**示例**
```ts
import { RainWeather } from '@user/client-modules';
const rain = controller.getWeather(RainWeather);
```
---
### `destroy`
```typescript
function destroy(): void;
```
摧毁这个天气控制器,摧毁后不可继续使用。
---
## 静态方法说明
### `WeatherController.register`
```typescript
function register(id: string, weather: Weather): void;
```
**静态方法**:注册新的天气类型。
- **参数**
- `id`: 天气唯一标识(如 "rain"
- `weather`: 天气类(需实现 `IWeather` 接口)
---
### `WeatherController.get`
```typescript
function get(id: string): WeatherController | undefined;
```
- **参数**
- `id`: 要获得的控制器标识符
## 天气接口说明
```typescript
interface IWeather {
activate(item: RenderItem): void; // 初始化天气效果
frame(): void; // 每帧更新逻辑
deactivate(item: RenderItem): void; // 清除天气效果
}
```
---
## 内置天气
- `rain`: 下雨天气
## 总使用示例 实现滤镜天气效果
::: code-group
```typescript [定义天气]
// 定义灰度滤镜天气
class GrayFilterWeather implements IWeather {
private scale: number;
private now: number = 0;
private item?: RenderItem;
constructor(level: number = 5) {
this.scale = level / 10;
}
activate(item: RenderItem) {
// 添加灰度滤镜
item.filter = `grayscale(0)`;
this.item = item;
}
frame() {
// 动态调整滤镜强度(示例:正弦波动)
if (this.item) {
const intensity = ((Math.sin(Date.now() / 1000) + 1) * scale) / 2;
this.item.filter = `grayscale(${itensity})`;
}
}
deactivate(item: RenderItem) {
item.filter = `none`;
}
}
// 注册天气类型
WeatherController.register('gray-filter', GrayFilterWeather);
```
```tsx [使用天气]
import { defineComponent, onMounted } from 'vue';
import { Container } from '@motajs/render';
import { useWeather } from '@user/client-modules';
const MyCom = defineComponent(() => {
const [controller] = useWeather();
const root = ref<Container>();
onMounted(() => {
// 绑定天气的渲染元素
controller.bind(root.value);
// 激活天气效果
controller.activate('gray-filter', 5);
});
return () => <container ref={root}></container>;
});
```
:::

View File

@ -0,0 +1,410 @@
# 模块函数 API 文档
本文档由 `DeepSeek R1` 模型生成并微调。
## 钩子
### `onOrientationChange`
```typescript
function onOrientationChange(hook: OrientationHook): void;
```
监听屏幕方向变化事件。
**参数**
- `hook`: 方向变化回调函数
```typescript
type OrientationHook = (
orientation: Orientation, // 当前方向
width: number, // 窗口宽度
height: number // 窗口高度
) => void;
```
**示例** - 响应式布局
```typescript
import { onOrientationChange, Orientation } from './use';
onOrientationChange((orient, width) => {
if (orient === Orientation.Portrait) {
// 竖屏模式
adjustMobileLayout(width);
} else {
// 横屏模式
resetDesktopLayout();
}
});
```
---
### `onLoaded`
```typescript
function onLoaded(hook: () => void): void;
```
在游戏核心资源加载完成后执行回调(若已加载则立即执行)。
---
## 过渡动画控制
### 通用接口
```typescript
interface ITransitionedController<T> {
readonly ref: Ref<T>; // 响应式引用
readonly value: T; // 当前值
set(value: T, time?: number): void; // 设置目标值
mode(timing: TimingFn): void; // 设置缓动曲线
setTime(time: number): void; // 设置默认时长
}
```
### `transitioned`
```typescript
function transitioned(
value: number, // 初始值
time: number, // 默认过渡时长ms
curve: TimingFn // 缓动函数(如 linear()
): ITransitionedController<number> | null;
```
创建数值渐变控制器(仅限组件内使用)。
**示例** - 旋转动画
```tsx
// Vue 组件内
const rotate = transitioned(0, 500, hyper('sin', 'out'));
// 触发动画
rotate.set(Math.PI, 800); // 800ms 内旋转到 180 度
// 模板中使用
<text rotate={rotate.ref.value} text="一些显示内容" />;
```
### `transitionedColor`
```typescript
function transitionedColor(
color: string, // 初始颜色(目前支持 #RGB/#RGBA/rgb()/rgba()
time: number, // 默认过渡时长ms
curve: TimingFn // 缓动函数
): ITransitionedController<string> | null;
```
创建颜色渐变控制器(仅限组件内使用)。
**示例** - 背景色过渡
```tsx
// Vue 组件内
const bgColor = transitionedColor('#fff', 300, linear());
// 触发颜色变化
bgColor.set('rgba(255, 0, 0, 0.5)'); // 渐变为半透明红色
// 模板中使用
<g-rect fillStyle={bgColor.ref.value} />;
```
---
### 注意事项
1. **组件生命周期**:过渡控制器必须在 Vue 组件内部创建,卸载时自动销毁
2. **性能优化**:避免在频繁触发的回调(如每帧渲染)中创建新控制器
3. **颜色格式**`transitionedColor` 支持 HEX/RGB/RGBA但不支持 HSL
4. **默认时长**:调用 `set()` 时不传时间参数则使用初始化时设置的时间
### 高级用法示例
#### 组合动画
```typescript
// 同时控制位置和透明度
const posX = transitioned(0, 500, linear());
const alpha = transitioned(1, 300, linear());
const moveAndFade = () => {
posX.set(200);
alpha.set(0);
};
// 组件卸载时自动清理动画资源
```
## 组件控制
### `getConfirm`
```typescript
function getConfirm(
controller: IUIMountable, // UI 控制器
text: string, // 确认内容
loc: ElementLocator, // 定位配置
width: number, // 对话框宽度(像素)
props?: Partial<ConfirmBoxProps> // 扩展配置
): Promise<boolean>;
```
---
#### 参数说明
| 参数名 | 类型 | 必填 | 描述 |
| ------------ | -------------------------- | ---- | ---------------------------------------------- |
| `controller` | `IUIMountable` | 是 | UI 控制器实例(通常从组件 props 获取) |
| `text` | `string` | 是 | 需要用户确认的文本内容 |
| `loc` | `ElementLocator` | 是 | 对话框位置配置(需包含 x,y 坐标及锚点) |
| `width` | `number` | 是 | 对话框宽度(像素),高度自动计算 |
| `props` | `Partial<ConfirmBoxProps>` | 否 | 扩展配置项(支持所有 ConfirmBox 组件的 props |
---
#### 返回值
返回 `Promise<boolean>`
- `true` 表示用户点击确认
- `false` 表示用户取消或关闭
---
#### 使用示例
##### 基础用法 - 删除确认
```tsx
import { defineComponent } from 'vue';
import { DefaultProps } from '@motajs/render';
import { GameUI } from '@motajs/system-ui';
// 在业务逻辑中调用,注意,组件需要使用 UI 控制器打开,它会自动传递 controller 参数
const MyCom = defineComponent<DefaultProps>(props => {
const handleDeleteItem = async (itemId: string) => {
const confirmed = await getConfirm(
props.controller, // 从组件 props 获取控制器
`确认删除 ID 为 ${itemId} 的项目吗?`,
[208, 208, void 0, void 0, 0.5, 0.5], // 居中显示
208
);
if (confirmed) {
api.deleteItem(itemId);
}
};
return () => (
<container>
{/* 假设有一个按钮在点击后触发上面的删除函数 */}
<text text="删除" onClick={() => handleDeleteItem(item.id)} />
</container>
);
});
export const MyUI = new GameUI('my-ui', MyCom);
```
##### 自定义按钮文本
```typescript
import { mainUIController } from '@user/client-modules';
// 注意,如果在 client-modules/render/ui 下编写代码,应该引入:
import { mainUIController } from './controller.ts';
// 修改确认/取消按钮文案
const result = await getConfirm(
// 传入主 UI 控制器也可以
mainUIController,
'切换场景将丢失未保存进度',
[208, 208, void 0, void 0, 0.5, 0.5],
320,
{
yesText: '继续切换',
noText: '留在当前',
selFill: '#e74c3c',
border: '#c0392b'
}
);
```
---
### `getChoice`
```typescript
function getChoice<T extends ChoiceKey = ChoiceKey>(
controller: IUIMountable, // UI 控制器
choices: ChoiceItem[], // 选项数组
loc: ElementLocator, // 定位配置
width: number, // 对话框宽度(像素)
props?: Partial<ChoicesProps> // 扩展配置
): Promise<T>;
```
#### 参数说明
| 参数名 | 类型 | 必填 | 描述 |
| ------------ | ----------------------- | ---- | ------------------------------------------- |
| `controller` | `IUIMountable` | 是 | UI 控制器实例(通常从组件 props 获取) |
| `choices` | `ChoiceItem[]` | 是 | 选项数组,格式为 `[key, text]` 的元组 |
| `loc` | `ElementLocator` | 是 | 对话框位置配置(需包含 x,y 坐标及锚点) |
| `width` | `number` | 是 | 对话框宽度(像素),高度自动计算 |
| `props` | `Partial<ChoicesProps>` | 否 | 扩展配置项(支持所有 Choices 组件的 props |
#### 返回值
返回 `Promise<T>`
- 解析为选中项的 `key`
#### 使用示例
##### 基础用法 - 难度选择
```typescript
import { getChoice, mainUIController } from '@user/client-modules';
// 写到异步函数里面
const selectedDifficulty = await getChoice(
mainUIController,
[
['easy', '新手模式'],
['normal', '普通模式'],
['hard', '困难模式']
],
[208, 208, void 0, void 0, 0.5, 0.5], // 居中显示
208,
{
title: '选择难度',
titleFont: new Font('黑体', 24)
}
);
// 判断选择的内容
if (selectedDifficulty === 'hard') {
applyHardcoreRules();
}
```
##### 分页支持 - 角色选择
```typescript
import { getChoice, mainUIController } from '@user/client-modules';
// 生成 200 个角色选项
const characterOptions = Array.from(
{ length: 200 },
(_, i) => [i, `角色 #${i + 1}`] as ChoiceItem
);
const chosenId = await getChoice(
mainUIController,
characterOptions,
[208, 208, void 0, void 0, 0.5, 0.5],
208,
{
maxHeight: 400, // 超过 400px 自动分页
winskin: 'winskin.png',
interval: 12
}
);
```
##### 动态样式配置
```typescript
import { getChoice, mainUIController } from '@user/client-modules';
// 自定义主题风格
const choiceResult = await getChoice(
mainUIController,
[
['light', '浅色主题'],
['dark', '深色主题'],
['oled', 'OLED 深黑']
],
[208, 208, void 0, void 0, 0.5, 0.5],
300,
{
color: 'rgba(30,30,30,0.9)',
border: '#4CAF50',
selFill: '#81C784',
titleFill: '#FFF59D'
}
);
```
### `waitbox`
```typescript
function waitbox<T>(
controller: IUIMountable,
loc: ElementLocator,
width: number,
promise: Promise<T>,
props?: Partial<WaitBoxProps<T>>
): Promise<T>;
```
#### 参数说明
| 参数名 | 类型 | 必填 | 默认值 | 描述 |
| ------------ | -------------------------- | ---- | ------ | ---------------------------------------------------- |
| `controller` | `IUIMountable` | 是 | - | UI 挂载控制器(通常传递父组件的 `props.controller` |
| `loc` | `ElementLocator` | 是 | - | 定位参数 |
| `width` | `number` | 是 | - | 内容区域宽度(像素) |
| `promise` | `Promise<T>` | 是 | - | 要监视的异步操作 |
| `props` | `Partial<WaitBoxProps<T>>` | 否 | `{}` | 扩展配置项(继承 `Background` + `TextContent` 属性) |
---
#### 返回值
| 类型 | 说明 |
| ------------ | ----------------------------------------------------------------------------------- |
| `Promise<T>` | 与传入 `Promise` 联动的代理 `Promise`,在以下情况会 `reject`:原始 `Promise` 被拒绝 |
---
#### 使用示例
##### 等待网络请求
```typescript
// 获取用户数据
const userData = await waitbox(
props.controller,
[400, 300, void 0, void 0, 0.5, 0.5], // 居中定位
300,
fetch('/api/user'),
{
text: '加载用户信息...',
winskin: 'ui/loading_panel'
}
);
```
### 注意事项
1. **控制器有效性**
必须确保传入的 `controller` 已正确挂载且未销毁
2. **异步特性**
需使用 `await``.then()` 处理返回的 Promise
3. **定位系统**
Y 轴坐标基于 Canvas 坐标系(向下为正方向)
4. **额外参考**
- [组件 ConfirmBox](./组件%20ConfirmBox.md)
- [组件 Choices](./组件%20Choices.md)
- [组件 Waitbox](./组件%20Waitbox.md)

View File

@ -0,0 +1,3 @@
# @user/client-modules
目录:

View File

@ -0,0 +1,37 @@
# 图标组件 API
## Props 属性说明
| 属性名 | 类型 | 必填 | 描述 |
| ------ | ---------------- | ---- | ---------- |
| `loc` | `ElementLocator` | 是 | 图标定位符 |
图标比例固定,会自动根据传入的长宽缩放。
## 图标列表
- `RollbackIcon`: 回退图标
- `RetweenIcon`: 回收图标
- `ViewMapIcon`: 浏览地图图标
- `DanmakuIcon`: 弹幕图标
- `ReplayIcon`: 回放图标
- `numpadIcon`: 数字键盘图标
- `PlayIcon`: 开始播放图标
- `PauseIcon`: 暂停播放图标
- `DoubleArrow`: 双箭头图标(向右)
- `StepForward`: 单步向前图标
## 使用示例
```tsx
import { defineComponent } from 'vue';
import { RollbackIcon } from '@user/client-modules';
export const MyCom = defineComponent(() => {
return () => (
<container>
<RollbackIcon loc={[32, 32, 64, 64]} />
</container>
);
});
```

View File

@ -0,0 +1,50 @@
# Arrow 组件 API 文档
本文档由 `DeepSeek R1` 模型生成并微调。
---
## 核心特性
- **两点连线**:通过坐标点绘制任意方向箭头
- **头部定制**:可调节箭头尖端大小
- **样式控制**:支持颜色自定义
---
## Props 属性说明
| 属性名 | 类型 | 默认值 | 描述 |
| ------- | ---------------------------------- | ------ | ----------------------------------------- |
| `arrow` | `[number, number, number, number]` | 必填 | 箭头坐标 [起点 x, 起点 y, 终点 x, 终点 y] |
| `head` | `number` | `8` | 箭头头部尺寸(像素) |
| `color` | `CanvasStyle` | `#fff` | 箭头颜色 |
---
## 使用示例
### 基础箭头
```tsx
// 从 (50, 100) 到 (200, 300) 的基础箭头
<Arrow arrow={[50, 100, 200, 300]} />
```
### 定制样式
```tsx
// 红色粗箭头头部尺寸12px
<Arrow arrow={[120, 80, 320, 400]} head={12} color="#FF0000" lineWidth={3} />
```
### 虚线箭头
```tsx
// 带虚线效果的箭头
<Arrow
arrow={[0, 0, 400, 300]}
lineDash={[5, 3]} // 5px实线 + 3px间隔
color="gold"
/>
```

View File

@ -0,0 +1,78 @@
# Background 背景组件 API 文档
本文档由 `DeepSeek R1` 模型生成并微调。
---
## 核心特性
- **双样式模式**:支持图片皮肤或纯色填充
- **精准定位**:像素级坐标控制
- **静态呈现**:无内置动画的稳定背景层
---
## Props 属性说明
| 属性名 | 类型 | 默认值 | 描述 |
| --------- | ---------------- | -------- | ----------------------------- |
| `loc` | `ElementLocator` | **必填** | 背景定位 |
| `winskin` | `ImageIds` | - | 皮肤图片资源 ID优先级最高 |
| `color` | `CanvasStyle` | `"#333"` | 填充颜色(无皮肤时生效) |
| `border` | `CanvasStyle` | `"#666"` | 边框颜色(无皮肤时生效) |
---
## 使用示例
### 图片皮肤模式
```tsx
// 使用预加载的UI背景图
<Background loc={[0, 0, 416, 416]} winskin="winskin.png" />
```
### 纯色模式
```tsx
// 自定义颜色背景
<Background
loc={[20, 20, 760, 560]}
color="gold"
border="rgba(255,255,255,0.2)"
/>
```
### 对话框组合
```tsx
// 对话框容器
<container loc={[200, 100, 400, 300]}>
<Background loc={[0, 0, 400, 300]} winskin="winskin.png" />
<text loc={[20, 20]} content="系统提示" font={titleFont} />
<text loc={[30, 60]} content="确认要离开吗?" font={contentFont} />
</container>
```
---
## 注意事项
1. **样式优先级**
同时指定参数时的生效顺序:
```tsx
// 以下配置仅生效 winskin
<Background winskin="bg_wood" color="#FF0000" />
```
2. **默认边框**
未指定 border 时的行为:
```tsx
// 无边框(指定为透明色)
<Background color="#222" border="transparent" />;
// 默认白色边框(当未指定任何参数时)
<Background />;
```

View File

@ -0,0 +1,159 @@
# Choices 选项框组件 API 文档
本文档由 `DeepSeek R1` 模型生成并微调。
---
## 组件特性
- **多选一机制**:从多个选项中选择一项
- **自动分页**:通过 `maxHeight` 控制分页
- **灵活样式**:支持图片背景/纯色背景 + 自定义字体
- **键盘导航**:方向键选择 + Enter 确认
- **动态内容**:支持异步加载选项数据
---
## Props 属性说明
```mermaid
graph LR
ConfirmBoxProps --> TextContentProps
click TextContentProps "./组件%20TextContent"
```
本组件完全继承 `TextContent` 组件的参数,参考 [组件 TextContent](./组件%20TextContent.md)
| 属性名 | 类型 | 默认值 | 描述 |
| ----------- | ---------------- | -------- | ------------------------------------- |
| `choices` | `ChoiceItem[]` | 必填 | 选项数组,格式为 `[key, text]` 的元组 |
| `loc` | `ElementLocator` | 必填 | 定位配置(需包含 x,y 坐标及锚点) |
| `width` | `number` | 必填 | 选项框宽度(像素) |
| `maxHeight` | `number` | `360` | 最大高度(超过时自动分页) |
| `text` | `string` | - | 主说明文本(显示在标题下方) |
| `title` | `string` | - | 标题文本 |
| `winskin` | `ImageIds` | - | 背景图片资源 ID与 color 互斥) |
| `color` | `CanvasStyle` | `#333` | 背景颜色(未设置 winskin 时生效) |
| `border` | `CanvasStyle` | `gold` | 边框颜色/样式 |
| `selFont` | `Font` | 系统默认 | 选项文本字体 |
| `selFill` | `CanvasStyle` | `#fff` | 选项文本颜色 |
| `titleFont` | `Font` | 系统默认 | 标题字体 |
| `titleFill` | `CanvasStyle` | `gold` | 标题颜色 |
| `interval` | `number` | `16` | 选项间垂直间距(像素) |
---
## Events 事件说明
| 事件名 | 参数 | 触发时机 |
| -------- | ---------------- | ---------------------- |
| `choose` | `key: ChoiceKey` | 用户选择任意选项时触发 |
---
## 使用示例
### 基础用法 - 系统设置
```tsx
import { defineComponent } from 'vue';
import { Choices, ChoiceItem } from '@user/client-modules';
export const MyCom = defineComponent(() => {
const options: ChoiceItem[] = [
['low', '低画质'],
['medium', '中画质'],
['high', '高画质']
];
return () => (
<Choices
choices={options}
loc={[208, 208, void 0, void 0, 0.5, 0.5]}
width={208}
title="图形质量设置"
text="请选择适合您设备的画质等级"
// key 在这里是每个选项的第一个元素,即 low, medium, high
onChoose={key => console.log(`Choose ${key}.`)}
/>
);
});
```
### 分页处理 - 角色选择
```tsx
import { defineComponent } from 'vue';
import { Choices, ChoiceItem } from '@user/client-modules';
export const MyCom = defineComponent(() => {
// 生成 50 个角色选项
const characters: ChoiceItem[] = Array.from(
{ length: 50 },
(_, i) => [`char_${i}`, `角色 ${i + 1}`] as ChoiceItem
);
return () => (
<Choices
choices={characters}
loc={[208, 208, void 0, void 0, 0.5, 0.5]}
width={208}
maxHeight={400} // 高度超过 400px 自动分页
interval={12}
winskin="winskin.png"
// 粗体20px 大小的 Verdana 字体
titleFont={new Font('Verdana', 20, 'px', 700)}
selFill="#4CAF50"
/>
);
});
```
### 动态内容 + 自定义样式
```tsx
import { defineComponent } from 'vue';
import { Choices, ChoiceItem } from '@user/client-modules';
import { onTick } from '@motajs/render';
export const MyCom = defineComponent(() => {
const dynamicOptions = ref<ChoiceItem[]>([]);
onTick(() => {
// 每帧生成随机选项名称
dynamicOptions.value = Array.from(
{ length: 50 },
(_, i) =>
[
`char_${i}`,
`随机数 ${Math.random().toFixed(8)}`
] as ChoiceItem
);
});
return () => (
<Choices
choices={dynamicOptions.value}
loc={[208, 208, void 0, void 0, 0.5, 0.5]}
width={208}
color="rgba(30,30,30,0.9)"
border="#607D8B"
title="选择随机数"
titleFill="#B2EBF2"
/>
);
});
```
---
## 注意事项
1. **选项键值唯一性**
每个选项的 `key` 必须唯一,否则可能引发不可预期行为
2. **分页计算规则**
分页依据 `maxHeight` 和字体大小自动计算,需确保字体大小一致
3. **使用更方便的函数**:多数情况下,你不需要使用本组件,使用包装好的函数往往会更加方便,参考 [`getChoice`](./functions.md#getchoice)

View File

@ -0,0 +1,124 @@
# ConfirmBox 确认框组件 API 文档
本文档由 `DeepSeek R1` 模型生成并微调。
## 组件特性
- **双选项支持**:是/否选择
- **灵活样式**:支持图片背景或纯色背景
- **键盘交互**:支持按键操作
- **自动布局**:根据内容动态计算高度
- **事件驱动**:提供明确的用户选择反馈
---
## Props 属性说明
```mermaid
graph LR
ConfirmBoxProps --> TextContentProps
click TextContentProps "./组件%20TextContent"
```
本组件完全继承 `TextContent` 组件的参数,参考 [组件 TextContent](./组件%20TextContent.md)
| 属性名 | 类型 | 默认值 | 描述 |
| ------------ | ---------------- | ------------ | --------------------------------- |
| `text` | `string` | 必填 | 显示的主文本内容 |
| `width` | `number` | 必填 | 确认框宽度(像素) |
| `loc` | `ElementLocator` | 必填 | 定位配置 |
| `winskin` | `ImageIds` | - | 背景图片资源 ID与 color 互斥) |
| `color` | `CanvasStyle` | `'#333'` | 背景颜色(未设置 winskin 时生效) |
| `border` | `CanvasStyle` | `'gold'` | 边框颜色/样式 |
| `selFont` | `Font` | 系统默认字体 | 选项按钮字体 |
| `selFill` | `CanvasStyle` | `'#d48'` | 选项按钮文本颜色 |
| `yesText` | `string` | `'是'` | 确认按钮文本 |
| `noText` | `string` | `'否'` | 取消按钮文本 |
| `defaultYes` | `boolean` | `true` | 默认选中确认按钮 |
---
## Events 事件说明
| 事件名 | 参数 | 触发时机 |
| ------ | ---- | --------------------------- |
| `yes` | - | 用户选择确认时触发 |
| `no` | - | 用户选择取消或按 Esc 时触发 |
---
## 使用示例
### 基础用法 - 文本确认
```tsx
import { defineComponent } from 'vue';
import { ConfirmBox } from '@user/client-modules';
export const MyCom defineComponent(() => {
return () => (
<ConfirmBox
text="确定要保存当前进度吗?"
width={208}
loc={[208, 208, void 0, void 0, 0.5, 0.5]}
onYes={() => console.log('用户确认保存')}
onNo={() => console.log('用户取消保存')}
/>
);
});
```
### 图片背景 + 自定义按钮
```tsx
import { defineComponent } from 'vue';
import { ConfirmBox } from '@user/client-modules';
import { Font } from '@motajs/render';
export const MyCom = defineComponent(() => {
return () => (
<ConfirmBox
text="此操作不可逆,是否继续?"
width={208}
loc={[208, 208, void 0, void 0, 0.5, 0.5]}
// 背景使用 winskin
winskin="winskin.png"
yesText="确认删除"
noText="取消操作"
// 设置选项字体
selFont={new Font('Verdana')}
selFill="#f44"
/>
);
});
```
### 动态内容 + 编程控制
```tsx
import { defineComponent, computed } from 'vue';
import { ConfirmBox } from '@user/client-modules';
export const MyCom = defineComponent(() => {
const count = ref(0);
const myText = computed(() => `当前确认次数与取消次数差值:${count.value}`);
return () => (
<ConfirmBox
text={myText.value}
width={360}
loc={[208, 208, void 0, void 0, 0.5, 0.5]}
color="rgba(0,0,0,0.8)"
border="#4CAF50"
defaultYes={false}
onYes={() => void count.value++} // 每次确认次数加一
onNo={() => void count.value--} // 每次确认次数减一
/>
);
});
```
## 注意事项
1. **使用更方便的函数**:多数情况下,你不需要使用本组件,使用包装好的函数往往会更加方便,参考 [`getConfirm`](./functions.md#getconfirm)

View File

@ -0,0 +1,192 @@
# Page 分页组件 API 文档
本文档由 `DeepSeek R1` 模型生成并微调。
## 组件描述
分页组件用于将大量内容分割为多个独立页面展示,支持通过编程控制或用户交互进行页面切换。适用于存档界面、多步骤表单等场景。
---
## Props 属性说明
| 属性名 | 类型 | 默认值 | 描述 |
| -------------- | ---------------- | ----------------- | -------------------------------- |
| `pages` | `number` | 必填 | 总页数 |
| `loc` | `ElementLocator` | 必填 | 页码组件定位配置(坐标系及位置) |
| `font` | `Font` | `Font.defaults()` | 页码文本字体配置(可选) |
| `hideIfSingle` | `boolean` | `false` | 当总页数为 1 时是否隐藏页码组件 |
---
## Events 事件说明
| 事件名 | 参数类型 | 触发时机 |
| ------------ | ---------------- | ------------------------------- |
| `pageChange` | `(page: number)` | 当前页码变化时触发(从 0 开始) |
---
## Slots 插槽说明
### `default`
接收当前页码(从 0 开始)并返回需要渲染的内容
**参数**
- `page: number` 当前页码索引0-based
---
## Exposed Methods 暴露方法
| 方法名 | 参数 | 返回值 | 描述 |
| ------------ | --------------- | -------- | --------------------------------------------------- |
| `changePage` | `page: number` | `void` | 跳转到指定页码0-based自动约束在有效范围内 |
| `movePage` | `delta: number` | `void` | 基于当前页码进行偏移切换(如 +1 下一页,-1 上一页) |
| `now` | - | `number` | 获取当前页码索引0-based |
---
## 使用示例
### 基础用法 - 多页文本展示
```tsx
import { defineComponent } from 'vue';
import { Page, PageExpose } from '@user/client-modules';
export const MyCom = defineComponent(() => {
return () => (
<Page pages={3} loc={[208, 208, 208, 208, 0.5, 0.5]}>
{page => (
<text
text={`第 ${page + 1} 页内容`}
loc={[104, 104, void 0, void 0, 0.5, 0.5]}
/>
)}
</Page>
);
});
```
### 监听页面修改
```tsx
import { defineComponent, ref } from 'vue';
import { Page, PageExpose } from '@user/client-modules';
export const MyCom = defineComponent(() => {
// 示例数据
const pages = [
{ content: '第一页内容' },
{ content: '第二页内容' },
{ content: '第三页内容' }
];
// 分页组件引用
const pageRef = ref<PageExpose>();
// 页码变化回调
const handlePageChange = (currentPage: number) => {
// 可以使用参数获得当前页码,加一是因为页码是从 0 开始的
console.log(`当前页码:${currentPage + 1}`);
// 或者也可以使用 Page 组件的接口获得当前页码
console.log(`当前页码:${pageRef.value!.now() + 1}`);
};
return () => (
<Page
pages={pages.length}
loc={[208, 208, 208, 208, 0.5, 0.5]} // 游戏画面居中
onPageChange={handlePageChange}
ref={pageRef}
>
{page => <text text={pages[page].content} />}
</Page>
);
});
```
### 动态配置示例
```tsx
import { defineComponent, ref } from 'vue';
import { Page, PageExpose } from '@user/client-modules';
// 带统计面板的复杂分页
export const MyCom = defineComponent(() => {
const dataPages = [
/* 复杂数据结构 */
];
// 暴露方法实现翻页逻辑
const pageRef = ref<PageExpose>();
const jumpToAnalysis = () => pageRef.value?.changePage(3); // 1-based
return () => (
<container>
{/* 分页内容 */}
<Page
pages={dataPages.length}
loc={[208, 208, 208, 208, 0.5, 0.5]}
hideIfSingle // 如果只有一个页面,那么隐藏底部的页码显示
ref={pageRef}
>
{page => (
<container>
{/* 这里面可以写一些复杂的渲染内容,或者单独写成一个组件,把页码作为参数传入 */}
<text text="渲染内容" />
<g-rect loc={[50, 50, 100, 50]} stroke />
</container>
)}
</Page>
{/* 自定义跳转按钮 */}
<text
loc={[108, 180, void 0, void 0, 0.5, 1]} // 左右居中,靠下对齐
onClick={jumpToAnalysis}
text="跳转到分析页"
/>
</container>
);
});
```
### 边缘检测示例
```tsx
import { defineComponent, ref } from 'vue';
// 边界处理逻辑
export const MyCom = defineComponent(() => {
const pageRef = ref<PageExpose>();
// 自定义边界提示
const handleEdge = () => {
const current = pageRef.value?.now() ?? 0;
const total = pageRef.value?.pages ?? 0;
// 到达边界时提示(可以换成其他提示方式)
if (current === 0) core.drawTip('已经是第一页');
if (current === total - 1) core.drawTip('已经是最后一页');
};
return () => (
<Page
pages={8}
ref={pageRef}
onPageChange={handleEdge}
loc={[208, 208, 208, 208, 0.5, 0.5]}
>
{page => <text text={`第${page}页`} />}
</Page>
);
});
```
---
## 注意事项
1. **自动约束**:切换页码时会自动约束在 `[0, pages-1]` 范围内

View File

@ -0,0 +1,107 @@
# Progress 组件 API 文档
本文档由 `DeepSeek R1` 模型生成并微调。
---
## 核心特性
- **动态进度显示**:支持 0.0~1.0 范围的进度可视化
- **双色样式分离**:可分别定制已完成/未完成部分样式
- **精准定位**:支持像素级坐标控制
- **平滑过渡**:数值变化自动触发重绘
---
## Props 属性说明
| 属性名 | 类型 | 默认值 | 描述 |
| ------------ | ---------------- | -------- | --------------------- |
| `loc` | `ElementLocator` | **必填** | 进度条容器坐标 |
| `progress` | `number` | **必填** | 当前进度值0.0~1.0 |
| `success` | `CanvasStyle` | `green` | 已完成部分填充样式 |
| `background` | `CanvasStyle` | `gray` | 未完成部分填充样式 |
| `lineWidth` | `number` | `2` | 进度条线宽(像素) |
---
## 使用示例
### 基础用法
```tsx
import { defineComponent, ref } from 'vue';
import { Progress } from '@user/client-modules';
import { onTick } from '@motajs/render';
export const MyCom = defineComponent(() => {
// 创建响应式进度值
const loadingProgress = ref(0);
// 模拟进度更新
onTick(() => {
if (loadingProgress.value < 1) {
loadingProgress.value += 0.002;
}
});
return () => (
<Progress
loc={[20, 20, 200, 8]} // x=20, y=20, 宽200px, 高8px
progress={loadingProgress.value}
/>
);
});
```
### 自定义样式
```tsx
// 自定义进度条的已完成和未完成部分的样式
<Progress
loc={[50, 100, 300, 12]}
progress={0.65}
success="rgb(54, 255, 201)"
background="rgba(255,255,255,0.2)"
lineWidth={6}
/>
```
### 垂直进度条
```tsx
// 通过旋转容器实现垂直效果,注意锚点的使用
<container rotation={-Math.PI / 2} loc={[100, 200, 150, 8, 0.5, 0.5]}>
<Progress loc={[0, 0, 150, 8]} progress={0.8} success="#FF5722" />
</container>
```
---
## 动画效果实现
### 平滑过渡示例
```tsx
import { transitioned } from '@user/client-modules';
import { pow } from 'mutate-animate';
const progressValue = transitioned(0, 2000, pow(2, 'out'));
progressValue.set(1); // 2秒内完成二次曲线平滑过渡
return () => (
<Progress loc={[0, 0, 400, 10]} progress={progressValue.ref.value} />
);
```
---
## 注意事项
1. **坐标系统**
实际渲染高度由 `loc[3]` 参数控制,会自动上下居中:
```tsx
// 情况1显式指定高度为8px
<Progress loc={[0, 0, 200, 8]} />
```

View File

@ -0,0 +1,118 @@
# Scroll 滚动组件 API 文档
本文档由 `DeepSeek R1` 模型生成并微调。
## 组件特性
- **虚拟滚动**:自动裁剪可视区域外元素
- **双模式支持**:垂直/水平滚动(默认垂直)
- **性能优化**:动态计算可视区域,支持万级元素流畅滚动
- **编程控制**:支持精准定位滚动位置
---
## Props 属性说明
| 属性名 | 类型 | 默认值 | 描述 |
| ---------- | ---------------- | ------- | ------------------------------------------------- |
| `hor` | `boolean` | `false` | 启用水平滚动模式 |
| `noscroll` | `boolean` | `false` | 是否不显示滚动条,可用于一些特殊场景 |
| `loc` | `ElementLocator` | 必填 | 滚动容器定位配置 |
| `padEnd` | `number` | `0` | 滚动到底部/右侧的额外留白(用于修正自动计算误差) |
---
## Exposed Methods 暴露方法
| 方法名 | 参数 | 返回值 | 描述 |
| ----------------- | --------------------------------- | -------- | --------------------------------------------------- |
| `scrollTo` | `position: number, time?: number` | `void` | 滚动到指定位置单位像素time 为过渡时间ms |
| `getScrollLength` | - | `number` | 获取最大可滚动距离(单位:像素) |
---
## Slots 插槽说明
### `default`
接收滚动内容,**必须直接包含可渲染元素**
⚠️ 禁止嵌套 container 包裹,推荐平铺结构:
```tsx
// ✅ 正确写法
<Scroll>
<item />
<item />
<item />
</Scroll>;
// ❌ 错误写法(影响虚拟滚动计算)
<Scroll>
<container>
// 会导致整体被视为单个元素
<item />
<item />
</container>
</Scroll>;
```
---
## 使用示例
### 基础垂直滚动
```tsx
import { defineComponent } from 'vue';
export const MyCom = defineComponent(() => {
const list = Array(200).fill(0);
return () => (
<Scroll loc={[208, 208, 208, 208, 0.5, 0.5]}>
{list.map((_, index) => (
<text key={index} text={index.toString()} />
))}
</Scroll>
);
});
```
### 水平滚动 + 编程控制
```tsx
import { defineComponent, ref, onMounted } from 'vue';
export const MyCom = defineComponent(() => {
const list = Array(200).fill(0);
const scrollRef = ref<ScrollExpose>();
// 滚动水平 100 像素位置,动画时长 500 毫秒
onMounted(() => {
scrollRef.value?.scrollTo(100, 500);
});
return () => (
<Scroll hor loc={[208, 208, 208, 208, 0.5, 0.5]} ref={scrollRef}>
{list.map((_, index) => (
<text key={index} text={index.toString()} />
))}
</Scroll>
);
});
```
---
## 性能优化指南
### 1. 替代方案建议
⚠️ **当子元素数量 > 1000 时**,推荐改用分页组件:
```tsx
// 使用 Page 组件处理超大数据集
<Page pages={Math.ceil(data.length / 50)}>
{page => renderChunk(data.slice(page * 50, (page + 1) * 50))}
</Page>
```

View File

@ -0,0 +1,160 @@
# ScrollText 组件 API 文档
本文档由 `DeepSeek R1` 模型生成并微调。
---
## 核心特性
- **自动滚动**:支持设定滚动速度的纵向滚动效果
- **长文本支持**:内置高性能文本渲染引擎
- **精准控制**:提供播放/暂停/调速等操作接口
- **智能布局**:自动计算文本高度和滚动距离
---
## Props 属性说明
```mermaid
graph LR
ScrollTextProps --> TextContentProps
ScrollTextProps --> ScrollProps
click TextContentProps "./组件%20TextContent"
click ScrollProps "./组件%20Scroll"
```
完全继承 `TextContent` 组件和 `Scroll` 组件的参数和事件。
| 属性名 | 类型 | 默认值 | 描述 |
| ------- | ---------------- | ------ | --------------------------- |
| `speed` | `number` | 必填 | 滚动速度(像素/秒) |
| `width` | `number` | 必填 | 文本区域固定宽度(像素) |
| `loc` | `ElementLocator` | 必填 | 容器定位 [x,y,width,height] |
| `pad` | `number` | `16` | 首行前空白距离(像素) |
---
## 事件说明
| 事件名 | 参数 | 触发时机 |
| ----------- | ---- | -------------------- |
| `scrollEnd` | - | 滚动到文本末尾时触发 |
---
## Exposed Methods 暴露方法
| 方法名 | 参数 | 返回值 | 描述 |
| ---------- | --------------- | ------ | --------------------------- |
| `pause` | - | void | 暂停滚动 |
| `resume` | - | void | 继续滚动 |
| `setSpeed` | `speed: number` | void | 动态调整滚动速度(像素/秒) |
| `rescroll` | - | void | 立即重置到起始位置重新滚动 |
---
## 使用示例
### 基础滚动
```tsx
import { defineComponent } from 'vue';
import { ScrollText } from '@user/client-modules';
export const MyCom = defineComponent(() => {
const longText = '序幕\n'.repeat(100) + '——全剧终——';
return () => (
<ScrollText
text={longText}
speed={80} // 每秒滚动80像素
width={416} // 文本区域宽度
loc={[0, 0, 416, 416]} // 容器位置和尺寸
fillStyle="#E6E6FA" // 薰衣草色文字
/>
);
});
```
### 动态控制
```tsx
import { defineComponent, ref } from 'vue';
import { ScrollText } from '@user/client-modules';
export const MyCom = defineComponent(() => {
const longText = '序幕\n'.repeat(100) + '——全剧终——';
const scrollRef = ref<ScrollTextExpose>();
// 暂停/恢复控制
const toggleScroll = () => {
if (scrollRef.value?.isPaused) {
scrollRef.value.resume();
} else {
scrollRef.value?.pause();
}
};
// 速度控制
const accelerate = () => {
scrollRef.value?.setSpeed(200);
};
return () => (
<ScrollText
ref={scrollRef}
text={longText}
speed={100}
width={416}
loc={[0, 0, 416, 416]}
onScrollEnd={() => console.log('滚动结束')}
/>
);
});
```
### 复杂排版
```tsx
const staffText =
'\\c[32]====制作人员====\\c\n\n' +
'\\r[#FFD700]总监督\\r\t\t张三\n' +
'\\r[#00FF00]美术指导\\r\\t李四\n' +
'\\i[logo]\n' +
'特别感谢:某某公司';
<ScrollText
text={staffText}
speed={120}
width={720}
loc={[40, 40, 720, 560]}
pad={40} // 顶部留白
font={new Font('黑体', 24)}
lineHeight={8} // 行间距
interval={0} // 禁用打字机效果
/>;
```
---
## 注意事项
1. **容器尺寸**
实际可滚动区域计算公式:
```
可视高度 = loc[3](容器高度)
滚动距离 = 文本总高度 + pad首行前空白
```
2. **速度控制**
推荐速度范围 50-200 像素/秒
3. **组合动画**
可与容器变换配合实现复杂效果:
```tsx
<container rotation={-5} alpha={0.9}>
<ScrollText />
</container>
```

View File

@ -0,0 +1,77 @@
# Selection 组件 API 文档
本文档由 `DeepSeek R1` 模型生成并微调。
---
## 核心特性
- **动态高亮**:自动呼吸动画效果
- **双样式模式**:支持图片皮肤或纯色样式
- **精准定位**:像素级坐标控制
- **透明度动画**:可定制不透明度变化范围
---
## Props 属性说明
| 属性名 | 类型 | 默认值 | 描述 |
| ------------ | ------------------ | -------------- | --------------------------------- |
| `loc` | `ElementLocator` | **必填** | 光标定位 |
| `winskin` | `ImageIds` | - | 图片资源 ID优先级最高 |
| `color` | `CanvasStyle` | `#ddd` | 填充颜色(无皮肤时生效) |
| `border` | `CanvasStyle` | `gold` | 边框颜色(无皮肤时生效) |
| `alphaRange` | `[number, number]` | `[0.25, 0.55]` | 不透明度波动范围 [最小值, 最大值] |
---
## 使用示例
### 图片皮肤模式
```tsx
// 使用预加载的游戏皮肤资源
<Selection
loc={[120, 80, 160, 24]}
winskin="winskin.png"
alphaRange={[0.4, 1.0]}
/>
```
---
### 纯色模式
```tsx
// 自定义颜色方案
<Selection
loc={[20, 240, 200, 32]}
color="rgba(0,128,255,0.2)" // 填充颜色
border="#00BFFF" // 边框颜色
alphaRange={[0.5, 0.9]}
/>
```
---
## 注意事项
1. **样式优先级**
同时指定 `winskin` 和颜色参数时:
```tsx
// 以下配置将忽略 color/border 参数
<Selection winskin="winskin.png" color="red" border="blue" />
```
2. **动画速度**
呼吸动画固定为 2000ms/周期,暂不支持自定义时长
3. **点击反馈**
建议配合事件系统实现点击效果:
```tsx
<container onClick={handleClick}>
<Selection />
<text />
</container>
```

View File

@ -0,0 +1,184 @@
# TextContent 文本组件 API 文档
本文档由 `DeepSeek R1` 模型生成并微调。
---
## 核心特性
- **自动布局**:根据宽度自动换行
- **样式控制**:支持动态修改字体/颜色/描边
- **打字机效果**:逐字显示支持
- **动态高度**:自适应或固定高度模式
---
## Props 属性说明
| 属性名 | 类型 | 默认值 | 描述 |
| ----------------- | ------------- | ----------------- | ------------------------------ |
| `text` | `string` | - | 显示文本(支持转义字符) |
| `width` | `number` | 必填 | 文本区域宽度(像素) |
| `fill` | `boolean` | `true` | 是否对文字填充 |
| `stroke` | `boolean` | `false` | 是否对文字描边 |
| `font` | `Font` | 系统默认字体 | 字体配置对象 |
| `lineHeight` | `number` | `0` | 行间距(像素) |
| `interval` | `number` | `50` | 打字机字符间隔ms |
| `autoHeight` | `boolean` | `false` | 是否根据内容自动调整高度 |
| `fillStyle` | `CanvasStyle` | `#fff` | 文字填充颜色 |
| `strokeStyle` | `CanvasStyle` | `#000` | 文字描边颜色 |
| `strokeWidth` | `number` | `1` | 描边宽度 |
| `textAlign` | `TextAlign` | `TextAlign.Left` | 文字对齐方式 |
| `wordBreak` | `WordBreak` | `WordBreak.Space` | 文本分词原则,将会影响换行表现 |
| `breakChars` | `string` | - | 会被分词规则识别的分词字符 |
| `ignoreLineStart` | `string` | - | 不允许出现在行首的字符 |
| `ignoreLineEnd` | `string` | - | 不允许出现在行尾的字符 |
---
## 事件说明
| 事件名 | 参数 | 触发时机 |
| -------------- | ---------------- | ------------------ |
| `typeStart` | - | 开始逐字显示时 |
| `typeEnd` | - | 全部文字显示完成时 |
| `updateHeight` | `height: number` | 文本高度变化时 |
---
## Exposed Methods 暴露方法
| 方法名 | 参数 | 返回值 | 描述 |
| ----------- | ---- | -------- | ---------------------------- |
| `retype` | - | `void` | 从头开始重新打字 |
| `showAll` | - | `void` | 立刻结束打字机,显示所有文字 |
| `getHeight` | - | `number` | 获得当前文本的高度 |
---
## 使用示例
### 基础用法 - 对话文本
```tsx
import { defineComponent } from 'vue';
import { TextContent } from '@user/client-modules';
import { Font } from '@motajs/render';
export const MyCom = defineComponent(() => {
return () => (
<TextContent
text="这是基础文本内容,会自动换行排版"
width={200} // 最大宽度,达到这个宽度会自动换行
font={new Font('宋体', 18)}
fillStyle="#333333" // 黑色字体
onTypeEnd={() => console.log('显示完成')} // 打字机结束后执行
/>
);
});
```
### 自定义样式 + 描边效果
```tsx
import { defineComponent } from 'vue';
import { TextContent } from '@user/client-modules';
import { Font } from '@motajs/render';
export const MyCom = defineComponent(() => {
return () => (
<TextContent
text="\\r[#FFD700]金色描边文字"
width={300}
font={new Font('黑体', 24)}
stroke // 设为填充+描边格式,如果仅描边需要设置 fill={false}
strokeStyle="#8B4513" // 描边颜色
strokeWidth={2} // 描边宽度
lineHeight={8} // 行间距8 像素
interval={30} // 打字机间隔
/>
);
});
```
### 动态内容更新
```tsx
import { defineComponent, ref } from 'vue';
import { TextContent } from '@user/client-modules';
export const MyCom = defineComponent(() => {
const dynamicText = ref('初始内容');
setTimeout(() => {
dynamicText.value = '更新后的内容\\z[5]带暂停效果';
}, 2000);
return () => (
<TextContent
text={dynamicText.value}
width={500}
autoHeight
onUpdateHeight={h => console.log('当前高度:', h)} // 当高度发生变化时触发
/>
);
});
```
### 禁用动画效果
```tsx
import { defineComponent } from 'vue';
import { TextContent } from '@user/client-modules';
export const MyCom = defineComponent(() => {
return () => (
<TextContent
text="立即显示所有内容"
width={350}
interval={0} // 设置为0禁用逐字效果
showAll // 立即显示全部
fillStyle="rgba(0,128,0,0.8)"
/>
);
});
```
### 多语言复杂排版
```tsx
import { defineComponent } from 'vue';
import { TextContent } from '@user/client-modules';
export const MyCom = defineComponent(() => {
const complexText =
'\\g[Times New Roman]Hello\\g[宋体] 你好 \\i[flag]\\n' +
'\\r[#FF5733]Multi\\r[#3498db]-\\r[#2ECC71]Color\\r\\n' +
'\\c[18]Small\\c[24]Size\\c[30]Changes';
return () => (
<TextContent
text={complexText}
width={600}
interval={25}
onTypeStart={() => console.log('开始渲染复杂文本')}
/>
);
});
```
---
## 转义字符示例
```tsx
// 颜色/字体/图标综合使用
const styledText =
'\\r[#FF0000]警告!\\g[方正粗宋]\\c[24]' +
'\\i[warning_icon]发现异常\\z[10]\\n' +
'请立即处理\\r\\g\\c';
<TextContent text={styledText} width={450} interval={40} />;
```
转义字符具体用法参考 [TextContentParser](./TextContentParser.md#转义字符语法说明)

Some files were not shown because too many files have changed in this diff Show More