mirror of
https://github.com/unanmed/HumanBreak.git
synced 2025-06-28 05:07:59 +08:00
Merge 45c1d8c952
into 820dc5bf4c
This commit is contained in:
commit
8883eca285
2
.github/workflows/page.yml
vendored
2
.github/workflows/page.yml
vendored
@ -27,7 +27,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
npm i -g pnpm@7.27.0
|
npm i -g pnpm@7.27.0
|
||||||
pnpm i
|
pnpm i
|
||||||
pnpm build-gh
|
pnpm build
|
||||||
|
|
||||||
# 执行部署
|
# 执行部署
|
||||||
- name: 部署
|
- name: 部署
|
||||||
|
18
.gitignore
vendored
18
.gitignore
vendored
@ -35,4 +35,20 @@ index.cjs
|
|||||||
!public/swap/*.h5save
|
!public/swap/*.h5save
|
||||||
_bundle
|
_bundle
|
||||||
out
|
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
12
.madgerc
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"fileExtensions": [
|
||||||
|
"ts",
|
||||||
|
"tsx"
|
||||||
|
],
|
||||||
|
"tsConfig": "./tsconfig.json",
|
||||||
|
"detectiveOptions": {
|
||||||
|
"ts": {
|
||||||
|
"skipTypeImports": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -5,4 +5,12 @@ public/project/floors/*.js
|
|||||||
public/project/items.js
|
public/project/items.js
|
||||||
public/project/floors/*.js
|
public/project/floors/*.js
|
||||||
public/project/maps.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
13
.prettierrc
Normal 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"
|
||||||
|
}
|
8
.vscode/extensions.json
vendored
8
.vscode/extensions.json
vendored
@ -1,3 +1,9 @@
|
|||||||
{
|
{
|
||||||
"recommendations": ["Vue.volar"]
|
"recommendations": [
|
||||||
|
"dbaeumer.vscode-eslint",
|
||||||
|
"esbenp.prettier-vscode",
|
||||||
|
"vue.volar",
|
||||||
|
"slevesque.shader",
|
||||||
|
"tobermory.es6-string-html"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
178
LICENSE
178
LICENSE
@ -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
|
This version of the GNU Lesser General Public License incorporates
|
||||||
copies or substantial portions of the Software.
|
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
|
0. Additional Definitions.
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
General Public License.
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
"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
3
components.d.ts
vendored
@ -7,7 +7,9 @@ export {}
|
|||||||
|
|
||||||
declare module '@vue/runtime-core' {
|
declare module '@vue/runtime-core' {
|
||||||
export interface GlobalComponents {
|
export interface GlobalComponents {
|
||||||
|
AButton: typeof import('ant-design-vue/es')['Button']
|
||||||
ADivider: typeof import('ant-design-vue/es')['Divider']
|
ADivider: typeof import('ant-design-vue/es')['Divider']
|
||||||
|
AInput: typeof import('ant-design-vue/es')['Input']
|
||||||
AProgress: typeof import('ant-design-vue/es')['Progress']
|
AProgress: typeof import('ant-design-vue/es')['Progress']
|
||||||
ASelect: typeof import('ant-design-vue/es')['Select']
|
ASelect: typeof import('ant-design-vue/es')['Select']
|
||||||
ASelectOption: typeof import('ant-design-vue/es')['SelectOption']
|
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']
|
BoxAnimate: typeof import('./src/components/boxAnimate.vue')['default']
|
||||||
Colomn: typeof import('./src/components/colomn.vue')['default']
|
Colomn: typeof import('./src/components/colomn.vue')['default']
|
||||||
EnemyOne: typeof import('./src/components/enemyOne.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']
|
Scroll: typeof import('./src/components/scroll.vue')['default']
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
97
docs/.vitepress/api.ts
Normal file
97
docs/.vitepress/api.ts
Normal 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
119
docs/.vitepress/config.ts
Normal 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']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
7
docs/.vitepress/theme.css
Normal file
7
docs/.vitepress/theme.css
Normal 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
32
docs/api/index.md
Normal 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) 用户遗留数据层代码
|
3
docs/api/motajs-client-base/KeyCode.md
Normal file
3
docs/api/motajs-client-base/KeyCode.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# KeyCode
|
||||||
|
|
||||||
|
参考 `monaco-editor` 文档 [KeyCode](https://microsoft.github.io/monaco-editor/docs.html#enums/KeyCode.html)
|
5
docs/api/motajs-client-base/index.md
Normal file
5
docs/api/motajs-client-base/index.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# @motajs/client-base
|
||||||
|
|
||||||
|
目录:
|
||||||
|
|
||||||
|
- [KeyCode](./KeyCode.md)
|
13
docs/api/motajs-client/index.md
Normal file
13
docs/api/motajs-client/index.md
Normal 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');
|
||||||
|
```
|
212
docs/api/motajs-common/Logger.md
Normal file
212
docs/api/motajs-common/Logger.md
Normal 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();
|
||||||
|
```
|
24
docs/api/motajs-common/functions.md
Normal file
24
docs/api/motajs-common/functions.md
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# @motajs/common 函数
|
||||||
|
|
||||||
|
## `sleep`
|
||||||
|
|
||||||
|
```ts
|
||||||
|
function sleep(time: number): Promise<void>;
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 描述
|
||||||
|
|
||||||
|
创建一个等待指定时长的异步。
|
||||||
|
|
||||||
|
#### 参数
|
||||||
|
|
||||||
|
- `time`: 等待时长
|
||||||
|
|
||||||
|
#### 使用示例
|
||||||
|
|
||||||
|
```ts
|
||||||
|
async function myFunc() {
|
||||||
|
await sleep(1000);
|
||||||
|
// 这后面的内容会在 1 秒之后执行
|
||||||
|
}
|
||||||
|
```
|
11
docs/api/motajs-common/index.md
Normal file
11
docs/api/motajs-common/index.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# @motajs/common
|
||||||
|
|
||||||
|
目录:
|
||||||
|
|
||||||
|
- [函数](./functions.md)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
类目录:
|
||||||
|
|
||||||
|
- [Logger](./Logger.md)
|
3
docs/api/motajs-legacy-client/index.md
Normal file
3
docs/api/motajs-legacy-client/index.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# @motajs/legacy-client
|
||||||
|
|
||||||
|
目录:
|
120
docs/api/motajs-legacy-common/Patch.md
Normal file
120
docs/api/motajs-legacy-common/Patch.md
Normal 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;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
```
|
3
docs/api/motajs-legacy-common/index.md
Normal file
3
docs/api/motajs-legacy-common/index.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# @motajs/legacy-common
|
||||||
|
|
||||||
|
目录:
|
3
docs/api/motajs-legacy-system/index.md
Normal file
3
docs/api/motajs-legacy-system/index.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# @motajs/legacy-system
|
||||||
|
|
||||||
|
目录:
|
3
docs/api/motajs-legacy-ui/index.md
Normal file
3
docs/api/motajs-legacy-ui/index.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# @motajs/legacy-ui
|
||||||
|
|
||||||
|
目录:
|
121
docs/api/motajs-render-core/Container.md
Normal file
121
docs/api/motajs-render-core/Container.md
Normal 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); // 自动触发重新排序
|
||||||
|
```
|
71
docs/api/motajs-render-core/ContainerCustom.md
Normal file
71
docs/api/motajs-render-core/ContainerCustom.md
Normal 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);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
```
|
201
docs/api/motajs-render-core/Event.md
Normal file
201
docs/api/motajs-render-core/Event.md
Normal 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} />;
|
||||||
|
```
|
||||||
|
|
||||||
|
:::
|
151
docs/api/motajs-render-core/GL2.md
Normal file
151
docs/api/motajs-render-core/GL2.md
Normal 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 功能
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 总使用示例
|
||||||
|
|
||||||
|
暂时没有。
|
188
docs/api/motajs-render-core/GL2Program.md
Normal file
188
docs/api/motajs-render-core/GL2Program.md
Normal 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);
|
||||||
|
}
|
||||||
|
```
|
311
docs/api/motajs-render-core/MotaOffscreenCanvas2D.md
Normal file
311
docs/api/motajs-render-core/MotaOffscreenCanvas2D.md
Normal 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);
|
||||||
|
```
|
174
docs/api/motajs-render-core/MotaRenderer.md
Normal file
174
docs/api/motajs-render-core/MotaRenderer.md
Normal 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();
|
||||||
|
});
|
||||||
|
```
|
230
docs/api/motajs-render-core/RenderAdapter.md
Normal file
230
docs/api/motajs-render-core/RenderAdapter.md
Normal 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();
|
||||||
|
```
|
477
docs/api/motajs-render-core/RenderItem.md
Normal file
477
docs/api/motajs-render-core/RenderItem.md
Normal 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` 模型生成并微调。
|
||||||
|
|
||||||
|
---
|
12
docs/api/motajs-render-core/Shader.md
Normal file
12
docs/api/motajs-render-core/Shader.md
Normal 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)
|
11
docs/api/motajs-render-core/ShaderProgram.md
Normal file
11
docs/api/motajs-render-core/ShaderProgram.md
Normal 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)
|
121
docs/api/motajs-render-core/Sprite.md
Normal file
121
docs/api/motajs-render-core/Sprite.md
Normal 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);
|
||||||
|
```
|
332
docs/api/motajs-render-core/Transform.md
Normal file
332
docs/api/motajs-render-core/Transform.md
Normal 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);
|
||||||
|
```
|
119
docs/api/motajs-render-core/functions.md
Normal file
119
docs/api/motajs-render-core/functions.md
Normal 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 --> 矩阵变换
|
||||||
|
```
|
1
docs/api/motajs-render-core/index.md
Normal file
1
docs/api/motajs-render-core/index.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
# @motajs/render-core
|
369
docs/api/motajs-render-elements/BlockCacher.md
Normal file
369
docs/api/motajs-render-elements/BlockCacher.md
Normal 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();
|
||||||
|
```
|
386
docs/api/motajs-render-elements/Camera.md
Normal file
386
docs/api/motajs-render-elements/Camera.md
Normal 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; // 纵向缩放比
|
||||||
|
}
|
||||||
|
```
|
201
docs/api/motajs-render-elements/CameraAnimation.md
Normal file
201
docs/api/motajs-render-elements/CameraAnimation.md
Normal 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;
|
||||||
|
```
|
3
docs/api/motajs-render-elements/index.md
Normal file
3
docs/api/motajs-render-elements/index.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# @motajs/render-elements
|
||||||
|
|
||||||
|
目录:
|
186
docs/api/motajs-render-style/Font.md
Normal file
186
docs/api/motajs-render-style/Font.md
Normal 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
|
||||||
|
});
|
||||||
|
```
|
3
docs/api/motajs-render-style/index.md
Normal file
3
docs/api/motajs-render-style/index.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# @motajs/render-style
|
||||||
|
|
||||||
|
目录:
|
134
docs/api/motajs-render-vue/BaseProps.md
Normal file
134
docs/api/motajs-render-vue/BaseProps.md
Normal 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)
|
167
docs/api/motajs-render-vue/GraphicBaseProps.md
Normal file
167
docs/api/motajs-render-vue/GraphicBaseProps.md
Normal 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` 属性来启用缓存,避免频繁的复杂图形绘制。
|
149
docs/api/motajs-render-vue/functions.md
Normal file
149
docs/api/motajs-render-vue/functions.md
Normal 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 设计,不可用于其他框架环境
|
3
docs/api/motajs-render-vue/index.md
Normal file
3
docs/api/motajs-render-vue/index.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# @motajs/render-vue
|
||||||
|
|
||||||
|
目录:
|
139
docs/api/motajs-render-vue/标签 container.md
Normal file
139
docs/api/motajs-render-vue/标签 container.md
Normal 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)可能触发浏览器纹理限制
|
88
docs/api/motajs-render-vue/标签 custom-container.md
Normal file
88
docs/api/motajs-render-vue/标签 custom-container.md
Normal 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>;
|
||||||
|
```
|
202
docs/api/motajs-render-vue/标签 g-bezier.md
Normal file
202
docs/api/motajs-render-vue/标签 g-bezier.md
Normal 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} .../>
|
||||||
|
```
|
182
docs/api/motajs-render-vue/标签 g-circle.md
Normal file
182
docs/api/motajs-render-vue/标签 g-circle.md
Normal 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)
|
||||||
|
/>
|
||||||
|
```
|
175
docs/api/motajs-render-vue/标签 g-ellipse.md
Normal file
175
docs/api/motajs-render-vue/标签 g-ellipse.md
Normal 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
|
||||||
|
/>
|
||||||
|
```
|
125
docs/api/motajs-render-vue/标签 g-line.md
Normal file
125
docs/api/motajs-render-vue/标签 g-line.md
Normal 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>
|
||||||
|
```
|
173
docs/api/motajs-render-vue/标签 g-path.md
Normal file
173
docs/api/motajs-render-vue/标签 g-path.md
Normal 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(); // 关键闭合操作
|
||||||
|
```
|
119
docs/api/motajs-render-vue/标签 g-quad.md
Normal file
119
docs/api/motajs-render-vue/标签 g-quad.md
Normal 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} .../>
|
||||||
|
```
|
91
docs/api/motajs-render-vue/标签 g-rect.md
Normal file
91
docs/api/motajs-render-vue/标签 g-rect.md
Normal 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. 在描边层上填充浅紫色
|
||||||
|
**视觉效果**:描边被填充色覆盖一部分
|
167
docs/api/motajs-render-vue/标签 g-rectr.md
Normal file
167
docs/api/motajs-render-vue/标签 g-rectr.md
Normal 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%
|
||||||
|
/>
|
||||||
|
```
|
121
docs/api/motajs-render-vue/标签 icon.md
Normal file
121
docs/api/motajs-render-vue/标签 icon.md
Normal 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 开始播放 |
|
103
docs/api/motajs-render-vue/标签 image.md
Normal file
103
docs/api/motajs-render-vue/标签 image.md
Normal 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 等) |
|
148
docs/api/motajs-render-vue/标签 sprite.md
Normal file
148
docs/api/motajs-render-vue/标签 sprite.md
Normal 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` 中循环更新自身
|
160
docs/api/motajs-render-vue/标签 text.md
Normal file
160
docs/api/motajs-render-vue/标签 text.md
Normal 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` 等
|
117
docs/api/motajs-render-vue/标签 winskin.md
Normal file
117
docs/api/motajs-render-vue/标签 winskin.md
Normal 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>;
|
||||||
|
```
|
16
docs/api/motajs-render/index.md
Normal file
16
docs/api/motajs-render/index.md
Normal 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';
|
||||||
|
```
|
311
docs/api/motajs-system-action/Hotkey.md
Normal file
311
docs/api/motajs-system-action/Hotkey.md
Normal 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();
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
:::
|
221
docs/api/motajs-system-action/Keyboard.md
Normal file
221
docs/api/motajs-system-action/Keyboard.md
Normal 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');
|
||||||
|
```
|
3
docs/api/motajs-system-action/index.md
Normal file
3
docs/api/motajs-system-action/index.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# @motajs/system-action
|
||||||
|
|
||||||
|
目录:
|
97
docs/api/motajs-system-ui/GameUI.md
Normal file
97
docs/api/motajs-system-ui/GameUI.md
Normal 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);
|
||||||
|
```
|
284
docs/api/motajs-system-ui/UIController.md
Normal file
284
docs/api/motajs-system-ui/UIController.md
Normal 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);
|
||||||
|
```
|
121
docs/api/motajs-system-ui/UIInstance.md
Normal file
121
docs/api/motajs-system-ui/UIInstance.md
Normal 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();
|
||||||
|
```
|
3
docs/api/motajs-system-ui/index.md
Normal file
3
docs/api/motajs-system-ui/index.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# @motajs/system-ui
|
||||||
|
|
||||||
|
目录:
|
25
docs/api/motajs-system/index.md
Normal file
25
docs/api/motajs-system/index.md
Normal 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');
|
||||||
|
```
|
3
docs/api/motajs-types/index.md
Normal file
3
docs/api/motajs-types/index.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# @motajs/types
|
||||||
|
|
||||||
|
目录:
|
142
docs/api/user-client-modules/AudioDecoder.md
Normal file
142
docs/api/user-client-modules/AudioDecoder.md
Normal 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 音频。
|
207
docs/api/user-client-modules/AudioEffect.md
Normal file
207
docs/api/user-client-modules/AudioEffect.md
Normal 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
|
||||||
|
```
|
||||||
|
|
||||||
|
- 带反馈的延迟效果
|
||||||
|
- 自动渐弱回声处理
|
||||||
|
|
||||||
|
---
|
172
docs/api/user-client-modules/AudioPlayer.md
Normal file
172
docs/api/user-client-modules/AudioPlayer.md
Normal 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+ ⊙ 朝向用户
|
||||||
|
```
|
221
docs/api/user-client-modules/AudioRoute.md
Normal file
221
docs/api/user-client-modules/AudioRoute.md
Normal 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: 暂停播放
|
||||||
|
```
|
184
docs/api/user-client-modules/AudioSource.md
Normal file
184
docs/api/user-client-modules/AudioSource.md
Normal 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[实时音频节点]
|
||||||
|
```
|
||||||
|
|
||||||
|
- 支持渐进式加载
|
||||||
|
- 动态缓冲管理
|
||||||
|
- 适用于浏览器自身不支持的音频类型
|
||||||
|
|
||||||
|
### AudioElementSource(HTML 音频元素源)
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
graph LR
|
||||||
|
AudioTag[audio 元素] -->|音频流| Output[媒体元素源节点]
|
||||||
|
```
|
||||||
|
|
||||||
|
- 基于 HTML5 Audio 元素
|
||||||
|
- 支持跨域资源
|
||||||
|
- 自动处理音频格式兼容
|
||||||
|
|
||||||
|
### AudioBufferSource(静态音频缓冲源)
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
graph LR
|
||||||
|
File[音频文件] --> Decode[解码为 AudioBuffer]
|
||||||
|
Decode --> Output[缓冲源节点]
|
||||||
|
```
|
||||||
|
|
||||||
|
- 完整音频数据预加载
|
||||||
|
- 精确播放控制
|
||||||
|
- 支持内存音频播放
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 注意事项
|
||||||
|
|
||||||
|
1. **时间精度**
|
||||||
|
所有时间参数均以 `AudioContext.currentTime` 为基准,精度可达 0.01 秒
|
158
docs/api/user-client-modules/BgmController.md
Normal file
158
docs/api/user-client-modules/BgmController.md
Normal 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);
|
||||||
|
});
|
||||||
|
```
|
147
docs/api/user-client-modules/HeroKeyMover.md
Normal file
147
docs/api/user-client-modules/HeroKeyMover.md
Normal 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. **作用域隔离**:只有当前作用域匹配时才会响应按键事件
|
197
docs/api/user-client-modules/SoundPlayer.md
Normal file
197
docs/api/user-client-modules/SoundPlayer.md
Normal 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 个,可通过优先级系统管理
|
208
docs/api/user-client-modules/StreamLoader.md
Normal file
208
docs/api/user-client-modules/StreamLoader.md
Normal 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('视频解码错误');
|
||||||
|
```
|
157
docs/api/user-client-modules/TextContentParser.md
Normal file
157
docs/api/user-client-modules/TextContentParser.md
Normal 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
|
||||||
|
```
|
245
docs/api/user-client-modules/TextContentTyper.md
Normal file
245
docs/api/user-client-modules/TextContentTyper.md
Normal 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` 组件。如果必须使用的话,可以直接阅读源码来看一些实现细节。
|
166
docs/api/user-client-modules/TextboxStore.md
Normal file
166
docs/api/user-client-modules/TextboxStore.md
Normal 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());
|
||||||
|
```
|
147
docs/api/user-client-modules/TipStore.md
Normal file
147
docs/api/user-client-modules/TipStore.md
Normal 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); // 等待淡出动画结束
|
||||||
|
```
|
217
docs/api/user-client-modules/WeatherController.md
Normal file
217
docs/api/user-client-modules/WeatherController.md
Normal 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>;
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
:::
|
410
docs/api/user-client-modules/functions.md
Normal file
410
docs/api/user-client-modules/functions.md
Normal 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)
|
3
docs/api/user-client-modules/index.md
Normal file
3
docs/api/user-client-modules/index.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# @user/client-modules
|
||||||
|
|
||||||
|
目录:
|
37
docs/api/user-client-modules/图标组件.md
Normal file
37
docs/api/user-client-modules/图标组件.md
Normal 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>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
```
|
50
docs/api/user-client-modules/组件 Arrow.md
Normal file
50
docs/api/user-client-modules/组件 Arrow.md
Normal 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"
|
||||||
|
/>
|
||||||
|
```
|
78
docs/api/user-client-modules/组件 Background.md
Normal file
78
docs/api/user-client-modules/组件 Background.md
Normal 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 />;
|
||||||
|
```
|
159
docs/api/user-client-modules/组件 Choices.md
Normal file
159
docs/api/user-client-modules/组件 Choices.md
Normal 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)
|
124
docs/api/user-client-modules/组件 ConfirmBox.md
Normal file
124
docs/api/user-client-modules/组件 ConfirmBox.md
Normal 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)
|
192
docs/api/user-client-modules/组件 Page.md
Normal file
192
docs/api/user-client-modules/组件 Page.md
Normal 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]` 范围内
|
107
docs/api/user-client-modules/组件 Progress.md
Normal file
107
docs/api/user-client-modules/组件 Progress.md
Normal 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]} />
|
||||||
|
```
|
118
docs/api/user-client-modules/组件 Scroll.md
Normal file
118
docs/api/user-client-modules/组件 Scroll.md
Normal 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>
|
||||||
|
```
|
160
docs/api/user-client-modules/组件 ScrollText.md
Normal file
160
docs/api/user-client-modules/组件 ScrollText.md
Normal 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>
|
||||||
|
```
|
77
docs/api/user-client-modules/组件 Selection.md
Normal file
77
docs/api/user-client-modules/组件 Selection.md
Normal 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>
|
||||||
|
```
|
184
docs/api/user-client-modules/组件 TextContent.md
Normal file
184
docs/api/user-client-modules/组件 TextContent.md
Normal 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
Loading…
Reference in New Issue
Block a user