Compare commits
130 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
1c803d0965 | ||
|
0106643c1a | ||
|
2a2a4ce488 | ||
|
3214ef1cc4 | ||
|
78507c2b91 | ||
|
38045a1027 | ||
|
af71702840 | ||
|
461713baba | ||
|
0aa1bc102b | ||
|
8f04522278 | ||
|
02ac6e6deb | ||
|
2255232499 | ||
|
8b0ad14f73 | ||
11ee6c1531 | |||
ddec8b9f77 | |||
7dbd032eb8 | |||
7f4719525a | |||
b29036144b | |||
110a1bfa00 | |||
baa468200a | |||
4c0bf4fbf2 | |||
36f3f0257e | |||
73aebfa4d3 | |||
7f5aebf49c | |||
|
473225145d | ||
|
1d5221dffb | ||
|
d75e16db82 | ||
|
9a4a307efa | ||
|
294973738c | ||
|
dd9c5b528a | ||
|
b5f2a9c1df | ||
|
100ddafc75 | ||
|
ae2b97d0fa | ||
|
59bbe2a41f | ||
|
d8f1ff2442 | ||
|
e9be1725f0 | ||
|
b5ca647503 | ||
1046d773f9 | |||
09a66cfcd9 | |||
|
95de26aad2 | ||
|
b9a8682f7e | ||
|
25aa6ae382 | ||
|
eb3d46c037 | ||
|
9de8fbda46 | ||
|
98298af2b2 | ||
|
88a9302ca7 | ||
|
1ce4626d9a | ||
|
c18057649b | ||
|
f7347ebb44 | ||
|
5c8db8dd91 | ||
|
9e4658f2ff | ||
|
2e19528e2f | ||
|
830a393a21 | ||
|
a1ca04827a | ||
|
e3b2e50a45 | ||
|
6ba32ee900 | ||
|
d19e1c149f | ||
|
acbb24a1db | ||
|
f44ecb69b8 | ||
|
218b1b5922 | ||
|
c6c4fe29dd | ||
|
1db5125454 | ||
|
b91c31f713 | ||
78a28b3031 | |||
0f7eefe3d8 | |||
62a1babc29 | |||
6ec177342e | |||
4187eb2c4f | |||
|
1d8ed69cc1 | ||
0338431267 | |||
3fe8f895fa | |||
87f4276d7e | |||
6ac8af13eb | |||
6e86cac613 | |||
|
9e6e72cbf0 | ||
460a6237e3 | |||
|
4327e3c282 | ||
|
8550a458fc | ||
023c84c4cc | |||
22fc9f8d6b | |||
|
c152c29051 | ||
|
e301c68687 | ||
3e1bbc92bf | |||
cc737578ba | |||
1762d6e629 | |||
530c01faa5 | |||
c66f841526 | |||
4fb52cc103 | |||
|
e7a5746769 | ||
|
5d6b323f47 | ||
|
e5608273ac | ||
df9615fe48 | |||
7e9c9eb311 | |||
b327c6b4c4 | |||
7c32c51462 | |||
|
6dde86d63f | ||
|
04e387554e | ||
|
897ed67ba4 | ||
|
1e09b4c3c4 | ||
|
8af2d71795 | ||
|
495daf7fad | ||
defae8c01e | |||
|
75f2f2266c | ||
4e785acf07 | |||
d13ffcc041 | |||
643ec9bfaf | |||
7aff26f0d3 | |||
50d3196eea | |||
ef8a0ae988 | |||
|
9ef7db9925 | ||
50f465b24f | |||
4e8135b471 | |||
|
809876ea5d | ||
|
3cb91d10ad | ||
|
3a87487697 | ||
d7379d4406 | |||
|
6cb5d39e43 | ||
91eb4a1d08 | |||
0562fb08b2 | |||
e521b07d86 | |||
a1a9eac588 | |||
7fe73a8334 | |||
0a08789fbd | |||
827247494a | |||
|
cbc4bd23a8 | ||
|
d0d815df06 | ||
6899504fef | |||
7f70f6ea55 | |||
0a7e6144ba | |||
34c9255f43 |
@ -1,7 +0,0 @@
|
||||
/dist
|
||||
/src-capacitor
|
||||
/src-cordova
|
||||
/.quasar
|
||||
/node_modules
|
||||
.eslintrc.js
|
||||
/src-ssr
|
21
.eslintrc
Normal file
21
.eslintrc
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
"root": true,
|
||||
"env": {
|
||||
"browser": true,
|
||||
"es2021": true
|
||||
},
|
||||
"plugins": ["@typescript-eslint", "prettier"],
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/eslint-recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"prettier"
|
||||
],
|
||||
"parserOptions": {
|
||||
"ecmaVersion": "latest",
|
||||
"sourceType": "module"
|
||||
},
|
||||
"rules": {
|
||||
"prettier/prettier": "error"
|
||||
}
|
||||
}
|
89
.eslintrc.js
89
.eslintrc.js
@ -1,89 +0,0 @@
|
||||
module.exports = {
|
||||
// https://eslint.org/docs/user-guide/configuring#configuration-cascading-and-hierarchy
|
||||
// This option interrupts the configuration hierarchy at this file
|
||||
// Remove this if you have an higher level ESLint config file (it usually happens into a monorepos)
|
||||
root: true,
|
||||
|
||||
// https://eslint.vuejs.org/user-guide/#how-to-use-a-custom-parser
|
||||
// Must use parserOptions instead of "parser" to allow vue-eslint-parser to keep working
|
||||
// `parser: 'vue-eslint-parser'` is already included with any 'plugin:vue/**' config and should be omitted
|
||||
parserOptions: {
|
||||
parser: require.resolve('@typescript-eslint/parser'),
|
||||
extraFileExtensions: ['.vue'],
|
||||
},
|
||||
|
||||
env: {
|
||||
browser: true,
|
||||
es2021: true,
|
||||
node: true,
|
||||
'vue/setup-compiler-macros': true,
|
||||
},
|
||||
|
||||
// Rules order is important, please avoid shuffling them
|
||||
extends: [
|
||||
// Base ESLint recommended rules
|
||||
// 'eslint:recommended',
|
||||
|
||||
// https://github.com/typescript-eslint/typescript-eslint/tree/master/packages/eslint-plugin#usage
|
||||
// ESLint typescript rules
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
|
||||
// Uncomment any of the lines below to choose desired strictness,
|
||||
// but leave only one uncommented!
|
||||
// See https://eslint.vuejs.org/rules/#available-rules
|
||||
'plugin:vue/vue3-essential', // Priority A: Essential (Error Prevention)
|
||||
// 'plugin:vue/vue3-strongly-recommended', // Priority B: Strongly Recommended (Improving Readability)
|
||||
// 'plugin:vue/vue3-recommended', // Priority C: Recommended (Minimizing Arbitrary Choices and Cognitive Overhead)
|
||||
|
||||
// https://github.com/prettier/eslint-config-prettier#installation
|
||||
// usage with Prettier, provided by 'eslint-config-prettier'.
|
||||
'prettier',
|
||||
],
|
||||
|
||||
plugins: [
|
||||
// required to apply rules which need type information
|
||||
'@typescript-eslint',
|
||||
|
||||
// https://eslint.vuejs.org/user-guide/#why-doesn-t-it-work-on-vue-files
|
||||
// required to lint *.vue files
|
||||
'vue',
|
||||
|
||||
// https://github.com/typescript-eslint/typescript-eslint/issues/389#issuecomment-509292674
|
||||
// Prettier has not been included as plugin to avoid performance impact
|
||||
// add it as an extension for your IDE
|
||||
],
|
||||
|
||||
globals: {
|
||||
ga: 'readonly', // Google Analytics
|
||||
cordova: 'readonly',
|
||||
__statics: 'readonly',
|
||||
__QUASAR_SSR__: 'readonly',
|
||||
__QUASAR_SSR_SERVER__: 'readonly',
|
||||
__QUASAR_SSR_CLIENT__: 'readonly',
|
||||
__QUASAR_SSR_PWA__: 'readonly',
|
||||
process: 'readonly',
|
||||
Capacitor: 'readonly',
|
||||
chrome: 'readonly',
|
||||
},
|
||||
|
||||
// add your custom rules here
|
||||
rules: {
|
||||
'prefer-promise-reject-errors': 'off',
|
||||
|
||||
quotes: ['warn', 'single', { avoidEscape: true }],
|
||||
|
||||
// this rule, if on, would require explicit return type on the `render` function
|
||||
'@typescript-eslint/explicit-function-return-type': 'off',
|
||||
|
||||
// in plain CommonJS modules, you can't use `import foo = require('foo')` to pass this rule, so it has to be disabled
|
||||
'@typescript-eslint/no-var-requires': 'off',
|
||||
'@typescript-eslint/no-namespace': 'off',
|
||||
|
||||
// The core 'no-unused-vars' rules (in the eslint:recommended ruleset)
|
||||
// does not work with type definitions
|
||||
'no-unused-vars': 'off',
|
||||
|
||||
// allow debugger during development only
|
||||
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
|
||||
},
|
||||
};
|
15
.vscode/extensions.json
vendored
15
.vscode/extensions.json
vendored
@ -1,15 +0,0 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"dbaeumer.vscode-eslint",
|
||||
"esbenp.prettier-vscode",
|
||||
"editorconfig.editorconfig",
|
||||
"vue.volar",
|
||||
"wayou.vscode-todo-highlight"
|
||||
],
|
||||
"unwantedRecommendations": [
|
||||
"octref.vetur",
|
||||
"hookyqr.beautify",
|
||||
"dbaeumer.jshint",
|
||||
"ms-vscode.vscode-typescript-tslint-plugin"
|
||||
]
|
||||
}
|
16
.vscode/settings.json
vendored
16
.vscode/settings.json
vendored
@ -1,16 +0,0 @@
|
||||
{
|
||||
"editor.bracketPairColorization.enabled": true,
|
||||
"editor.guides.bracketPairs": true,
|
||||
"editor.formatOnSave": true,
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.codeActionsOnSave": [
|
||||
"source.fixAll.eslint"
|
||||
],
|
||||
"eslint.validate": [
|
||||
"javascript",
|
||||
"javascriptreact",
|
||||
"typescript",
|
||||
"vue"
|
||||
],
|
||||
"typescript.tsdk": "node_modules/typescript/lib"
|
||||
}
|
63
README.md
63
README.md
@ -3,19 +3,28 @@
|
||||
图形应用基础框架,基于 pixi.js([官网](https://pixijs.com/), [API Docs](https://pixijs.download/release/docs/index.html))
|
||||
viewport 使用的 github 开源的 pixi-viewport[pixi-viewport](https://github.com/davidfig/pixi-viewport)
|
||||
|
||||
# 发布版本说明
|
||||
测试好可以发布时执行yarn run build进行构建,然后再提交push后,在gitea.joylink.club中进行版本发布
|
||||
```
|
||||
yarn run build
|
||||
```
|
||||
|
||||
# 路线图
|
||||
|
||||
- 图形的位置、旋转属性使用 pixijs 的 transform 变换(完成)
|
||||
- 图形对象的拖拽使用原始的 transform(图形的变换使用原始的变换)(完成)
|
||||
- 图形交互抽象(完成)
|
||||
- 图形子元素变换处理和存储(完成)
|
||||
- 图形复制功能(完成)
|
||||
- 绘制应用图形外包围框及旋转缩放功能(完成)
|
||||
- 绘制增加吸附功能(移动到特定位置附近吸附)(完成)
|
||||
- ~~图形的位置、旋转属性使用 pixijs 的 transform 变换(完成)~~
|
||||
- ~~图形对象的拖拽使用原始的 transform(图形的变换使用原始的变换)(完成)~~
|
||||
- ~~图形交互抽象(完成)~~
|
||||
- ~~图形子元素变换处理和存储(完成)~~
|
||||
- ~~图形复制功能(完成)~~
|
||||
- ~~绘制应用图形外包围框及旋转缩放功能(完成)~~
|
||||
- ~~绘制增加吸附功能(移动到特定位置附近吸附)(完成)~~
|
||||
- 图形动画抽象
|
||||
- 添加公用动画逻辑(如按指定路径位移,按角度旋转、按比例缩放、透明度控制等)
|
||||
- 菜单事件及处理,功能:菜单更新、菜单项显隐控制、菜单执行前后事件回调
|
||||
- 打包
|
||||
- 分割
|
||||
- globalMixin相关的编译配置(当前需打包完后手动修改index.d.ts第一行)
|
||||
-
|
||||
- 添加拖拽轨迹限制功能
|
||||
- 添加图形对象"可编辑属性"定义功能
|
||||
|
||||
@ -33,43 +42,3 @@ viewport 使用的 github 开源的 pixi-viewport[pixi-viewport](https://github.
|
||||
> - "static":发出(emit)事件并进行命中测试。与 v7 中的 interactive=true 相同
|
||||
|
||||
> - "dynamic":发出(emit)事件并进行命中测试,但也会接收模拟的交互事件,以便在鼠标不移动时进行交互
|
||||
|
||||
## Install the dependencies
|
||||
|
||||
```bash
|
||||
yarn
|
||||
# or
|
||||
npm install
|
||||
```
|
||||
|
||||
### Start the app in development mode (hot-code reloading, error reporting, etc.)
|
||||
|
||||
```bash
|
||||
quasar dev
|
||||
```
|
||||
|
||||
### Lint the files
|
||||
|
||||
```bash
|
||||
yarn lint
|
||||
# or
|
||||
npm run lint
|
||||
```
|
||||
|
||||
### Format the files
|
||||
|
||||
```bash
|
||||
yarn format
|
||||
# or
|
||||
npm run format
|
||||
```
|
||||
|
||||
### Build the app for production
|
||||
|
||||
```bash
|
||||
quasar build
|
||||
```
|
||||
|
||||
### Customize the configuration
|
||||
|
||||
See [Configuring quasar.config.js](https://v2.quasar.dev/quasar-cli-vite/quasar-config-js).
|
||||
|
22
src/jlgraphic/global.d.ts → global.d.ts
vendored
22
src/jlgraphic/global.d.ts → global.d.ts
vendored
@ -1,14 +1,14 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
declare namespace GlobalMixins {
|
||||
type JlCanvasType = import('./app').JlCanvas;
|
||||
type CanvasProperties = import('./app').ICanvasProperties;
|
||||
type GraphicApp = import('./app').GraphicApp;
|
||||
type JlGraphicType = import('./core').JlGraphic;
|
||||
type GraphicData = import('./core').GraphicData;
|
||||
type GraphicState = import('./core').GraphicState;
|
||||
type GraphicTransform = import('./core').GraphicTransform;
|
||||
type GraphicTransformEvent = import('./plugins').GraphicTransformEvent;
|
||||
type BoundsGraphic = import('./plugins').BoundsGraphic;
|
||||
type JlCanvasType = import('@jl-graphic').IJlCanvas;
|
||||
type CanvasProperties = import('@jl-graphic').ICanvasProperties;
|
||||
type GraphicApp = import('@jl-graphic').IGraphicApp;
|
||||
type JlGraphicType = import('@jl-graphic').JlGraphic;
|
||||
type GraphicData = import('@jl-graphic').GraphicData;
|
||||
type GraphicState = import('@jl-graphic').GraphicState;
|
||||
type GraphicTransform = import('@jl-graphic').GraphicTransform;
|
||||
type GraphicTransformEvent = import('@jl-graphic').GraphicTransformEvent;
|
||||
type BoundsGraphic = import('@jl-graphic').BoundsGraphic;
|
||||
type IPointDataType = import('pixi.js').IPointData;
|
||||
type PointType = import('pixi.js').Point;
|
||||
type FederatedMouseEvent = import('pixi.js').FederatedMouseEvent;
|
||||
@ -95,8 +95,8 @@ declare namespace GlobalMixins {
|
||||
isGraphic(): boolean; // 是否业务图形对象
|
||||
getGraphic<G extends JlGraphicType>(): G | null; // 获取所属的图形对象
|
||||
isGraphicChild(): boolean; // 是否图形子元素
|
||||
onAddToCanvas(): void; // 添加到画布处理
|
||||
onRemoveFromCanvas(): void; //从画布移除处理
|
||||
onAddToCanvas(canvas: JlCanvasType): void; // 添加到画布处理
|
||||
onRemoveFromCanvas(canvas: JlCanvasType): void; //从画布移除处理
|
||||
isInCanvas(): boolean; // 是否添加到画布中
|
||||
getCanvas(): JlCanvasType; // 获取所在画布
|
||||
isCanvas(): boolean; // 是否画布对象
|
21
index.html
21
index.html
@ -1,21 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title><%= productName %></title>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<meta name="description" content="<%= productDescription %>">
|
||||
<meta name="format-detection" content="telephone=no">
|
||||
<meta name="msapplication-tap-highlight" content="no">
|
||||
<meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width<% if (ctx.mode.cordova || ctx.mode.capacitor) { %>, viewport-fit=cover<% } %>">
|
||||
|
||||
<link rel="icon" type="image/png" sizes="128x128" href="icons/favicon-128x128.png">
|
||||
<link rel="icon" type="image/png" sizes="96x96" href="icons/favicon-96x96.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="icons/favicon-32x32.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="icons/favicon-16x16.png">
|
||||
<link rel="icon" type="image/ico" href="favicon.ico">
|
||||
</head>
|
||||
<body>
|
||||
<!-- quasar:entry-point -->
|
||||
</body>
|
||||
</html>
|
42
lib/app/BasicOperation.d.ts
vendored
Normal file
42
lib/app/BasicOperation.d.ts
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
import { GraphicData, JlGraphic } from '../core';
|
||||
import { JlOperation } from '../operation';
|
||||
import { ICanvasProperties, IGraphicApp, IJlCanvas } from './JlGraphicApp';
|
||||
/**
|
||||
* 更新画布操作
|
||||
*/
|
||||
export declare class UpdateCanvasOperation extends JlOperation {
|
||||
obj: IJlCanvas;
|
||||
old: ICanvasProperties;
|
||||
data: ICanvasProperties;
|
||||
description: string;
|
||||
constructor(app: IGraphicApp, obj: IJlCanvas, old: ICanvasProperties, data: ICanvasProperties);
|
||||
undo(): JlGraphic[];
|
||||
redo(): JlGraphic[];
|
||||
}
|
||||
/**
|
||||
* 创建图形操作
|
||||
*/
|
||||
export declare class GraphicCreateOperation extends JlOperation {
|
||||
obj: JlGraphic[];
|
||||
description: string;
|
||||
constructor(app: IGraphicApp, obj: JlGraphic[]);
|
||||
undo(): JlGraphic[] | void;
|
||||
redo(): JlGraphic[];
|
||||
}
|
||||
/**
|
||||
* 删除图形操作
|
||||
*/
|
||||
export declare class GraphicDeleteOperation extends JlOperation {
|
||||
obj: JlGraphic[];
|
||||
constructor(app: IGraphicApp, obj: JlGraphic[]);
|
||||
undo(): JlGraphic[];
|
||||
redo(): void;
|
||||
}
|
||||
export declare class GraphicDataUpdateOperation extends JlOperation {
|
||||
obj: JlGraphic[];
|
||||
oldData: GraphicData[];
|
||||
newData: GraphicData[];
|
||||
constructor(app: IGraphicApp, obj: JlGraphic[], oldData: GraphicData[], newData: GraphicData[]);
|
||||
undo(): void | JlGraphic[];
|
||||
redo(): void | JlGraphic[];
|
||||
}
|
150
lib/app/JlDrawApp.d.ts
vendored
Normal file
150
lib/app/JlDrawApp.d.ts
vendored
Normal file
@ -0,0 +1,150 @@
|
||||
import { BitmapFont, BitmapText, Container, FederatedMouseEvent, Point } from 'pixi.js';
|
||||
import { GraphicData, GraphicTemplate, JlGraphic } from '../core/JlGraphic';
|
||||
import { AppInteractionPlugin, InteractionPlugin, KeyListener } from '../plugins';
|
||||
import { GraphicApp, GraphicAppOptions, ICanvasProperties, IGraphicApp, IJlCanvas } from './JlGraphicApp';
|
||||
/**
|
||||
* 图形绘制助手
|
||||
*/
|
||||
export declare abstract class GraphicDrawAssistant<GT extends GraphicTemplate, GD extends GraphicData> extends AppInteractionPlugin {
|
||||
readonly __GraphicDrawAssistant = true;
|
||||
app: IDrawApp;
|
||||
type: string;
|
||||
description: string;
|
||||
icon: string;
|
||||
container: Container;
|
||||
graphicTemplate: GT;
|
||||
escListener: KeyListener;
|
||||
onEsc(): void;
|
||||
constructor(graphicApp: IDrawApp, graphicTemplate: GT, icon: string, description: string);
|
||||
get canvas(): IJlCanvas;
|
||||
bind(): void;
|
||||
unbind(): void;
|
||||
onLeftDown(e: FederatedMouseEvent): void;
|
||||
onMouseMove(e: FederatedMouseEvent): void;
|
||||
onLeftUp(e: FederatedMouseEvent): void;
|
||||
onRightDown(e: FederatedMouseEvent): void;
|
||||
onRightUp(e: FederatedMouseEvent): void;
|
||||
onRightClick(e: FederatedMouseEvent): void;
|
||||
/**
|
||||
* 获取下一个id
|
||||
*/
|
||||
nextId(): number;
|
||||
clearCache(): void;
|
||||
/**
|
||||
* 重绘
|
||||
* @param cp 鼠标所在画布坐标
|
||||
*/
|
||||
abstract redraw(cp: Point): void;
|
||||
abstract prepareData(data: GD): boolean;
|
||||
toCanvasCoordinates(p: Point): Point;
|
||||
/**
|
||||
* 保存创建的图形对象
|
||||
*/
|
||||
storeGraphic(...graphics: JlGraphic[]): void;
|
||||
/**
|
||||
* 创建并添加到图形App
|
||||
*/
|
||||
createAndStore(finish: boolean): JlGraphic | null;
|
||||
/**
|
||||
* 绘制完成
|
||||
*/
|
||||
finish(...graphics: JlGraphic[]): void;
|
||||
}
|
||||
/**
|
||||
* 绘制助手类型
|
||||
*/
|
||||
export type DrawAssistant = GraphicDrawAssistant<GraphicTemplate, GraphicData>;
|
||||
/**
|
||||
* 绘制配置选项
|
||||
*/
|
||||
export type DrawAppOptions = GraphicAppOptions;
|
||||
/**
|
||||
* 绘制应用接口
|
||||
*/
|
||||
export interface IDrawApp extends IGraphicApp {
|
||||
/**
|
||||
* 是否正在绘制图形
|
||||
*/
|
||||
get drawing(): boolean;
|
||||
/**
|
||||
* 更新绘制中状态
|
||||
*/
|
||||
set drawing(value: boolean);
|
||||
/**
|
||||
* 设置配置选项
|
||||
* @param options
|
||||
*/
|
||||
setOptions(options: DrawAppOptions): void;
|
||||
/**
|
||||
* 获取绘制助手
|
||||
*/
|
||||
getDrawAssistant<DA extends DrawAssistant>(graphicType: string): DA;
|
||||
/**
|
||||
* 更新画布并记录
|
||||
* @param data
|
||||
*/
|
||||
updateCanvasAndRecord(data: ICanvasProperties): void;
|
||||
/**
|
||||
* 更新图形并记录
|
||||
* @param g
|
||||
* @param data
|
||||
*/
|
||||
updateGraphicAndRecord(g: JlGraphic, data: GraphicData): void;
|
||||
/**
|
||||
* 绑定form表单对象
|
||||
* @param form
|
||||
*/
|
||||
bindFormData(form: GraphicData): void;
|
||||
/**
|
||||
* 解绑form表单对象
|
||||
* @param form
|
||||
*/
|
||||
unbindFormData(form: GraphicData): void;
|
||||
}
|
||||
/**
|
||||
* 绘制应用
|
||||
*/
|
||||
export declare class JlDrawApp extends GraphicApp implements IDrawApp {
|
||||
font: BitmapFont;
|
||||
coordinates: BitmapText;
|
||||
scaleText: BitmapText;
|
||||
drawAssistants: DrawAssistant[];
|
||||
_drawing: boolean;
|
||||
private debouncedFormDataUpdator;
|
||||
get drawing(): boolean;
|
||||
set drawing(value: boolean);
|
||||
constructor(options: DrawAppOptions);
|
||||
setOptions(options: DrawAppOptions): void;
|
||||
registerInteractionPlugin(...plugins: InteractionPlugin[]): void;
|
||||
getDrawAssistant<DA extends DrawAssistant>(graphicType: string): DA;
|
||||
private appOperationRecord;
|
||||
/**
|
||||
* 绘制状态信息显示
|
||||
*/
|
||||
private appendDrawStatesDisplay;
|
||||
bindKeyboardOperation(): void;
|
||||
/**
|
||||
* 图形对象存储处理,默认添加图形交互
|
||||
* @param graphic
|
||||
*/
|
||||
beforeGraphicStore(graphic: JlGraphic): void;
|
||||
formData: GraphicData | undefined;
|
||||
/**
|
||||
* 绑定form表单对象
|
||||
* @param form
|
||||
*/
|
||||
bindFormData(form: GraphicData): void;
|
||||
/**
|
||||
* 移除form绑定
|
||||
* @param form
|
||||
*/
|
||||
unbindFormData(form: GraphicData): void;
|
||||
private formDataSyncListen;
|
||||
/**
|
||||
* 处理表单数据更新(使用debounce限流)
|
||||
*/
|
||||
private handleFormDataUpdate;
|
||||
private doFormDataUpdate;
|
||||
updateCanvasAndRecord(data: ICanvasProperties): void;
|
||||
updateGraphicAndRecord(g: JlGraphic, data: GraphicData): void;
|
||||
}
|
618
lib/app/JlGraphicApp.d.ts
vendored
Normal file
618
lib/app/JlGraphicApp.d.ts
vendored
Normal file
@ -0,0 +1,618 @@
|
||||
/// <reference types="node" />
|
||||
import EventEmitter from 'eventemitter3';
|
||||
import { Viewport } from 'pixi-viewport';
|
||||
import { Application, Container, DisplayObject, Graphics, Point } from 'pixi.js';
|
||||
import { GraphicQueryStore } from '../core/GraphicStore';
|
||||
import { GraphicData, GraphicState, GraphicTemplate, GraphicTransform, JlGraphic } from '../core/JlGraphic';
|
||||
import { AbsorbablePosition } from '../graphic';
|
||||
import { AppWsMsgBroker, GraphicQuery, ICreateOnNotFound, type AppStateSubscription, type MessageCliOption } from '../message';
|
||||
import { OperationRecord } from '../operation/JlOperation';
|
||||
import { AnimationManager, IMouseToolOptions } from '../plugins';
|
||||
import { GraphicCopyPlugin } from '../plugins/CopyPlugin';
|
||||
import { AppDragEvent, InteractionPlugin } from '../plugins/InteractionPlugin';
|
||||
import { JlGraphicAppKeyboardPlugin, KeyListener } from '../plugins/KeyboardPlugin';
|
||||
import { ContextMenu, ContextMenuPlugin } from '../ui/ContextMenu';
|
||||
import { MenuItemOptions } from '../ui/Menu';
|
||||
export declare const AppConsts: {
|
||||
viewportname: string;
|
||||
canvasname: string;
|
||||
AssistantAppendsName: string;
|
||||
assistantElementColor: string;
|
||||
};
|
||||
/**
|
||||
* 画布属性
|
||||
*/
|
||||
export interface ICanvasProperties {
|
||||
width: number;
|
||||
height: number;
|
||||
backgroundColor: string;
|
||||
viewportTransform: GraphicTransform;
|
||||
gridBackground?: IGridBackground;
|
||||
}
|
||||
export interface IGridBackground {
|
||||
hasGrid: boolean;
|
||||
lineColor: string;
|
||||
space: number;
|
||||
}
|
||||
export declare class CanvasData implements ICanvasProperties {
|
||||
width: number;
|
||||
height: number;
|
||||
backgroundColor: string;
|
||||
viewportTransform: GraphicTransform;
|
||||
gridBackground: IGridBackground | undefined;
|
||||
constructor(properties?: ICanvasProperties);
|
||||
copyFrom(properties: ICanvasProperties): boolean;
|
||||
clone(): CanvasData;
|
||||
}
|
||||
export interface IJlCanvas extends Container {
|
||||
/**
|
||||
* 获取画布属性
|
||||
*/
|
||||
get properties(): ICanvasProperties;
|
||||
/**
|
||||
* 获取所属场景
|
||||
*/
|
||||
get scene(): IGraphicScene;
|
||||
/**
|
||||
* 更新画布属性
|
||||
* @param properties
|
||||
*/
|
||||
update(properties: ICanvasProperties): void;
|
||||
/**
|
||||
* 添加辅助附加元素
|
||||
* @param appends
|
||||
*/
|
||||
addAssistantAppends(...appends: DisplayObject[]): void;
|
||||
/**
|
||||
* 移除辅助附加元素
|
||||
* @param appends
|
||||
*/
|
||||
removeAssistantAppends(...appends: DisplayObject[]): void;
|
||||
/**
|
||||
* 保存画布及视口缩放数据
|
||||
*/
|
||||
saveData(): ICanvasProperties;
|
||||
}
|
||||
export declare class JlCanvas extends Container implements IJlCanvas {
|
||||
__JlCanvas: boolean;
|
||||
type: string;
|
||||
scene: IGraphicScene;
|
||||
_properties: CanvasData;
|
||||
bg: Graphics;
|
||||
gridBackgroundLine: Container<DisplayObject>;
|
||||
nonInteractiveContainer: Container;
|
||||
assistantAppendContainer: Container;
|
||||
constructor(scene: IGraphicScene, properties?: CanvasData);
|
||||
/**
|
||||
* 图形重绘(数据/状态变化时触发)
|
||||
*/
|
||||
repaint(): void;
|
||||
get width(): number;
|
||||
get height(): number;
|
||||
get backgroundColor(): string;
|
||||
get gridBackground(): IGridBackground | undefined;
|
||||
doRepaint(): void;
|
||||
get properties(): CanvasData;
|
||||
saveData(): CanvasData;
|
||||
update(properties: ICanvasProperties): void;
|
||||
addChild<U extends DisplayObject[]>(...children: U): U[0];
|
||||
removeChild<U extends DisplayObject[]>(...children: U): U[0];
|
||||
/**
|
||||
* 添加无交互Child
|
||||
*/
|
||||
addNonInteractiveChild(...obj: DisplayObject[]): void;
|
||||
removeGraphic(...obj: DisplayObject[]): void;
|
||||
/**
|
||||
* 移除无交互Child
|
||||
*/
|
||||
removeNonInteractiveChild(...obj: DisplayObject[]): void;
|
||||
addAssistantAppends(...appends: DisplayObject[]): void;
|
||||
removeAssistantAppends(...appends: DisplayObject[]): void;
|
||||
/**
|
||||
* 暂停所有可交互对象
|
||||
*/
|
||||
pauseInteractiveChildren(): void;
|
||||
/**
|
||||
* 恢复所有可交互对象
|
||||
*/
|
||||
resumeInteractiveChildren(): void;
|
||||
}
|
||||
/**
|
||||
* 选中改变事件
|
||||
*/
|
||||
export declare class SelectedChangeEvent {
|
||||
graphic: JlGraphic;
|
||||
select: boolean;
|
||||
constructor(graphic: JlGraphic, select: boolean);
|
||||
}
|
||||
/**
|
||||
* 应用事件
|
||||
*/
|
||||
export interface GraphicAppEvents extends GlobalMixins.GraphicAppEvents {
|
||||
graphicstored: [graphic: JlGraphic];
|
||||
graphicdeleted: [graphic: JlGraphic];
|
||||
postdataloaded: [];
|
||||
loadfinish: [];
|
||||
'interaction-plugin-resume': [plugin: InteractionPlugin];
|
||||
'interaction-plugin-pause': [plugin: InteractionPlugin];
|
||||
'options-update': [options: GraphicAppOptions];
|
||||
graphicselectedchange: [graphic: JlGraphic, selected: boolean];
|
||||
graphicchildselectedchange: [child: DisplayObject, selected: boolean];
|
||||
graphicselected: [graphics: JlGraphic[]];
|
||||
'viewport-scaled': [vp: Viewport];
|
||||
drag_op_start: [event: AppDragEvent];
|
||||
drag_op_move: [event: AppDragEvent];
|
||||
drag_op_end: [event: AppDragEvent];
|
||||
'pre-menu-handle': [menu: MenuItemOptions];
|
||||
'post-menu-handle': [menu: MenuItemOptions];
|
||||
'websocket-connect-state-change': [connected: boolean];
|
||||
'websocket-error': [err: Error];
|
||||
destroy: [app: IGraphicApp];
|
||||
}
|
||||
/**
|
||||
* 图形数据存储
|
||||
*/
|
||||
export interface IGraphicStorage {
|
||||
/**
|
||||
* 画布属性
|
||||
*/
|
||||
canvasProperty?: ICanvasProperties;
|
||||
/**
|
||||
* 图形数据
|
||||
*/
|
||||
datas: GraphicData[];
|
||||
}
|
||||
/**
|
||||
* 图形App构造参数
|
||||
*/
|
||||
export interface IGraphicAppConfig {
|
||||
/**
|
||||
* 数据加载
|
||||
* @returns
|
||||
*/
|
||||
dataLoader?: () => Promise<IGraphicStorage>;
|
||||
/**
|
||||
* 最大保存的操作记录数,默认100,越大越占用内存资源
|
||||
*/
|
||||
maxOperationRecords?: number;
|
||||
/**
|
||||
* 拖拽触发移动门槛
|
||||
*/
|
||||
threshold?: number;
|
||||
/**
|
||||
* 通用鼠标工具选项
|
||||
*/
|
||||
mouseToolOptions?: IMouseToolOptions;
|
||||
/**
|
||||
* 可吸附位置列表
|
||||
*/
|
||||
absorbablePositions?: AbsorbablePosition[];
|
||||
/**
|
||||
* 超出屏幕显示范围是否剪裁,默认true
|
||||
*/
|
||||
cullable?: boolean;
|
||||
/**
|
||||
* 是否支持删除操作
|
||||
*/
|
||||
isSupportDeletion?: (g: JlGraphic) => boolean;
|
||||
/**
|
||||
* 辅助元素颜色,默认蓝色
|
||||
*/
|
||||
assistantElementColor?: string;
|
||||
}
|
||||
/**
|
||||
* 图形添加到容器选项
|
||||
*/
|
||||
export interface IInteractiveGraphicOptions {
|
||||
/**
|
||||
* 包含添加到可交互容器的图形类型,和Excludes同时只能存在一个
|
||||
*/
|
||||
interactiveGraphicTypeIncludes?: string[];
|
||||
/**
|
||||
* 不包含添加到可交互容器的图形类型,和Includes同时只能存在一个
|
||||
*/
|
||||
interactiveGraphicTypeExcludes?: string[];
|
||||
}
|
||||
export type GraphicAppOptions = IGraphicAppConfig & IInteractiveGraphicOptions;
|
||||
/**
|
||||
* 图形场景接口
|
||||
*/
|
||||
export interface IGraphicScene extends EventEmitter<GraphicAppEvents> {
|
||||
/**
|
||||
* 获取图形应用对象
|
||||
*/
|
||||
get app(): GraphicApp;
|
||||
/**
|
||||
* 获取pixijs应用对象
|
||||
*/
|
||||
get pixi(): Application;
|
||||
/**
|
||||
* 获取视口对象
|
||||
*/
|
||||
get viewport(): Viewport;
|
||||
/**
|
||||
* 获取画布对象
|
||||
*/
|
||||
get canvas(): IJlCanvas;
|
||||
/**
|
||||
* 获取dom
|
||||
*/
|
||||
get dom(): HTMLElement | undefined;
|
||||
/**
|
||||
* 获取图形查询仓库
|
||||
*/
|
||||
get queryStore(): GraphicQueryStore;
|
||||
/**
|
||||
* 获取选中的图形对象
|
||||
*/
|
||||
get selectedGraphics(): JlGraphic[];
|
||||
/**
|
||||
* 获取动画管理器
|
||||
*/
|
||||
get animationManager(): AnimationManager;
|
||||
/**
|
||||
* 获取配置选项
|
||||
*/
|
||||
get appOptions(): GraphicAppOptions;
|
||||
/**
|
||||
* 设置配置选项
|
||||
* @param options
|
||||
*/
|
||||
setOptions(options: GraphicAppOptions): void;
|
||||
/**
|
||||
* 注册菜单
|
||||
* @param menu
|
||||
*/
|
||||
registerMenu(menu: ContextMenu): void;
|
||||
/**
|
||||
* 将屏幕点转换为画布坐标
|
||||
* @param p 屏幕坐标
|
||||
*/
|
||||
toCanvasCoordinates(p: Point): Point;
|
||||
/**
|
||||
* 加载/重新加载数据(若已经加载过,则不会重新加载)
|
||||
*/
|
||||
reload(): Promise<void>;
|
||||
/**
|
||||
* 强制重新加载,无论是否已经加载过
|
||||
*/
|
||||
forceReload(): Promise<void>;
|
||||
/**
|
||||
* 绑定到dom
|
||||
* @param dom
|
||||
*/
|
||||
bindDom(dom: HTMLElement): void;
|
||||
/**
|
||||
* 从dom节点移除
|
||||
*/
|
||||
unbindDom(): void;
|
||||
/**
|
||||
* 注册图形模板
|
||||
* @param graphicTemplates
|
||||
*/
|
||||
registerGraphicTemplates(...graphicTemplates: GraphicTemplate[]): void;
|
||||
/**
|
||||
* 处理图形状态
|
||||
* @param graphicStates
|
||||
*/
|
||||
handleGraphicStates(graphicStates: GraphicState[], queryer?: GraphicQuery, createOnNotFound?: ICreateOnNotFound): void;
|
||||
/**
|
||||
* 根据类型获取图形模板
|
||||
* @param type
|
||||
*/
|
||||
getGraphicTemplatesByType<GT extends GraphicTemplate>(type: string): GT;
|
||||
/**
|
||||
* 添加图形
|
||||
* @param graphics
|
||||
*/
|
||||
addGraphics(...graphics: JlGraphic[]): void;
|
||||
/**
|
||||
* 删除图形
|
||||
* @param graphics
|
||||
*/
|
||||
deleteGraphics(...graphics: JlGraphic[]): JlGraphic[];
|
||||
/**
|
||||
* 检测并构建关系
|
||||
*/
|
||||
detectRelations(): void;
|
||||
/**
|
||||
* 注册交互插件
|
||||
* @param plugins
|
||||
*/
|
||||
registerInteractionPlugin(...plugins: InteractionPlugin[]): void;
|
||||
/**
|
||||
* 暂停交互插件
|
||||
*/
|
||||
pauseAppInteractionPlugins(): void;
|
||||
/**
|
||||
* 根据name获取交互插件
|
||||
* @param name
|
||||
*/
|
||||
interactionPlugin<P = InteractionPlugin>(name: string): P;
|
||||
/**
|
||||
* 更新选中图形对象
|
||||
* @param graphics
|
||||
*/
|
||||
updateSelected(...graphics: JlGraphic[]): void;
|
||||
/**
|
||||
* 选中所有图形
|
||||
*/
|
||||
selectAllGraphics(): void;
|
||||
/**
|
||||
* 使所选图形居中
|
||||
* @param group
|
||||
*/
|
||||
makeGraphicCenterShow(...group: JlGraphic[]): void;
|
||||
/**
|
||||
* 销毁
|
||||
*/
|
||||
destroy(): void;
|
||||
/**
|
||||
* 订阅websocket消息
|
||||
*/
|
||||
subscribe(sub: AppStateSubscription): void;
|
||||
/**
|
||||
* 取消websocket订阅
|
||||
*/
|
||||
unsubscribe(destination: string): void;
|
||||
/**
|
||||
* 发布websocket消息
|
||||
*/
|
||||
publishMessage(destination: string, message: Uint8Array): void;
|
||||
}
|
||||
declare abstract class GraphicSceneBase extends EventEmitter<GraphicAppEvents> implements IGraphicScene {
|
||||
private graphicStore;
|
||||
_options: GraphicAppOptions;
|
||||
pixi: Application;
|
||||
viewport: Viewport;
|
||||
canvas: JlCanvas;
|
||||
_loaded: boolean;
|
||||
_dom?: HTMLElement;
|
||||
_viewportResizer?: NodeJS.Timeout;
|
||||
graphicTemplateMap: Map<string, GraphicTemplate>;
|
||||
interactionPluginMap: Map<string, InteractionPlugin>;
|
||||
graphicCopyPlugin: GraphicCopyPlugin;
|
||||
animationManager: AnimationManager;
|
||||
menuPlugin: ContextMenuPlugin;
|
||||
private debounceEmitFunc;
|
||||
wsMsgBroker: AppWsMsgBroker;
|
||||
constructor(options: GraphicAppOptions);
|
||||
get appOptions(): GraphicAppOptions;
|
||||
abstract get app(): GraphicApp;
|
||||
get dom(): HTMLElement | undefined;
|
||||
get queryStore(): GraphicQueryStore;
|
||||
get selectedGraphics(): JlGraphic[];
|
||||
private load;
|
||||
/**
|
||||
* 重新加载数据
|
||||
*/
|
||||
reload(): Promise<void>;
|
||||
forceReload(): Promise<void>;
|
||||
/**
|
||||
* 更新选项
|
||||
* @param options
|
||||
*/
|
||||
setOptions(options: GraphicAppOptions): void;
|
||||
toCanvasCoordinates(p: Point): Point;
|
||||
/**
|
||||
* 注册菜单
|
||||
* @param menu
|
||||
*/
|
||||
registerMenu(menu: ContextMenu): void;
|
||||
/**
|
||||
* 注册图形对象模板
|
||||
* @param graphicTemplates
|
||||
*/
|
||||
registerGraphicTemplates(...graphicTemplates: GraphicTemplate[]): void;
|
||||
getGraphicTemplatesByType<GT extends GraphicTemplate>(type: string): GT;
|
||||
private updateViewport;
|
||||
/**
|
||||
* 暂停
|
||||
*/
|
||||
private pause;
|
||||
/**
|
||||
* 恢复
|
||||
*/
|
||||
private resume;
|
||||
bindDom(dom: HTMLElement): void;
|
||||
unbindDom(): void;
|
||||
/**
|
||||
* 加载图形,GraphicApp默认添加到无交互容器,DrawApp默认添加到交互容器,如需定制,提供选项配置
|
||||
* @param protos
|
||||
* @param options 添加到可交互/不可交互容器选项配置
|
||||
*/
|
||||
loadGraphic(protos: GraphicData[]): Promise<void>;
|
||||
/**
|
||||
* 添加图形前处理
|
||||
* @param graphic
|
||||
*/
|
||||
beforeGraphicStore(graphic: JlGraphic): void;
|
||||
/**
|
||||
* 执行添加图形对象
|
||||
* @param graphic
|
||||
*/
|
||||
private doAddGraphics;
|
||||
private doDeleteGraphics;
|
||||
/**
|
||||
* 存储图形
|
||||
* @param graphics 图形对象
|
||||
*/
|
||||
addGraphics(...graphics: JlGraphic[]): void;
|
||||
/**
|
||||
* 删除图形
|
||||
* @param graphics 图形对象
|
||||
*/
|
||||
deleteGraphics(...graphics: JlGraphic[]): JlGraphic[];
|
||||
/**
|
||||
* 检测并构建关系
|
||||
*/
|
||||
detectRelations(): void;
|
||||
/**
|
||||
* 全选
|
||||
*/
|
||||
selectAllGraphics(filter?: (g: JlGraphic) => boolean): void;
|
||||
/**
|
||||
* 更新选中
|
||||
*/
|
||||
updateSelected(...graphics: JlGraphic[]): void;
|
||||
private doEmitAppGraphicSelected;
|
||||
/**
|
||||
* 更新画布
|
||||
* @param param
|
||||
*/
|
||||
updateCanvas(param: ICanvasProperties): void;
|
||||
/**
|
||||
* 使图形居中显示(所有图形的外包围盒)
|
||||
*/
|
||||
makeGraphicCenterShow(...group: JlGraphic[]): void;
|
||||
/**
|
||||
* 注册交互插件,会替换旧的
|
||||
*/
|
||||
registerInteractionPlugin(...plugins: InteractionPlugin[]): void;
|
||||
/**
|
||||
* 根据名称获取交互插件
|
||||
* @param name
|
||||
* @returns
|
||||
*/
|
||||
interactionPlugin<P = InteractionPlugin>(name: string): P;
|
||||
/**
|
||||
* 停止应用交互插件
|
||||
*/
|
||||
pauseAppInteractionPlugins(): void;
|
||||
private doPauseInteractionPlugin;
|
||||
/**
|
||||
* 移除交互插件
|
||||
*/
|
||||
removeInteractionPlugin(plugin: InteractionPlugin): void;
|
||||
private checkWsMsgCli;
|
||||
/**
|
||||
* 订阅websocket消息
|
||||
*/
|
||||
subscribe(sub: AppStateSubscription): void;
|
||||
/**
|
||||
* 取消websocket订阅
|
||||
*/
|
||||
unsubscribe(destination: string): void;
|
||||
/**
|
||||
* 发布websocket消息
|
||||
*/
|
||||
publishMessage(destination: string, message: Uint8Array): void;
|
||||
/**
|
||||
* 处理图形状态
|
||||
* @param graphicStates
|
||||
*/
|
||||
handleGraphicStates(graphicStates: GraphicState[], queryer?: GraphicQuery, createOnNotFound?: ICreateOnNotFound): void;
|
||||
/**
|
||||
* 销毁
|
||||
*/
|
||||
destroy(): void;
|
||||
}
|
||||
/**
|
||||
* 图形应用接口
|
||||
*/
|
||||
export interface IGraphicApp extends IGraphicScene {
|
||||
get opRecord(): OperationRecord;
|
||||
/**
|
||||
* 实例化一个场景
|
||||
* @param code 场景标识
|
||||
* @returns
|
||||
*/
|
||||
initScene(code: string, options: GraphicAppOptions): IGraphicScene;
|
||||
/**
|
||||
* 获取场景
|
||||
* @param code
|
||||
* @returns
|
||||
*/
|
||||
getScene(code: string): IGraphicScene;
|
||||
/**
|
||||
* 切换场景
|
||||
* @param dom
|
||||
*/
|
||||
switchScene(code: string, dom: HTMLElement): void;
|
||||
/**
|
||||
* 移除指定code场景
|
||||
* @param code
|
||||
*/
|
||||
removeScene(code: string): void;
|
||||
/**
|
||||
* 添加图形并记录
|
||||
* @param graphics
|
||||
*/
|
||||
addGraphicAndRecord(...graphics: JlGraphic[]): void;
|
||||
/**
|
||||
* 删除图形并记录
|
||||
* @param graphics
|
||||
*/
|
||||
deleteGraphicAndRecord(...graphics: JlGraphic[]): void;
|
||||
/**
|
||||
* 启动websocket消息客户端
|
||||
*/
|
||||
enableWsMassaging(options: MessageCliOption): void;
|
||||
/**
|
||||
* 添加键盘监听器,如果是相同的按键,新注册的会覆盖旧的,当移除新的时,旧的自动生效
|
||||
* @param keyListeners
|
||||
*/
|
||||
addKeyboardListener(...keyListeners: KeyListener[]): void;
|
||||
/**
|
||||
* 移除键盘监听器
|
||||
* @param keyListeners
|
||||
*/
|
||||
removeKeyboardListener(...keyListeners: KeyListener[]): void;
|
||||
}
|
||||
/**
|
||||
* 图形app基类
|
||||
*/
|
||||
export declare class GraphicApp extends GraphicSceneBase implements IGraphicApp {
|
||||
/**
|
||||
* 场景列表
|
||||
*/
|
||||
scenes: Map<string, JlScene>;
|
||||
opRecord: OperationRecord;
|
||||
keyboardPlugin: JlGraphicAppKeyboardPlugin;
|
||||
constructor(options: GraphicAppOptions);
|
||||
get app(): GraphicApp;
|
||||
setOptions(options: GraphicAppOptions): void;
|
||||
addGraphicAndRecord(...graphics: JlGraphic[]): void;
|
||||
deleteGraphicAndRecord(...graphics: JlGraphic[]): void;
|
||||
/**
|
||||
* 实例化一个场景
|
||||
* @param code 场景标识
|
||||
* @returns
|
||||
*/
|
||||
initScene(code: string, options: GraphicAppOptions): IGraphicScene;
|
||||
/**
|
||||
* 获取场景
|
||||
* @param code
|
||||
* @returns
|
||||
*/
|
||||
getScene(code: string): IGraphicScene;
|
||||
switchScene(code: string, dom: HTMLElement): void;
|
||||
removeScene(code: string): void;
|
||||
/**
|
||||
* 启动websocket消息客户端
|
||||
*/
|
||||
enableWsMassaging(options: MessageCliOption): void;
|
||||
/**
|
||||
* 添加键盘监听器,如果是相同的按键,新注册的会覆盖旧的,当移除新的时,旧的自动生效
|
||||
* @param keyListeners
|
||||
*/
|
||||
addKeyboardListener(...keyListeners: KeyListener[]): void;
|
||||
/**
|
||||
* 移除键盘监听器
|
||||
* @param keyListeners
|
||||
*/
|
||||
removeKeyboardListener(...keyListeners: KeyListener[]): void;
|
||||
/**
|
||||
* 销毁
|
||||
*/
|
||||
destroy(): void;
|
||||
}
|
||||
/**
|
||||
* 场景
|
||||
*/
|
||||
export default class JlScene extends GraphicSceneBase {
|
||||
code: string;
|
||||
app: GraphicApp;
|
||||
constructor(app: GraphicApp, code: string, options: GraphicAppOptions);
|
||||
}
|
||||
export {};
|
17
lib/app/index.d.ts
vendored
Normal file
17
lib/app/index.d.ts
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
import { DrawAppOptions, DrawAssistant, GraphicDrawAssistant, IDrawApp } from './JlDrawApp';
|
||||
import { AppConsts, GraphicAppOptions, ICanvasProperties, IGraphicApp, IGraphicScene, IGraphicStorage, IJlCanvas, IGridBackground } from './JlGraphicApp';
|
||||
import { GraphicDataUpdateOperation } from './BasicOperation';
|
||||
/**
|
||||
* 实例化图形app
|
||||
* @param options
|
||||
* @returns
|
||||
*/
|
||||
export declare function newGraphicApp(options: GraphicAppOptions): IGraphicApp;
|
||||
/**
|
||||
* 实例化绘图app
|
||||
* @param options
|
||||
* @returns
|
||||
*/
|
||||
export declare function newDrawApp(options: DrawAppOptions): IDrawApp;
|
||||
export { AppConsts, GraphicDrawAssistant, GraphicDataUpdateOperation };
|
||||
export type { DrawAssistant, ICanvasProperties, IDrawApp, IGraphicApp, IGraphicScene, IGraphicStorage, IJlCanvas, IGridBackground };
|
82
lib/core/GraphicRelation.d.ts
vendored
Normal file
82
lib/core/GraphicRelation.d.ts
vendored
Normal file
@ -0,0 +1,82 @@
|
||||
import { JlGraphic } from './JlGraphic';
|
||||
/**
|
||||
* 图形关系数据
|
||||
*/
|
||||
export declare class GraphicRelationParam {
|
||||
g: JlGraphic;
|
||||
param: any;
|
||||
constructor(g: JlGraphic, param?: any);
|
||||
isTheGraphic(g: JlGraphic): boolean;
|
||||
getGraphic<G extends JlGraphic>(): G;
|
||||
getParam<P>(): P;
|
||||
equals(other: GraphicRelationParam): boolean;
|
||||
}
|
||||
/**
|
||||
* 图形关系
|
||||
*/
|
||||
export declare class GraphicRelation {
|
||||
rp1: GraphicRelationParam;
|
||||
rp2: GraphicRelationParam;
|
||||
constructor(rp1: GraphicRelationParam, rp2: GraphicRelationParam);
|
||||
contains(g: JlGraphic): boolean;
|
||||
/**
|
||||
* 获取给定图形的关系参数
|
||||
* @param g
|
||||
* @returns
|
||||
*/
|
||||
getRelationParam(g: JlGraphic): GraphicRelationParam;
|
||||
/**
|
||||
* 获取关联的另一个图形的关系参数
|
||||
* @param g
|
||||
* @returns
|
||||
*/
|
||||
getOtherRelationParam(g: JlGraphic): GraphicRelationParam;
|
||||
/**
|
||||
* 获取关联的另一个图形对象
|
||||
* @param g
|
||||
* @returns graphic
|
||||
*/
|
||||
getOtherGraphic<G extends JlGraphic>(g: JlGraphic): G;
|
||||
equals(orp1: GraphicRelationParam, orp2: GraphicRelationParam): boolean;
|
||||
isEqualOther(other: GraphicRelation): boolean;
|
||||
}
|
||||
/**
|
||||
* 图形关系管理
|
||||
*/
|
||||
export declare class RelationManage {
|
||||
relations: GraphicRelation[];
|
||||
isContainsRelation(rp1: GraphicRelationParam, rp2: GraphicRelationParam): boolean;
|
||||
addRelation(rp1: GraphicRelationParam | JlGraphic, rp2: GraphicRelationParam | JlGraphic): void;
|
||||
/**
|
||||
* 获取图形的所有关系
|
||||
* @param g
|
||||
* @returns
|
||||
*/
|
||||
getRelationsOfGraphic(g: JlGraphic): GraphicRelation[];
|
||||
/**
|
||||
* 获取指定图形的指定关系图形类型的所有关系
|
||||
* @param g 指定图形
|
||||
* @param type 关联图形的类型
|
||||
* @returns
|
||||
*/
|
||||
getRelationsOfGraphicAndOtherType(g: JlGraphic, type: string): GraphicRelation[];
|
||||
/**
|
||||
* 删除关系
|
||||
* @param relation
|
||||
*/
|
||||
private deleteRelation;
|
||||
/**
|
||||
* 删除指定图形的所有关系
|
||||
* @param g
|
||||
*/
|
||||
deleteRelationOfGraphic(g: JlGraphic): void;
|
||||
/**
|
||||
* 删除指定图形的所有关系
|
||||
* @param g
|
||||
*/
|
||||
deleteRelationOfGraphicAndOtherType(g: JlGraphic, type: string): void;
|
||||
/**
|
||||
* 清空
|
||||
*/
|
||||
clear(): void;
|
||||
}
|
92
lib/core/GraphicStore.d.ts
vendored
Normal file
92
lib/core/GraphicStore.d.ts
vendored
Normal file
@ -0,0 +1,92 @@
|
||||
import { RelationManage } from './GraphicRelation';
|
||||
import { JlGraphic } from './JlGraphic';
|
||||
export interface GraphicQueryStore {
|
||||
/**
|
||||
* 获取所有图形对象
|
||||
*/
|
||||
getAllGraphics(): JlGraphic[];
|
||||
/**
|
||||
* 根据id获取图形
|
||||
*/
|
||||
queryById<T extends JlGraphic>(id: number | string): T;
|
||||
/**
|
||||
* 根据id模糊查询图形
|
||||
* @param id
|
||||
*/
|
||||
queryByIdAmbiguous(id: number | string): JlGraphic[];
|
||||
/**
|
||||
* 根据类型获取图形列表
|
||||
*/
|
||||
queryByType<T extends JlGraphic>(type: string): T[];
|
||||
/**
|
||||
* 根据code查询
|
||||
* @param code
|
||||
*/
|
||||
queryByCode(code: string): JlGraphic[] | undefined;
|
||||
/**
|
||||
* 根据code模糊查询图形
|
||||
* @param code
|
||||
* @param type
|
||||
*/
|
||||
queryByCodeAmbiguous(code: string): JlGraphic[];
|
||||
/**
|
||||
* 根据id或code查询图形
|
||||
* @param v
|
||||
*/
|
||||
queryByIdOrCode(v: string | number): JlGraphic[];
|
||||
/**
|
||||
* 根据id或code及类型查询图形
|
||||
* @param v
|
||||
* @param type
|
||||
*/
|
||||
queryByIdOrCodeAndType(v: string | number, type: string): JlGraphic[];
|
||||
/**
|
||||
* 根据code和类型获取图形
|
||||
* @param code
|
||||
* @param type
|
||||
*/
|
||||
queryByCodeAndType<T extends JlGraphic>(code: string, type: string): T | undefined;
|
||||
/**
|
||||
* 根据code和类型模糊查询图形
|
||||
* @param code
|
||||
* @param type
|
||||
*/
|
||||
queryByCodeAndTypeAmbiguous<T extends JlGraphic>(code: string, type: string): T[];
|
||||
checkIdExist(v: number): boolean;
|
||||
}
|
||||
/**
|
||||
* 图形存储
|
||||
*/
|
||||
export declare class GraphicStore implements GraphicQueryStore {
|
||||
store: Map<number, JlGraphic>;
|
||||
relationManage: RelationManage;
|
||||
constructor();
|
||||
/**
|
||||
* 获取所有图形对象
|
||||
*/
|
||||
getAllGraphics(): JlGraphic[];
|
||||
queryById<T extends JlGraphic>(id: number | string): T;
|
||||
queryByIdAmbiguous(id: number | string): JlGraphic[];
|
||||
queryByType<T extends JlGraphic>(type: string): T[];
|
||||
queryByCode(code: string): JlGraphic[] | undefined;
|
||||
queryByCodeAmbiguous(code: string): JlGraphic[];
|
||||
queryByIdOrCode(s: string | number): JlGraphic[];
|
||||
queryByIdOrCodeAndType(s: string | number, type: string): JlGraphic[];
|
||||
queryByCodeAndType<T extends JlGraphic>(code: string, type: string): T | undefined;
|
||||
queryByCodeAndTypeAmbiguous<T extends JlGraphic>(code: string, type: string): T[];
|
||||
/**
|
||||
* 存储图形对象
|
||||
* @param graphics 要存储的图形
|
||||
*/
|
||||
storeGraphics(graphic: JlGraphic): boolean;
|
||||
/**
|
||||
* 删除图形
|
||||
* @param graph 要删除的图形
|
||||
*/
|
||||
deleteGraphics(graphic: JlGraphic): JlGraphic | undefined;
|
||||
/**
|
||||
* 清空
|
||||
*/
|
||||
clear(): void;
|
||||
checkIdExist(id: number): boolean;
|
||||
}
|
12
lib/core/IdGenerator.d.ts
vendored
Normal file
12
lib/core/IdGenerator.d.ts
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
/**
|
||||
* ID生成器
|
||||
*/
|
||||
export declare class IdGenerator {
|
||||
serial: number;
|
||||
type: string;
|
||||
constructor(type: string);
|
||||
next(): number;
|
||||
getType(): string;
|
||||
initSerial(serial: number): void;
|
||||
}
|
||||
export declare const GraphicIdGenerator: IdGenerator;
|
284
lib/core/JlGraphic.d.ts
vendored
Normal file
284
lib/core/JlGraphic.d.ts
vendored
Normal file
@ -0,0 +1,284 @@
|
||||
import { Container, DisplayObject, IPointData, Rectangle } from 'pixi.js';
|
||||
import { GraphicRelation, RelationManage } from './GraphicRelation';
|
||||
import { GraphicQueryStore } from './GraphicStore';
|
||||
export interface IGraphicTransform {
|
||||
position: IPointData;
|
||||
scale: IPointData;
|
||||
rotation: number;
|
||||
skew: IPointData;
|
||||
}
|
||||
/**
|
||||
* 图形变换数据
|
||||
*/
|
||||
export declare class GraphicTransform {
|
||||
position: IPointData;
|
||||
scale: IPointData;
|
||||
rotation: number;
|
||||
skew: IPointData;
|
||||
constructor(position: IPointData, scale: IPointData, rotation: number, skew: IPointData);
|
||||
static default(): GraphicTransform;
|
||||
static fromObject(obj: DisplayObject): GraphicTransform;
|
||||
static from(transform: IGraphicTransform | undefined): GraphicTransform;
|
||||
}
|
||||
export interface IChildTransform {
|
||||
name: string;
|
||||
transform: IGraphicTransform;
|
||||
}
|
||||
/**
|
||||
* 图形子元素变换
|
||||
*/
|
||||
export declare class ChildTransform {
|
||||
name: string;
|
||||
transform: GraphicTransform;
|
||||
constructor(name: string, transform: GraphicTransform);
|
||||
static fromChild(child: DisplayObject): ChildTransform;
|
||||
static from(ct: IChildTransform): ChildTransform;
|
||||
}
|
||||
/**
|
||||
* 图形数据
|
||||
*/
|
||||
export interface GraphicData {
|
||||
get id(): number;
|
||||
set id(v: number);
|
||||
get graphicType(): string;
|
||||
set graphicType(v: string);
|
||||
get transform(): GraphicTransform;
|
||||
set transform(v: GraphicTransform);
|
||||
get childTransforms(): ChildTransform[] | undefined;
|
||||
set childTransforms(v: ChildTransform[] | undefined);
|
||||
/**
|
||||
* 克隆消息
|
||||
*/
|
||||
clone(): GraphicData;
|
||||
/**
|
||||
* 从给定数据拷贝
|
||||
* @param data
|
||||
*/
|
||||
copyFrom(data: GraphicData): void;
|
||||
/**
|
||||
* 是否相等
|
||||
* @param other
|
||||
*/
|
||||
eq(other: GraphicData): boolean;
|
||||
}
|
||||
/**
|
||||
* 图形状态
|
||||
*/
|
||||
export interface GraphicState {
|
||||
get code(): string;
|
||||
get graphicType(): string;
|
||||
remove?: boolean;
|
||||
/**
|
||||
* 克隆消息
|
||||
*/
|
||||
clone(): GraphicState;
|
||||
/**
|
||||
* 从给定数据拷贝
|
||||
* @param data
|
||||
*/
|
||||
copyFrom(data: GraphicState): void;
|
||||
/**
|
||||
* 是否相等
|
||||
* @param data
|
||||
*/
|
||||
eq(data: GraphicState): boolean;
|
||||
}
|
||||
export interface GraphicAnimationOptions {
|
||||
name: string;
|
||||
run?: (dt: number) => void;
|
||||
}
|
||||
export declare class GraphicAnimation {
|
||||
options: GraphicAnimationOptions;
|
||||
_running: boolean;
|
||||
/**
|
||||
* 倍速
|
||||
*/
|
||||
_xSpeed: number;
|
||||
constructor(options: GraphicAnimationOptions);
|
||||
static init(options: GraphicAnimationOptions): GraphicAnimation;
|
||||
pause(): GraphicAnimation;
|
||||
resume(): GraphicAnimation;
|
||||
get name(): string;
|
||||
get running(): boolean;
|
||||
get xSpeed(): number;
|
||||
set xSpeed(v: number);
|
||||
run(dt: number): GraphicAnimation;
|
||||
}
|
||||
/**
|
||||
* 图形对象基类
|
||||
*/
|
||||
export declare abstract class JlGraphic extends Container {
|
||||
readonly __JlGraphic: true;
|
||||
readonly type: string;
|
||||
private _id;
|
||||
private _code;
|
||||
_datas?: GraphicData;
|
||||
_states?: GraphicState;
|
||||
private _relationManage?;
|
||||
private _queryStore?;
|
||||
constructor(type: string);
|
||||
/**
|
||||
* 添加图形动画,只有在画布上才能添加
|
||||
* @param animation
|
||||
*/
|
||||
addAnimation(animation: GraphicAnimation): void;
|
||||
removeAnimation(name: string): void;
|
||||
animation(name: string): GraphicAnimation | undefined;
|
||||
removeAllAnimation(): void;
|
||||
/**
|
||||
* 更新选中状态
|
||||
* @param selected
|
||||
* @returns 是否更新
|
||||
*/
|
||||
updateSelected(selected: boolean): boolean;
|
||||
invertSelected(): void;
|
||||
fireSelected(): void;
|
||||
hasSelectedChilds(): boolean;
|
||||
setChildSelected(child: DisplayObject): boolean;
|
||||
invertChildSelected(child: DisplayObject): boolean;
|
||||
removeAllChildSelected(): void;
|
||||
fireChildSelected(child: DisplayObject): void;
|
||||
exitChildEdit(): void;
|
||||
/**
|
||||
* 是否此对象id/code
|
||||
*/
|
||||
isIdOrCode(s: string | number): boolean;
|
||||
/**
|
||||
* 获取图形id,如果图形数据对象存在,则返回图形数据对象id
|
||||
*/
|
||||
get id(): number;
|
||||
/**
|
||||
* 设置图形id,如果图形数据存在,则同时设置图形数据id
|
||||
*/
|
||||
set id(v: number);
|
||||
/**
|
||||
* 获取图形业务code,如果业务code在图形数据或图形状态中,则需要重写此方法
|
||||
*/
|
||||
get code(): string;
|
||||
/**
|
||||
* 设置图形业务code,如果业务code在图形数据或图形状态中,则需要重写此方法
|
||||
*/
|
||||
set code(v: string);
|
||||
getDatas<D extends GraphicData>(): D;
|
||||
getStates<S extends GraphicState>(): S;
|
||||
get queryStore(): GraphicQueryStore;
|
||||
set queryStore(v: GraphicQueryStore);
|
||||
get relationManage(): RelationManage;
|
||||
set relationManage(v: RelationManage);
|
||||
/**
|
||||
* 构建图形关系
|
||||
* @param g
|
||||
*/
|
||||
buildRelation(): void;
|
||||
/**
|
||||
* 从数据加载恢复图形关系
|
||||
*/
|
||||
loadRelations(): void;
|
||||
/**
|
||||
* 获取当前图形的所有图形关系
|
||||
* @returns
|
||||
*/
|
||||
getAllRelations(): GraphicRelation[];
|
||||
/**
|
||||
* 获取当前图形的所有指定类型图形关系
|
||||
* @param type
|
||||
* @returns
|
||||
*/
|
||||
queryRelationByType(type: string): GraphicRelation[];
|
||||
/**
|
||||
* 删除当前图形关联的指定类型的关系
|
||||
* @param type
|
||||
*/
|
||||
deleteRelationByType(type: string): void;
|
||||
/**
|
||||
* 构建并保存关系数据到datas中
|
||||
*/
|
||||
saveRelations(): void;
|
||||
/**
|
||||
* 保存数据,复制,非原始数据
|
||||
* @returns
|
||||
*/
|
||||
saveData<D extends GraphicData>(): D;
|
||||
/**
|
||||
* 构建子元素变换列表
|
||||
* @returns
|
||||
*/
|
||||
private buildChildTransforms;
|
||||
/**
|
||||
* 加载数据
|
||||
* @param data
|
||||
*/
|
||||
loadData(data: GraphicData): void;
|
||||
private loadTransformFrom;
|
||||
/**
|
||||
* 更新图形数据
|
||||
* @param data
|
||||
* @returns
|
||||
*/
|
||||
updateData(data: GraphicData): boolean;
|
||||
/**
|
||||
* 图形数据更新
|
||||
*/
|
||||
onDataChange(newVal: GraphicData, old?: GraphicData): void;
|
||||
/**
|
||||
* 加载状态
|
||||
* @param state
|
||||
*/
|
||||
loadState(state: GraphicState): void;
|
||||
/**
|
||||
* 更新状态
|
||||
* @param state
|
||||
* @returns
|
||||
*/
|
||||
updateStates(state: GraphicState): boolean;
|
||||
/**
|
||||
* 图形状态更新处理
|
||||
*/
|
||||
onStateChange(newVal: GraphicState, old?: GraphicState): void;
|
||||
repaint(): void;
|
||||
/**
|
||||
* 处理重绘逻辑
|
||||
*/
|
||||
abstract doRepaint(): void;
|
||||
/**
|
||||
* 处理删除逻辑
|
||||
*/
|
||||
onDelete(): void;
|
||||
/**
|
||||
* 框选检测,默认取图形包围盒判定,若需要精细判定-子类重写此方法
|
||||
* @param box
|
||||
* @returns
|
||||
*/
|
||||
boxIntersectCheck(box: Rectangle): boolean;
|
||||
}
|
||||
export type CreateData = () => GraphicData;
|
||||
export type CreateState = () => GraphicState;
|
||||
export interface IGraphicTemplateOptions {
|
||||
dataTemplate?: GraphicData;
|
||||
stateTemplate?: GraphicState;
|
||||
}
|
||||
/**
|
||||
* 图形对象模板
|
||||
*/
|
||||
export declare abstract class JlGraphicTemplate<G extends JlGraphic> {
|
||||
readonly type: string;
|
||||
options: IGraphicTemplateOptions;
|
||||
constructor(type: string, options: IGraphicTemplateOptions);
|
||||
get datas(): GraphicData;
|
||||
get states(): GraphicState;
|
||||
/**
|
||||
* 初始化一个新的图形对象
|
||||
*/
|
||||
abstract new(): G;
|
||||
/**
|
||||
* 加载图形对象需要用到的资源
|
||||
*/
|
||||
loadAssets(): Promise<any>;
|
||||
/**
|
||||
* 克隆图形对象
|
||||
* @param graphic
|
||||
* @returns
|
||||
*/
|
||||
clone(graphic: G): G;
|
||||
}
|
||||
export type GraphicTemplate = JlGraphicTemplate<JlGraphic>;
|
91
lib/graphic/AbsorbablePosition.d.ts
vendored
Normal file
91
lib/graphic/AbsorbablePosition.d.ts
vendored
Normal file
@ -0,0 +1,91 @@
|
||||
import { Container, DisplayObject, Graphics, IPointData, Point } from 'pixi.js';
|
||||
import { VectorGraphic } from './VectorGraphic';
|
||||
/**
|
||||
* 抽象可吸附位置
|
||||
*/
|
||||
export interface AbsorbablePosition extends Container {
|
||||
/**
|
||||
* 是否与另一个可吸附位置重叠(相似,但可能范围不同)
|
||||
* @param other
|
||||
*/
|
||||
isOverlapping(other: AbsorbablePosition): boolean;
|
||||
/**
|
||||
* 与另一个相似的吸附位置比较范围大小
|
||||
* @param other
|
||||
* @returns >0此吸附范围大,<0另一个吸附范围大,=0两个吸附范围一样大
|
||||
*/
|
||||
compareTo(other: AbsorbablePosition): number;
|
||||
/**
|
||||
* 尝试吸附图形对象
|
||||
* @param objs 图形对象列表
|
||||
* @returns 如果吸附成功,返回true,否则false
|
||||
*/
|
||||
tryAbsorb(...objs: DisplayObject[]): void;
|
||||
}
|
||||
/**
|
||||
* 可吸附点图形参数
|
||||
*/
|
||||
export declare const AbsorbablePointParam: {
|
||||
lineWidth: number;
|
||||
lineColor: string;
|
||||
fillColor: string;
|
||||
radius: number;
|
||||
};
|
||||
/**
|
||||
* 可吸附点
|
||||
*/
|
||||
export declare class AbsorbablePoint extends Graphics implements AbsorbablePosition, VectorGraphic {
|
||||
_point: Point;
|
||||
absorbRange: number;
|
||||
scaledListenerOn: boolean;
|
||||
/**
|
||||
*
|
||||
* @param point 画布坐标
|
||||
* @param absorbRange
|
||||
*/
|
||||
constructor(point: IPointData, absorbRange?: number);
|
||||
compareTo(other: AbsorbablePosition): number;
|
||||
isOverlapping(other: AbsorbablePosition): boolean;
|
||||
tryAbsorb(...objs: DisplayObject[]): void;
|
||||
updateOnScaled(): void;
|
||||
}
|
||||
/**
|
||||
* 可吸附线
|
||||
*/
|
||||
export declare class AbsorbableLine extends Graphics implements AbsorbablePosition {
|
||||
p1: Point;
|
||||
p2: Point;
|
||||
absorbRange: number;
|
||||
_color: string;
|
||||
/**
|
||||
*
|
||||
* @param p1 画布坐标
|
||||
* @param p2 画布坐标
|
||||
* @param absorbRange
|
||||
*/
|
||||
constructor(p1: IPointData, p2: IPointData, absorbRange?: number);
|
||||
isOverlapping(other: AbsorbablePosition): boolean;
|
||||
compareTo(other: AbsorbablePosition): number;
|
||||
redraw(): void;
|
||||
tryAbsorb(...objs: DisplayObject[]): void;
|
||||
}
|
||||
/**
|
||||
* 可吸附圆
|
||||
*/
|
||||
export declare class AbsorbableCircle extends Graphics implements AbsorbablePosition {
|
||||
absorbRange: number;
|
||||
p0: Point;
|
||||
radius: number;
|
||||
_color: string;
|
||||
/**
|
||||
*
|
||||
* @param p 画布坐标
|
||||
* @param radius
|
||||
* @param absorbRange
|
||||
*/
|
||||
constructor(p: IPointData, radius: number, absorbRange?: number);
|
||||
isOverlapping(other: AbsorbablePosition): boolean;
|
||||
compareTo(other: AbsorbablePosition): number;
|
||||
redraw(): void;
|
||||
tryAbsorb(...objs: DisplayObject[]): void;
|
||||
}
|
39
lib/graphic/DashedLine.d.ts
vendored
Normal file
39
lib/graphic/DashedLine.d.ts
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
import { Container, IPointData, Point } from 'pixi.js';
|
||||
export interface IDashedLineOptions {
|
||||
/**
|
||||
* 每小段长度,默认4
|
||||
*/
|
||||
length?: number;
|
||||
/**
|
||||
* 起始间隔,默认0
|
||||
*/
|
||||
startSpace?: number;
|
||||
/**
|
||||
* 间隔长度,默认4
|
||||
*/
|
||||
space?: number;
|
||||
/**
|
||||
* 线宽,默认1
|
||||
*/
|
||||
lineWidth?: number;
|
||||
/**
|
||||
* 线色,默认黑
|
||||
*/
|
||||
color?: string;
|
||||
}
|
||||
interface ICompleteDashedLineOptions extends IDashedLineOptions {
|
||||
length: number;
|
||||
startSpace: number;
|
||||
space: number;
|
||||
lineWidth: number;
|
||||
color: string;
|
||||
}
|
||||
export declare class DashedLine extends Container {
|
||||
p1: Point;
|
||||
p2: Point;
|
||||
_options: ICompleteDashedLineOptions;
|
||||
constructor(p1: IPointData, p2: IPointData, options?: IDashedLineOptions);
|
||||
setOptions(options: IDashedLineOptions): void;
|
||||
redraw(): void;
|
||||
}
|
||||
export {};
|
23
lib/graphic/DraggablePoint.d.ts
vendored
Normal file
23
lib/graphic/DraggablePoint.d.ts
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
import { Graphics, IPointData } from 'pixi.js';
|
||||
import { VectorGraphic } from './VectorGraphic';
|
||||
/**
|
||||
* 拖拽点参数
|
||||
*/
|
||||
export declare const DraggablePointParam: {
|
||||
lineWidth: number;
|
||||
lineColor: number;
|
||||
fillColor: number;
|
||||
radius: number;
|
||||
};
|
||||
/**
|
||||
* 拖拽点,用于更新图形属性
|
||||
*/
|
||||
export declare class DraggablePoint extends Graphics implements VectorGraphic {
|
||||
scaledListenerOn: boolean;
|
||||
/**
|
||||
*
|
||||
* @param point 画布坐标点
|
||||
*/
|
||||
constructor(point: IPointData);
|
||||
updateOnScaled(): void;
|
||||
}
|
8
lib/graphic/VectorGraphic.d.ts
vendored
Normal file
8
lib/graphic/VectorGraphic.d.ts
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
import { DisplayObject } from 'pixi.js';
|
||||
export interface VectorGraphic extends DisplayObject {
|
||||
scaledListenerOn: boolean;
|
||||
updateOnScaled(): void;
|
||||
}
|
||||
export declare class VectorGraphicUtil {
|
||||
static handle(obj: VectorGraphic): void;
|
||||
}
|
16
lib/graphic/VectorText.d.ts
vendored
Normal file
16
lib/graphic/VectorText.d.ts
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
import { ICanvas, ITextStyle, Text, TextStyle } from 'pixi.js';
|
||||
import { VectorGraphic } from '.';
|
||||
/**
|
||||
* 矢量文字.实现原理:在缩放发生变化时,更新fontSize
|
||||
*/
|
||||
export declare class VectorText extends Text implements VectorGraphic {
|
||||
vectorFontSize: number;
|
||||
scaled: number;
|
||||
scaledListenerOn: boolean;
|
||||
constructor(text?: string | number, style?: Partial<ITextStyle> | TextStyle, canvas?: ICanvas);
|
||||
updateOnScaled(): void;
|
||||
/**
|
||||
* 设置矢量文字的字体大小
|
||||
*/
|
||||
setVectorFontSize(fontSize: number): void;
|
||||
}
|
5
lib/graphic/index.d.ts
vendored
Normal file
5
lib/graphic/index.d.ts
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
export * from './VectorGraphic';
|
||||
export * from './VectorText';
|
||||
export * from './DraggablePoint';
|
||||
export * from './AbsorbablePosition';
|
||||
export * from './DashedLine';
|
12
src/jlgraphic/index.ts → lib/index.d.ts
vendored
12
src/jlgraphic/index.ts → lib/index.d.ts
vendored
@ -1,7 +1,11 @@
|
||||
/// <reference path="../global.d.ts" />
|
||||
export * as GraphicsExtras from '@pixi/graphics-extras';
|
||||
export * from './app';
|
||||
export * from './core';
|
||||
export * from './graphic';
|
||||
export * from './app';
|
||||
export * from './operation';
|
||||
export * from './utils';
|
||||
export * from './plugins';
|
||||
export * from './math';
|
||||
export * from './message';
|
||||
export * from './operation';
|
||||
export * from './plugins';
|
||||
export * from './ui';
|
||||
export * from './utils';
|
7814
lib/index.js
Normal file
7814
lib/index.js
Normal file
File diff suppressed because it is too large
Load Diff
17
lib/math/Constants.d.ts
vendored
Normal file
17
lib/math/Constants.d.ts
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
/**
|
||||
* 浮点数相等判断误差值
|
||||
*/
|
||||
export declare const epsilon = 0.00001;
|
||||
/**
|
||||
* 判断浮点数是不是0
|
||||
* @param v
|
||||
* @returns
|
||||
*/
|
||||
export declare function isZero(v: number): boolean;
|
||||
/**
|
||||
* 两浮点数是否相等
|
||||
* @param f1
|
||||
* @param f2
|
||||
* @returns
|
||||
*/
|
||||
export declare function floatEquals(f1: number, f2: number): boolean;
|
91
lib/math/Vector2.d.ts
vendored
Normal file
91
lib/math/Vector2.d.ts
vendored
Normal file
@ -0,0 +1,91 @@
|
||||
export declare class Vector2 {
|
||||
constructor(values?: [number, number]);
|
||||
static from(p: {
|
||||
x: number;
|
||||
y: number;
|
||||
}): Vector2;
|
||||
private values;
|
||||
static readonly zero: Vector2;
|
||||
static readonly one: Vector2;
|
||||
get x(): number;
|
||||
set x(value: number);
|
||||
get y(): number;
|
||||
set y(value: number);
|
||||
get xy(): [number, number];
|
||||
set xy(values: [number, number]);
|
||||
at(index: number): number;
|
||||
reset(): void;
|
||||
copy(dest?: Vector2): Vector2;
|
||||
negate(dest?: Vector2): Vector2;
|
||||
equals(vector: Vector2, threshold?: number): boolean;
|
||||
length(): number;
|
||||
squaredLength(): number;
|
||||
add(vector: Vector2): Vector2;
|
||||
subtract(vector: Vector2): Vector2;
|
||||
multiply(vector: Vector2): Vector2;
|
||||
divide(vector: Vector2): Vector2;
|
||||
scale(value: number, dest?: Vector2): Vector2;
|
||||
normalize(dest?: Vector2): Vector2;
|
||||
/**
|
||||
* 向量点乘
|
||||
* @param vector
|
||||
* @param vector2
|
||||
* @returns
|
||||
*/
|
||||
static dot(vector: Vector2, vector2: Vector2): number;
|
||||
/**
|
||||
* 向量长度
|
||||
* @param vector
|
||||
* @param vector2
|
||||
* @returns
|
||||
*/
|
||||
static distance(vector: Vector2, vector2: Vector2): number;
|
||||
/**
|
||||
* 向量长度平方
|
||||
* @param vector
|
||||
* @param vector2
|
||||
* @returns
|
||||
*/
|
||||
static squaredDistance(vector: Vector2, vector2: Vector2): number;
|
||||
/**
|
||||
* v2->v1的方向的单位向量
|
||||
* @param v1
|
||||
* @param v2
|
||||
* @param dest
|
||||
* @returns
|
||||
*/
|
||||
static direction(v1: Vector2, v2: Vector2, dest?: Vector2): Vector2;
|
||||
static mix(vector: Vector2, vector2: Vector2, time: number, dest?: Vector2): Vector2;
|
||||
/**
|
||||
* 向量加法
|
||||
* @param vector
|
||||
* @param vector2
|
||||
* @param dest
|
||||
* @returns
|
||||
*/
|
||||
static sum(vector: Vector2, vector2: Vector2, dest?: Vector2): Vector2;
|
||||
/**
|
||||
* 向量减法
|
||||
* @param vector
|
||||
* @param vector2
|
||||
* @param dest
|
||||
* @returns
|
||||
*/
|
||||
static difference(vector: Vector2, vector2: Vector2, dest?: Vector2): Vector2;
|
||||
/**
|
||||
* 向量乘法
|
||||
* @param vector
|
||||
* @param vector2
|
||||
* @param dest
|
||||
* @returns
|
||||
*/
|
||||
static product(vector: Vector2, vector2: Vector2, dest?: Vector2): Vector2;
|
||||
/**
|
||||
* 向量除法
|
||||
* @param vector
|
||||
* @param vector2
|
||||
* @param dest
|
||||
* @returns
|
||||
*/
|
||||
static quotient(vector: Vector2, vector2: Vector2, dest?: Vector2): Vector2;
|
||||
}
|
2
lib/math/index.d.ts
vendored
Normal file
2
lib/math/index.d.ts
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
export * from './Constants';
|
||||
export * from './Vector2';
|
54
lib/message/BasicMessageClient.d.ts
vendored
Normal file
54
lib/message/BasicMessageClient.d.ts
vendored
Normal file
@ -0,0 +1,54 @@
|
||||
import EventEmitter from 'eventemitter3';
|
||||
import { IGraphicScene } from '../app';
|
||||
import { CompleteMessageCliOption, IMessageClient } from './MessageBroker';
|
||||
export interface MessageClientEvents {
|
||||
connected: [ctx: any];
|
||||
disconnected: [ctx: any];
|
||||
error: [err: any];
|
||||
}
|
||||
export type HandleMessage = (data: any) => void;
|
||||
export interface IMessageHandler {
|
||||
/**
|
||||
* id
|
||||
*/
|
||||
get App(): IGraphicScene;
|
||||
/**
|
||||
* 处理消息数据
|
||||
* @param data
|
||||
*/
|
||||
handle(data: any): void;
|
||||
}
|
||||
export declare abstract class MessageClient extends EventEmitter<MessageClientEvents> implements IMessageClient {
|
||||
options: CompleteMessageCliOption;
|
||||
subClients: SubscriptionClient[];
|
||||
constructor(options: CompleteMessageCliOption);
|
||||
/**
|
||||
* 订阅消息
|
||||
* @param destination
|
||||
* @param handle
|
||||
*/
|
||||
abstract subscribe(destination: string, handle: HandleMessage): boolean;
|
||||
unsubscribe(destination: string): void;
|
||||
abstract unsubscribe0(destination: string): void;
|
||||
getOrNewSubClient(destination: string): SubscriptionClient;
|
||||
addSubscription(destination: string, handler: IMessageHandler): void;
|
||||
removeSubscription(destination: string, handle: IMessageHandler): void;
|
||||
publishMessage(destination: string, message: Uint8Array): void;
|
||||
abstract get connected(): boolean;
|
||||
abstract close(): void;
|
||||
}
|
||||
export declare class SubscriptionClient {
|
||||
mc: MessageClient;
|
||||
destination: string;
|
||||
protocol: 'json' | 'protobuf';
|
||||
handlers: IMessageHandler[];
|
||||
subscripted: boolean;
|
||||
constructor(mc: MessageClient, destination: string, protocal: 'json' | 'protobuf');
|
||||
addHandler(handler: IMessageHandler): void;
|
||||
removeHandler(handler: IMessageHandler): void;
|
||||
trySubscribe(): void;
|
||||
unsubscribe(): void;
|
||||
publishMessage(destination: string, message: Uint8Array): void;
|
||||
handleMessage(data: any): void;
|
||||
onDisconnect(): void;
|
||||
}
|
154
lib/message/MessageBroker.d.ts
vendored
Normal file
154
lib/message/MessageBroker.d.ts
vendored
Normal file
@ -0,0 +1,154 @@
|
||||
import EventEmitter from 'eventemitter3';
|
||||
import { IGraphicScene } from '../app';
|
||||
import { GraphicQueryStore, GraphicState, JlGraphic } from '../core';
|
||||
import { IMessageHandler, MessageClientEvents } from './BasicMessageClient';
|
||||
export declare enum ClientEngine {
|
||||
Stomp = 0,
|
||||
MQTT = 1
|
||||
}
|
||||
export interface MessageCliOption {
|
||||
/**
|
||||
* 客户端引擎
|
||||
*/
|
||||
engine?: ClientEngine;
|
||||
/**
|
||||
* 消息协议,默认protobuf
|
||||
*/
|
||||
protocol?: 'json' | 'protobuf';
|
||||
/**
|
||||
* websocket url地址
|
||||
*/
|
||||
wsUrl: string;
|
||||
/**
|
||||
* 认证token
|
||||
*/
|
||||
token?: string;
|
||||
/**
|
||||
* 项目名称(可用于订阅客户端识别)
|
||||
*/
|
||||
clientName?: string;
|
||||
/**
|
||||
* 连接超时,默认30秒,ms
|
||||
*/
|
||||
connectTimeout?: number;
|
||||
/**
|
||||
* 心跳发送间隔,默认60秒,s
|
||||
*/
|
||||
heartbeat?: number;
|
||||
/**
|
||||
* 重试间隔,默认2秒,ms
|
||||
*/
|
||||
retryPeriod?: number;
|
||||
/**
|
||||
* 重试次数,默认100次
|
||||
*/
|
||||
retryTimes?: number;
|
||||
}
|
||||
export interface CompleteMessageCliOption extends MessageCliOption {
|
||||
protocol: 'json' | 'protobuf';
|
||||
connectTimeout: number;
|
||||
heartbeat: number;
|
||||
retryPeriod: number;
|
||||
retryTimes: number;
|
||||
}
|
||||
export interface IMessageClient extends EventEmitter<MessageClientEvents> {
|
||||
/**
|
||||
* 添加订阅
|
||||
* @param destination
|
||||
* @param handler
|
||||
*/
|
||||
addSubscription(destination: string, handler: IMessageHandler): void;
|
||||
/**
|
||||
* 移除订阅
|
||||
* @param destination
|
||||
* @param handler
|
||||
*/
|
||||
removeSubscription(destination: string, handler: IMessageHandler): void;
|
||||
/**
|
||||
* 发布消息
|
||||
* @param destination
|
||||
* @param message
|
||||
*/
|
||||
publishMessage(destination: string, message: Uint8Array): void;
|
||||
/**
|
||||
* 是否已经连接
|
||||
*/
|
||||
get connected(): boolean;
|
||||
/**
|
||||
* 关闭连接
|
||||
*/
|
||||
close(): void;
|
||||
}
|
||||
export declare class WsMsgCli {
|
||||
private static client;
|
||||
private static options;
|
||||
private static appMsgBroker;
|
||||
static new(options: MessageCliOption): void;
|
||||
static isInitiated(): boolean;
|
||||
static emitConnectStateChangeEvent(connected: boolean): void;
|
||||
static isConnected(): boolean;
|
||||
static registerSubscription(destination: string, handler: IMessageHandler): void;
|
||||
static unregisterSubscription(destination: string, handler: IMessageHandler): void;
|
||||
static registerAppMsgBroker(broker: AppWsMsgBroker): void;
|
||||
static publishMessage(destination: string, message: Uint8Array): void;
|
||||
static removeAppMsgBroker(broker: AppWsMsgBroker): void;
|
||||
static hasAppMsgBroker(): boolean;
|
||||
/**
|
||||
* 关闭websocket连接
|
||||
*/
|
||||
static close(): void;
|
||||
}
|
||||
export type GraphicStateMessageConvert = (message: Uint8Array) => GraphicState[];
|
||||
export type GraphicQuery = (state: GraphicState, store: GraphicQueryStore) => JlGraphic | undefined;
|
||||
export type SubscriptionMessageHandle = (message: Uint8Array) => void;
|
||||
export interface ICreateOnNotFound {
|
||||
graphicTypes?: string[];
|
||||
}
|
||||
export interface AppStateSubscription {
|
||||
/**
|
||||
* 订阅路径
|
||||
*/
|
||||
destination: string;
|
||||
/**
|
||||
* 图形状态消息转换
|
||||
*/
|
||||
messageConverter?: GraphicStateMessageConvert;
|
||||
/**
|
||||
* 根据状态查询图形对象,默认为根据code和type查询图形对象
|
||||
*/
|
||||
graphicQueryer?: GraphicQuery;
|
||||
/**
|
||||
* 当未根据状态找到图形对象时是否创建新对象
|
||||
* 值为设备类型列表
|
||||
*/
|
||||
createOnNotFound?: ICreateOnNotFound;
|
||||
/**
|
||||
* 订阅消息处理
|
||||
*/
|
||||
messageHandle?: SubscriptionMessageHandle;
|
||||
}
|
||||
declare class AppMessageHandler implements IMessageHandler {
|
||||
app: IGraphicScene;
|
||||
sub: AppStateSubscription;
|
||||
constructor(app: IGraphicScene, subOptions: AppStateSubscription);
|
||||
get App(): IGraphicScene;
|
||||
handle(data: any): void;
|
||||
}
|
||||
/**
|
||||
* 图形APP的websocket消息代理
|
||||
*/
|
||||
export declare class AppWsMsgBroker {
|
||||
app: IGraphicScene;
|
||||
subscriptions: Map<string, AppMessageHandler>;
|
||||
constructor(app: IGraphicScene);
|
||||
subscribe(sub: AppStateSubscription): void;
|
||||
unsbuscribe(destination: string): void;
|
||||
unsubscribeAll(): void;
|
||||
resubscribeAll(): void;
|
||||
publishMessage(destination: string, message: Uint8Array): void;
|
||||
/**
|
||||
* 取消所有订阅,从通用Stomp客户端移除此消息代理
|
||||
*/
|
||||
close(): void;
|
||||
}
|
||||
export {};
|
14
lib/message/MqttBroker.d.ts
vendored
Normal file
14
lib/message/MqttBroker.d.ts
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
import mqtt from 'mqtt';
|
||||
import { HandleMessage, MessageClient } from './BasicMessageClient';
|
||||
import { CompleteMessageCliOption } from './MessageBroker';
|
||||
export declare class MqttMsgClient extends MessageClient {
|
||||
cli: mqtt.MqttClient;
|
||||
retryTimes: number;
|
||||
subMsgHandler: Map<string, HandleMessage>;
|
||||
constructor(options: CompleteMessageCliOption);
|
||||
subscribe(destination: string, handle: HandleMessage): boolean;
|
||||
unsubscribe0(destination: string): void;
|
||||
get connected(): boolean;
|
||||
close(): void;
|
||||
publishMessage(destination: string, message: Uint8Array): void;
|
||||
}
|
12
lib/message/WsMsgBroker.d.ts
vendored
Normal file
12
lib/message/WsMsgBroker.d.ts
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
import { Client as StompClient } from '@stomp/stompjs';
|
||||
import { HandleMessage, MessageClient } from './BasicMessageClient';
|
||||
import { CompleteMessageCliOption } from './MessageBroker';
|
||||
export declare class StompMessagingClient extends MessageClient {
|
||||
cli: StompClient;
|
||||
constructor(options: CompleteMessageCliOption);
|
||||
get connected(): boolean;
|
||||
subscribe(destination: string, handle: HandleMessage): boolean;
|
||||
unsubscribe0(destination: string): void;
|
||||
publishMessage(destination: string, message: Uint8Array): void;
|
||||
close(): void;
|
||||
}
|
4
lib/message/index.d.ts
vendored
Normal file
4
lib/message/index.d.ts
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
export * from './MessageBroker';
|
||||
export * from './MqttBroker';
|
||||
export * from './WsMsgBroker';
|
||||
export * from './BasicMessageClient';
|
42
lib/operation/JlOperation.d.ts
vendored
Normal file
42
lib/operation/JlOperation.d.ts
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
import { IGraphicApp } from '../app/JlGraphicApp';
|
||||
import { JlGraphic } from '../core/JlGraphic';
|
||||
/**
|
||||
* 操作
|
||||
*/
|
||||
export declare abstract class JlOperation {
|
||||
type: string;
|
||||
app: IGraphicApp;
|
||||
obj?: any;
|
||||
data?: any;
|
||||
description?: string;
|
||||
constructor(app: IGraphicApp, type: string);
|
||||
undo1(): void;
|
||||
redo1(): void;
|
||||
abstract undo(): JlGraphic[] | void;
|
||||
abstract redo(): JlGraphic[] | void;
|
||||
}
|
||||
/**
|
||||
* 操作记录
|
||||
*/
|
||||
export declare class OperationRecord {
|
||||
undoStack: JlOperation[];
|
||||
redoStack: JlOperation[];
|
||||
private maxLen;
|
||||
constructor(maxLen?: number);
|
||||
get hasUndo(): boolean;
|
||||
get hasRedo(): boolean;
|
||||
setMaxLen(v: number): void;
|
||||
/**
|
||||
* 记录
|
||||
* @param op
|
||||
*/
|
||||
record(op: JlOperation): void;
|
||||
/**
|
||||
* 撤销
|
||||
*/
|
||||
undo(): void;
|
||||
/**
|
||||
* 重做
|
||||
*/
|
||||
redo(): void;
|
||||
}
|
48
lib/plugins/AnimationManager.d.ts
vendored
Normal file
48
lib/plugins/AnimationManager.d.ts
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
import { IGraphicScene } from '../app';
|
||||
import { GraphicAnimation, JlGraphic } from '../core';
|
||||
/**
|
||||
* 图形动画管理
|
||||
*/
|
||||
export declare class AnimationManager {
|
||||
app: IGraphicScene;
|
||||
_pause: boolean;
|
||||
/**
|
||||
* key - graphic.id
|
||||
*/
|
||||
graphicAnimationMap: Map<number, Map<string, GraphicAnimation>>;
|
||||
constructor(app: IGraphicScene);
|
||||
private run;
|
||||
pause(): void;
|
||||
resume(): void;
|
||||
destroy(): void;
|
||||
/**
|
||||
* 图形对象的所有动画map
|
||||
* @param graphic
|
||||
* @returns
|
||||
*/
|
||||
animationMap(graphic: JlGraphic): Map<string, GraphicAnimation>;
|
||||
/**
|
||||
* 注册图形动画
|
||||
* @param graphic
|
||||
* @param animation
|
||||
*/
|
||||
registerAnimation(graphic: JlGraphic, animation: GraphicAnimation): void;
|
||||
/**
|
||||
* 删除图形动画
|
||||
* @param graphic
|
||||
* @param name
|
||||
*/
|
||||
unregisterAnimation(graphic: JlGraphic, name: string): void;
|
||||
/**
|
||||
* 删除所有图形动画
|
||||
* @param graphic
|
||||
*/
|
||||
unregisterGraphicAnimations(graphic: JlGraphic): void;
|
||||
/**
|
||||
* 获取图形指定名称动画
|
||||
* @param graphic
|
||||
* @param name
|
||||
* @returns
|
||||
*/
|
||||
animation(graphic: JlGraphic, name: string): GraphicAnimation | undefined;
|
||||
}
|
82
lib/plugins/CommonMousePlugin.d.ts
vendored
Normal file
82
lib/plugins/CommonMousePlugin.d.ts
vendored
Normal file
@ -0,0 +1,82 @@
|
||||
import { DisplayObject, FederatedMouseEvent, Graphics, Point } from 'pixi.js';
|
||||
import { IGraphicScene } from '../app';
|
||||
import { JlGraphic } from '../core';
|
||||
import { AppDragEvent, AppInteractionPlugin } from './InteractionPlugin';
|
||||
type GraphicSelectFilter = (graphic: JlGraphic) => boolean;
|
||||
export interface IMouseToolOptions {
|
||||
/**
|
||||
* 是否启用框选,默认启用
|
||||
*/
|
||||
boxSelect?: boolean;
|
||||
/**
|
||||
* 是否启用视口拖拽(默认右键),默认启用
|
||||
*/
|
||||
viewportDrag?: boolean;
|
||||
/**
|
||||
* 是否启用左键视口拖拽
|
||||
*/
|
||||
viewportDragLeft?: boolean;
|
||||
/**
|
||||
* 是否启用鼠标滚轮缩放,默认启用
|
||||
*/
|
||||
wheelZoom?: boolean;
|
||||
/**
|
||||
* 可选择图形过滤器
|
||||
*/
|
||||
selectFilter?: GraphicSelectFilter;
|
||||
}
|
||||
declare class CompleteMouseToolOptions implements IMouseToolOptions {
|
||||
boxSelect: boolean;
|
||||
viewportDrag: boolean;
|
||||
viewportDragLeft: boolean;
|
||||
wheelZoom: boolean;
|
||||
selectFilter?: GraphicSelectFilter | undefined;
|
||||
constructor();
|
||||
update(options: IMouseToolOptions): void;
|
||||
}
|
||||
/**
|
||||
* 通用交互工具
|
||||
*/
|
||||
export declare class CommonMouseTool extends AppInteractionPlugin {
|
||||
static Name: string;
|
||||
static SelectBox: string;
|
||||
options: CompleteMouseToolOptions;
|
||||
box: Graphics;
|
||||
leftDownTarget: DisplayObject | null;
|
||||
drag: boolean;
|
||||
graphicSelect: boolean;
|
||||
rightTarget: DisplayObject | null;
|
||||
constructor(scene: IGraphicScene);
|
||||
static new(app: IGraphicScene): CommonMouseTool;
|
||||
bind(): void;
|
||||
unbind(): void;
|
||||
onDragStart(event: AppDragEvent): void;
|
||||
onDragMove(event: AppDragEvent): void;
|
||||
onDragEnd(event: AppDragEvent): void;
|
||||
setLeftCursor(e: FederatedMouseEvent): void;
|
||||
resumeLeftCursor(): void;
|
||||
setCursor(e: FederatedMouseEvent): void;
|
||||
resumeCursor(): void;
|
||||
onMouseDown(e: FederatedMouseEvent): void;
|
||||
/**
|
||||
* 选中处理
|
||||
* @param e
|
||||
*/
|
||||
onMouseUp(e: FederatedMouseEvent): void;
|
||||
/**
|
||||
* 清理缓存
|
||||
*/
|
||||
clearCache(): void;
|
||||
get boxSelect(): boolean | undefined;
|
||||
get selectFilter(): GraphicSelectFilter | undefined;
|
||||
/**
|
||||
* 框选图形绘制并检查
|
||||
*/
|
||||
boxSelectDraw(start: Point, end: Point): void;
|
||||
/**
|
||||
* 框选图形判断
|
||||
* @returns
|
||||
*/
|
||||
boxSelectGraphicCheck(): void;
|
||||
}
|
||||
export {};
|
35
lib/plugins/CopyPlugin.d.ts
vendored
Normal file
35
lib/plugins/CopyPlugin.d.ts
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
import { Container, FederatedPointerEvent, Point } from 'pixi.js';
|
||||
import { IGraphicScene } from '../app';
|
||||
import { JlGraphic } from '../core';
|
||||
import { KeyListener } from './KeyboardPlugin';
|
||||
interface GraphicControler {
|
||||
controlerList: KeyListener[];
|
||||
check: () => boolean;
|
||||
moveLimitOption?: {
|
||||
moveLimitName: string;
|
||||
moveLimit: (e: FederatedPointerEvent) => void;
|
||||
};
|
||||
}
|
||||
/**
|
||||
* 图形复制插件
|
||||
*/
|
||||
export declare class GraphicCopyPlugin {
|
||||
container: Container;
|
||||
scene: IGraphicScene;
|
||||
keyListeners: KeyListener[];
|
||||
graphicControlers: GraphicControler[];
|
||||
copys: JlGraphic[];
|
||||
start?: Point;
|
||||
running: boolean;
|
||||
moveLimit?: string;
|
||||
constructor(scene: IGraphicScene);
|
||||
updateMoveLimit(limit?: string): void;
|
||||
init(): void;
|
||||
addGraphicControlers(graphicControlers: GraphicControler[]): void;
|
||||
clear(): void;
|
||||
onPointerMove(e: FederatedPointerEvent): void;
|
||||
onFinish(): void;
|
||||
saveCopyGraphic(): void;
|
||||
cancle(): void;
|
||||
}
|
||||
export {};
|
82
lib/plugins/GraphicEditPlugin.d.ts
vendored
Normal file
82
lib/plugins/GraphicEditPlugin.d.ts
vendored
Normal file
@ -0,0 +1,82 @@
|
||||
import { Container, DisplayObject, Graphics, IDestroyOptions, IPointData } from 'pixi.js';
|
||||
import { JlGraphic } from '../core';
|
||||
import { DraggablePoint } from '../graphic';
|
||||
export declare abstract class GraphicEditPlugin<DO extends DisplayObject = DisplayObject> extends Container {
|
||||
graphic: DO;
|
||||
constructor(g: DO);
|
||||
destroy(options?: boolean | IDestroyOptions | undefined): void;
|
||||
abstract updateEditedPointsPosition(): void;
|
||||
hideAll(): void;
|
||||
showAll(): void;
|
||||
}
|
||||
export interface ILineGraphic extends JlGraphic {
|
||||
get linePoints(): IPointData[];
|
||||
set linePoints(points: IPointData[]);
|
||||
}
|
||||
export declare abstract class LineEditPlugin extends GraphicEditPlugin<ILineGraphic> {
|
||||
linePoints: IPointData[];
|
||||
editedPoints: DraggablePoint[];
|
||||
constructor(g: ILineGraphic);
|
||||
destroy(options?: boolean | IDestroyOptions | undefined): void;
|
||||
reset(): void;
|
||||
abstract initEditPoints(): void;
|
||||
}
|
||||
export declare function getWayLineIndex(points: IPointData[], p: IPointData): {
|
||||
start: number;
|
||||
end: number;
|
||||
};
|
||||
export declare function getWaypointRangeIndex(points: IPointData[], curve: boolean, p: IPointData, lineWidth: number): {
|
||||
start: number;
|
||||
end: number;
|
||||
};
|
||||
export type onEditPointCreate = (g: ILineGraphic, dp: DraggablePoint, index: number) => void;
|
||||
export interface IEditPointOptions {
|
||||
/**
|
||||
* 编辑点创建处理
|
||||
*/
|
||||
onEditPointCreate?: onEditPointCreate;
|
||||
}
|
||||
/**
|
||||
* 折线编辑(兼容线段)
|
||||
*/
|
||||
export declare class PolylineEditPlugin extends LineEditPlugin {
|
||||
static Name: string;
|
||||
options: IEditPointOptions;
|
||||
constructor(g: ILineGraphic, options?: IEditPointOptions);
|
||||
initEditPoints(): void;
|
||||
updateEditedPointsPosition(): void;
|
||||
}
|
||||
export interface BezierCurveEditPointOptions extends IEditPointOptions {
|
||||
auxiliaryLineColor?: string;
|
||||
smooth?: boolean;
|
||||
symmetry?: boolean;
|
||||
}
|
||||
export interface ICompleteBezierCurveEditPointOptions extends BezierCurveEditPointOptions {
|
||||
smooth: boolean;
|
||||
}
|
||||
export declare function addWayPoint(graphic: ILineGraphic, curve: boolean, start: number, end: number, p: IPointData): void;
|
||||
export declare function addLineWayPoint(graphic: ILineGraphic, start: number, end: number, p: IPointData): void;
|
||||
export declare function addPolygonSegmentingPoint(graphic: ILineGraphic, start: number, end: number, knife?: number): void;
|
||||
export declare function addBezierWayPoint(graphic: ILineGraphic, start: number, end: number, p: IPointData): void;
|
||||
export declare function removeWayPoint(graphic: ILineGraphic, curve: boolean, i: number): void;
|
||||
export declare function removeLineWayPoint(graphic: ILineGraphic, i: number): void;
|
||||
export declare function removeBezierWayPoint(graphic: ILineGraphic, i: number): void;
|
||||
/**
|
||||
* 清除路径点(只留端点),适用于直线和贝塞尔曲线
|
||||
* @param graphic
|
||||
* @param curve
|
||||
*/
|
||||
export declare function clearWayPoint(graphic: ILineGraphic, curve: boolean): void;
|
||||
/**
|
||||
* 贝塞尔曲线编辑
|
||||
*/
|
||||
export declare class BezierCurveEditPlugin extends LineEditPlugin {
|
||||
static Name: string;
|
||||
options: ICompleteBezierCurveEditPointOptions;
|
||||
auxiliaryLines: Graphics[];
|
||||
constructor(g: ILineGraphic, options?: BezierCurveEditPointOptions);
|
||||
reset(): void;
|
||||
initEditPoints(): void;
|
||||
drawAuxiliaryLine(line: Graphics, p1: IPointData, p2: IPointData): void;
|
||||
updateEditedPointsPosition(): void;
|
||||
}
|
207
lib/plugins/GraphicTransformPlugin.d.ts
vendored
Normal file
207
lib/plugins/GraphicTransformPlugin.d.ts
vendored
Normal file
@ -0,0 +1,207 @@
|
||||
import { Container, DisplayObject, Graphics, IDestroyOptions, Point } from 'pixi.js';
|
||||
import { AppDragEvent, InteractionPluginBase, KeyListener } from '.';
|
||||
import { IGraphicScene } from '../app';
|
||||
import { AbsorbablePosition, VectorText } from '../graphic';
|
||||
import { DraggablePoint } from '../graphic/DraggablePoint';
|
||||
import { DebouncedFunction } from '../utils';
|
||||
export declare class ShiftData {
|
||||
/**
|
||||
* 起始位置
|
||||
*/
|
||||
startPosition: Point;
|
||||
/**
|
||||
* 上一次终点位置
|
||||
*/
|
||||
lastPosition?: Point;
|
||||
/**
|
||||
* 当前位置
|
||||
*/
|
||||
currentPosition?: Point;
|
||||
constructor(startPosition: Point, currentPosition?: Point, lastPosition?: Point);
|
||||
static new(startPosition: Point, currentPosition?: Point, lastPosition?: Point): ShiftData;
|
||||
get dx(): number;
|
||||
get dy(): number;
|
||||
get dsx(): number;
|
||||
get dsy(): number;
|
||||
}
|
||||
export declare class ScaleData {
|
||||
start: Point;
|
||||
current?: Point;
|
||||
last?: Point;
|
||||
constructor(start: Point, current?: Point, last?: Point);
|
||||
static new(start: Point, current?: Point, last?: Point): ScaleData;
|
||||
}
|
||||
export type TransformData = ShiftData | null;
|
||||
/**
|
||||
* 图形平移事件
|
||||
*/
|
||||
export declare class GraphicTransformEvent {
|
||||
/**
|
||||
* 图形对象
|
||||
*/
|
||||
target: DisplayObject;
|
||||
type: 'shift' | 'rotate' | 'scale' | 'skew';
|
||||
data: TransformData;
|
||||
constructor(target: DisplayObject, type: 'shift' | 'rotate' | 'scale' | 'skew', data: TransformData);
|
||||
getData<D extends TransformData>(): D;
|
||||
static shift(target: DisplayObject, data: ShiftData): GraphicTransformEvent;
|
||||
static scale(target: DisplayObject): GraphicTransformEvent;
|
||||
static rotate(target: DisplayObject): GraphicTransformEvent;
|
||||
static skew(target: DisplayObject): GraphicTransformEvent;
|
||||
isShift(): boolean;
|
||||
isRotate(): boolean;
|
||||
isScale(): boolean;
|
||||
isSkew(): boolean;
|
||||
}
|
||||
export declare class GraphicTransformPlugin extends InteractionPluginBase {
|
||||
static Name: string;
|
||||
/**
|
||||
* 可吸附位置列表
|
||||
*/
|
||||
absorbablePositions?: AbsorbablePosition[];
|
||||
apContainer: Container;
|
||||
static AbsorbablePosisiontsName: string;
|
||||
constructor(app: IGraphicScene);
|
||||
/**
|
||||
* 过滤重复的吸附位置
|
||||
* @param positions
|
||||
* @returns
|
||||
*/
|
||||
filterAbsorbablePositions(positions: AbsorbablePosition[]): AbsorbablePosition[];
|
||||
static new(app: IGraphicScene): GraphicTransformPlugin;
|
||||
bind(): void;
|
||||
unbind(): void;
|
||||
getDraggedTargets(e: AppDragEvent): DisplayObject[];
|
||||
onDragStart(e: AppDragEvent): void;
|
||||
onDragMove(e: AppDragEvent): void;
|
||||
onDragEnd(e: AppDragEvent): void;
|
||||
/**
|
||||
* 清理缓存
|
||||
*/
|
||||
clearCache(): void;
|
||||
onGraphicSelectedChange(g: DisplayObject, selected: boolean): void;
|
||||
}
|
||||
/**
|
||||
* 缩放、旋转辅助
|
||||
*/
|
||||
export declare class TransformPoints extends Container {
|
||||
static Name: string;
|
||||
static MinLength: number;
|
||||
static LeftTopName: string;
|
||||
static TopName: string;
|
||||
static RightTopName: string;
|
||||
static RightName: string;
|
||||
static RightBottomName: string;
|
||||
static BottomName: string;
|
||||
static LeftBottomName: string;
|
||||
static LeftName: string;
|
||||
static RotateName: string;
|
||||
obj: DisplayObject;
|
||||
ltScalePoint: DraggablePoint;
|
||||
ltLocal: Point;
|
||||
tScalePoint: DraggablePoint;
|
||||
tLocal: Point;
|
||||
tCanvas: Point;
|
||||
rtScalePoint: DraggablePoint;
|
||||
rtLocal: Point;
|
||||
rScalePoint: DraggablePoint;
|
||||
rLocal: Point;
|
||||
rbScalePoint: DraggablePoint;
|
||||
rbLocal: Point;
|
||||
bScalePoint: DraggablePoint;
|
||||
bLocal: Point;
|
||||
lbScalePoint: DraggablePoint;
|
||||
lbLocal: Point;
|
||||
lScalePoint: DraggablePoint;
|
||||
lLocal: Point;
|
||||
originScale: Point;
|
||||
scalePivot: Point;
|
||||
/**
|
||||
* 旋转拖拽点
|
||||
*/
|
||||
rotatePoint: DraggablePoint;
|
||||
/**
|
||||
* 旋转中心坐标
|
||||
*/
|
||||
rotatePivot: Point;
|
||||
/**
|
||||
* 起始旋转坐标
|
||||
*/
|
||||
rotateLastPoint: Point;
|
||||
/**
|
||||
* 起始图形角度
|
||||
*/
|
||||
startAngle: number;
|
||||
/**
|
||||
* 当前角度信息文本辅助
|
||||
*/
|
||||
angleAssistantText: VectorText;
|
||||
/**
|
||||
* 旋转角度步长
|
||||
*/
|
||||
angleStep: number;
|
||||
/**
|
||||
* 修改旋转步长键盘监听
|
||||
*/
|
||||
rotateAngleStepKeyListeners: KeyListener[];
|
||||
constructor(obj: DisplayObject);
|
||||
onObjTransformStart(): void;
|
||||
onObjTransformEnd(): void;
|
||||
onGraphicRepaint(): void;
|
||||
/**
|
||||
* 旋转开始
|
||||
* @param de
|
||||
*/
|
||||
onRotateStart(de: GraphicTransformEvent): void;
|
||||
updateAngleAssistantText(de: GraphicTransformEvent): void;
|
||||
/**
|
||||
* 旋转移动
|
||||
* @param de
|
||||
*/
|
||||
onRotateMove(de: GraphicTransformEvent): void;
|
||||
/**
|
||||
* 旋转结束
|
||||
* @param de
|
||||
*/
|
||||
onRotateEnd(): void;
|
||||
/**
|
||||
* 缩放开始
|
||||
*/
|
||||
onScaleDragStart(): void;
|
||||
onScaleDragMove(e: GraphicTransformEvent): void;
|
||||
onScaleDragEnd(): void;
|
||||
hideOthers(dg: DisplayObject): void;
|
||||
hideAll(): void;
|
||||
showAll(): void;
|
||||
getObjBounds(): {
|
||||
width: number;
|
||||
height: number;
|
||||
};
|
||||
/**
|
||||
* 更新位置和cursor
|
||||
* @returns
|
||||
*/
|
||||
update(): void;
|
||||
updateRotatePoint(): void;
|
||||
updateScalePoints(): void;
|
||||
}
|
||||
/**
|
||||
* 包围盒矩形图形,现使用外边框转画布多边形实现
|
||||
*/
|
||||
export declare class BoundsGraphic extends Graphics {
|
||||
static Name: string;
|
||||
static BoundsLineStyle: {
|
||||
width: number;
|
||||
color: string;
|
||||
alpha: number;
|
||||
};
|
||||
obj: DisplayObject;
|
||||
debouncedRedraw: DebouncedFunction<() => void>;
|
||||
constructor(graphic: DisplayObject);
|
||||
onObjTransformStart(): void;
|
||||
onObjTransformEnd(): void;
|
||||
onGraphicRepaint(): void;
|
||||
destroy(options?: boolean | IDestroyOptions | undefined): void;
|
||||
redraw(): void;
|
||||
doRedraw(): void;
|
||||
}
|
173
lib/plugins/InteractionPlugin.d.ts
vendored
Normal file
173
lib/plugins/InteractionPlugin.d.ts
vendored
Normal file
@ -0,0 +1,173 @@
|
||||
/// <reference types="node" />
|
||||
import { DisplayObject, FederatedMouseEvent, FederatedPointerEvent, Point } from 'pixi.js';
|
||||
import { IGraphicScene } from '../app/JlGraphicApp';
|
||||
import { JlGraphic } from '../core/JlGraphic';
|
||||
export declare enum InteractionPluginType {
|
||||
App = "app",
|
||||
Graphic = "graphic",
|
||||
Other = "other"
|
||||
}
|
||||
/**
|
||||
* 交互插件
|
||||
*/
|
||||
export interface InteractionPlugin {
|
||||
readonly _type: string;
|
||||
name: string;
|
||||
app: IGraphicScene;
|
||||
/**
|
||||
* 恢复
|
||||
*/
|
||||
resume(): void;
|
||||
/**
|
||||
* 停止
|
||||
*/
|
||||
pause(): void;
|
||||
/**
|
||||
* 是否生效
|
||||
*/
|
||||
isActive(): boolean;
|
||||
isAppPlugin(): boolean;
|
||||
isOtherPlugin(): boolean;
|
||||
isGraphicPlugin(): boolean;
|
||||
}
|
||||
export declare abstract class InteractionPluginBase implements InteractionPlugin {
|
||||
readonly _type: string;
|
||||
name: string;
|
||||
app: IGraphicScene;
|
||||
_pause: boolean;
|
||||
constructor(app: IGraphicScene, name: string, type: string);
|
||||
/**
|
||||
* 恢复
|
||||
*/
|
||||
resume(): void;
|
||||
/**
|
||||
* 停止
|
||||
*/
|
||||
pause(): void;
|
||||
abstract bind(): void;
|
||||
abstract unbind(): void;
|
||||
/**
|
||||
* 是否生效
|
||||
*/
|
||||
isActive(): boolean;
|
||||
isGraphicPlugin(): boolean;
|
||||
isAppPlugin(): boolean;
|
||||
isOtherPlugin(): boolean;
|
||||
}
|
||||
export declare abstract class OtherInteractionPlugin extends InteractionPluginBase {
|
||||
constructor(app: IGraphicScene, name: string);
|
||||
}
|
||||
export declare class AppDragEvent {
|
||||
app: IGraphicScene;
|
||||
type: 'start' | 'move' | 'end';
|
||||
target: DisplayObject;
|
||||
original: FederatedPointerEvent;
|
||||
start: Point;
|
||||
constructor(app: IGraphicScene, type: 'start' | 'move' | 'end', target: DisplayObject, original: FederatedPointerEvent, start: Point);
|
||||
get isMouse(): boolean;
|
||||
get isLeftButton(): boolean;
|
||||
get isRightButton(): boolean;
|
||||
get isMiddleButton(): boolean;
|
||||
get isTouch(): boolean;
|
||||
/**
|
||||
* 终点坐标(画布坐标)
|
||||
*/
|
||||
get end(): Point;
|
||||
get dx(): number;
|
||||
get dy(): number;
|
||||
get dsx(): number;
|
||||
get dsy(): number;
|
||||
/**
|
||||
* 转换为目标对象的位移距离
|
||||
*/
|
||||
toTargetShiftLen(target: DisplayObject): {
|
||||
dx: number;
|
||||
dy: number;
|
||||
};
|
||||
}
|
||||
/**
|
||||
* 拖拽操作插件
|
||||
*/
|
||||
export declare class DragPlugin extends OtherInteractionPlugin {
|
||||
static Name: string;
|
||||
private threshold;
|
||||
target: DisplayObject | null;
|
||||
start: Point | null;
|
||||
startClientPoint: Point | null;
|
||||
drag: boolean;
|
||||
constructor(app: IGraphicScene);
|
||||
static new(app: IGraphicScene): DragPlugin;
|
||||
bind(): void;
|
||||
unbind(): void;
|
||||
onPointerDown(e: FederatedPointerEvent): void;
|
||||
onPointerMove(e: FederatedPointerEvent): void;
|
||||
onPointerUp(e: FederatedPointerEvent): void;
|
||||
/**
|
||||
* 清理缓存
|
||||
*/
|
||||
clearCache(): void;
|
||||
}
|
||||
/**
|
||||
* 视口移动插件
|
||||
*/
|
||||
export declare class ViewportMovePlugin extends OtherInteractionPlugin {
|
||||
static Name: string;
|
||||
static MoveInterval: number;
|
||||
static TriggerRange: number;
|
||||
static DefaultMoveSpeed: number;
|
||||
moveHandler: NodeJS.Timeout | null;
|
||||
moveSpeedx: number;
|
||||
moveSpeedy: number;
|
||||
constructor(app: IGraphicScene);
|
||||
static new(app: IGraphicScene): ViewportMovePlugin;
|
||||
pause(): void;
|
||||
bind(): void;
|
||||
unbind(): void;
|
||||
startMove(moveSpeedx: number, moveSpeedy: number): void;
|
||||
stopMove(): void;
|
||||
private calculateBoundaryMoveSpeed;
|
||||
calculateMoveSpeed(dd: number): number;
|
||||
viewportMove(e: FederatedMouseEvent): void;
|
||||
}
|
||||
/**
|
||||
* 应用交互插件,同时只能生效一个
|
||||
*/
|
||||
export declare abstract class AppInteractionPlugin extends InteractionPluginBase {
|
||||
constructor(name: string, app: IGraphicScene);
|
||||
/**
|
||||
* 恢复,app交互插件同时只能生效一个
|
||||
*/
|
||||
resume(): void;
|
||||
}
|
||||
/**
|
||||
* 图形交互插件,可同时生效
|
||||
*/
|
||||
export declare abstract class GraphicInteractionPlugin<G extends JlGraphic> implements InteractionPlugin {
|
||||
readonly _type = InteractionPluginType.Graphic;
|
||||
app: IGraphicScene;
|
||||
name: string;
|
||||
_pause: boolean;
|
||||
constructor(name: string, app: IGraphicScene);
|
||||
isActive(): boolean;
|
||||
isAppPlugin(): boolean;
|
||||
isOtherPlugin(): boolean;
|
||||
isGraphicPlugin(): boolean;
|
||||
resume(): void;
|
||||
pause(): void;
|
||||
/**
|
||||
* 过滤需要的图形对象
|
||||
*/
|
||||
abstract filter(...grahpics: JlGraphic[]): G[] | undefined;
|
||||
binds(list?: G[]): void;
|
||||
unbinds(list?: G[]): void;
|
||||
/**
|
||||
* 绑定图形对象的交互处理
|
||||
* @param g 图形对象
|
||||
*/
|
||||
abstract bind(g: G): void;
|
||||
/**
|
||||
* 取消图形对象的交互处理
|
||||
* @param g 图形对象
|
||||
*/
|
||||
abstract unbind(g: G): void;
|
||||
}
|
81
lib/plugins/KeyboardPlugin.d.ts
vendored
Normal file
81
lib/plugins/KeyboardPlugin.d.ts
vendored
Normal file
@ -0,0 +1,81 @@
|
||||
import { IGraphicApp } from '../app/JlGraphicApp';
|
||||
export declare class GlobalKeyboardHelper {
|
||||
appKeyboardPluginMap: JlGraphicAppKeyboardPlugin[];
|
||||
constructor();
|
||||
registerGAKPlugin(plugin: JlGraphicAppKeyboardPlugin): void;
|
||||
removeGAKPlugin(plugin: JlGraphicAppKeyboardPlugin): void;
|
||||
}
|
||||
export declare class JlGraphicAppKeyboardPlugin {
|
||||
app: IGraphicApp;
|
||||
/**
|
||||
* 结构为Map<key.code|key.key|key.keyCode, Map<KeyListener.identifier, KeyListener>>
|
||||
*/
|
||||
keyListenerMap: Map<number | string, Map<string, KeyListener>>;
|
||||
keyListenerStackMap: Map<string, KeyListener[]>;
|
||||
constructor(app: IGraphicApp);
|
||||
private getOrInit;
|
||||
private getOrInitStack;
|
||||
/**
|
||||
* 注册按键监听,若有旧的,旧的入栈
|
||||
* @param keyListener
|
||||
*/
|
||||
addKeyListener(keyListener: KeyListener): void;
|
||||
/**
|
||||
* 移除按键监听,若是当前注册的监听,尝试从栈中取出作为按键监听器,若是旧的,则同时移除栈中的监听
|
||||
* @param keyListener
|
||||
*/
|
||||
removeKeyListener(keyListener: KeyListener): void;
|
||||
getKeyListenerBy(key: string | number): Map<string, KeyListener> | undefined;
|
||||
getKeyListener(e: KeyboardEvent): Map<string, KeyListener> | undefined;
|
||||
isKeyListened(key: string | number): boolean;
|
||||
/**
|
||||
* 获取所有注册监听的键值(组合键)
|
||||
*/
|
||||
getAllListenedKeys(): string[];
|
||||
}
|
||||
type KeyboardKeyHandler = (e: KeyboardEvent, app: IGraphicApp) => void;
|
||||
export declare enum CombinationKey {
|
||||
Ctrl = "Ctrl",
|
||||
Alt = "Alt",
|
||||
Shift = "Shift"
|
||||
}
|
||||
export interface KeyListenerOptions {
|
||||
value: string | number;
|
||||
combinations?: CombinationKey[];
|
||||
global?: boolean;
|
||||
onPress?: KeyboardKeyHandler;
|
||||
pressTriggerAsOriginalEvent?: boolean;
|
||||
onRelease?: KeyboardKeyHandler;
|
||||
}
|
||||
export interface ICompleteKeyListenerOptions {
|
||||
value: string | number;
|
||||
combinations: CombinationKey[];
|
||||
global: boolean;
|
||||
onPress?: KeyboardKeyHandler;
|
||||
pressTriggerAsOriginalEvent: boolean;
|
||||
onRelease?: KeyboardKeyHandler;
|
||||
}
|
||||
export declare class KeyListener {
|
||||
readonly options: ICompleteKeyListenerOptions;
|
||||
private isPress;
|
||||
constructor(options: KeyListenerOptions);
|
||||
static create(options: KeyListenerOptions): KeyListener;
|
||||
get value(): string | number;
|
||||
get combinations(): string[];
|
||||
get identifier(): string;
|
||||
get global(): boolean | undefined;
|
||||
get onPress(): KeyboardKeyHandler | undefined;
|
||||
set onPress(v: KeyboardKeyHandler | undefined);
|
||||
get onRelease(): KeyboardKeyHandler | undefined;
|
||||
set onRelease(v: KeyboardKeyHandler | undefined);
|
||||
get pressTriggerEveryTime(): boolean;
|
||||
set pressTriggerEveryTime(v: boolean);
|
||||
press(e: KeyboardEvent, app: IGraphicApp): void;
|
||||
/**
|
||||
* 检查组合键是否匹配
|
||||
*/
|
||||
checkCombinations(e: KeyboardEvent): boolean;
|
||||
release(e: KeyboardEvent, app: IGraphicApp): void;
|
||||
onRemove(): void;
|
||||
}
|
||||
export {};
|
7
lib/plugins/index.d.ts
vendored
Normal file
7
lib/plugins/index.d.ts
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
export * from './AnimationManager';
|
||||
export * from './CommonMousePlugin';
|
||||
export * from './CopyPlugin';
|
||||
export * from './GraphicEditPlugin';
|
||||
export * from './GraphicTransformPlugin';
|
||||
export * from './InteractionPlugin';
|
||||
export * from './KeyboardPlugin';
|
164
lib/ui/ContextMenu.d.ts
vendored
Normal file
164
lib/ui/ContextMenu.d.ts
vendored
Normal file
@ -0,0 +1,164 @@
|
||||
/// <reference types="node" />
|
||||
import { Container, Graphics, Point, Rectangle, Text } from 'pixi.js';
|
||||
import { IGraphicScene } from '../app';
|
||||
import { OutOfBound } from '../utils';
|
||||
import { MenuCompletionItemStyle, MenuCompletionOptions, MenuCompletionStyleOptions, MenuGroupOptions, MenuItemOptions, MenuOptions } from './Menu';
|
||||
export declare class ContextMenuPlugin {
|
||||
app: IGraphicScene;
|
||||
contextMenuMap: Map<string, ContextMenu>;
|
||||
constructor(app: IGraphicScene);
|
||||
registerMenu(menu: ContextMenu): void;
|
||||
/**
|
||||
* 获取视口屏幕宽度
|
||||
*/
|
||||
get screenWidth(): number;
|
||||
/**
|
||||
* 获取视口屏幕高度
|
||||
*/
|
||||
get screenHeight(): number;
|
||||
/**
|
||||
* 打开菜单
|
||||
* @param menu
|
||||
* @param global
|
||||
*/
|
||||
open(menu: ContextMenu, global: Point): void;
|
||||
/**
|
||||
* 关闭菜单
|
||||
* @param menu
|
||||
*/
|
||||
close(menu: ContextMenu): void;
|
||||
/**
|
||||
* 关闭所有菜单
|
||||
*/
|
||||
closeAll(): void;
|
||||
/**
|
||||
* 越界检查
|
||||
* @param menu
|
||||
* @param global
|
||||
* @returns
|
||||
*/
|
||||
oob(menu: ContextMenu, global: Point): OutOfBound;
|
||||
}
|
||||
/**
|
||||
* 上下文菜单,多级嵌套
|
||||
*/
|
||||
export declare class ContextMenu extends Container {
|
||||
_plugin?: ContextMenuPlugin;
|
||||
parentMenuItem?: ContextMenuItem;
|
||||
openedSubMenu?: ContextMenu;
|
||||
menuOptions: MenuCompletionOptions;
|
||||
opened: boolean;
|
||||
bg: Graphics;
|
||||
title?: Text;
|
||||
groups: MenuGroup[];
|
||||
private padding;
|
||||
_active: boolean;
|
||||
timeoutCloseHandle?: NodeJS.Timeout;
|
||||
constructor(menuOptions: MenuOptions, parentMenuItem?: ContextMenuItem);
|
||||
static init(options: MenuOptions): ContextMenu;
|
||||
get style(): MenuCompletionStyleOptions;
|
||||
/**
|
||||
* 父级菜单
|
||||
*/
|
||||
get parentMenu(): ContextMenu | undefined;
|
||||
/**
|
||||
* 最顶级菜单
|
||||
*/
|
||||
get rootMenu(): ContextMenu;
|
||||
/**
|
||||
* 是否存在激活的菜单项
|
||||
* @returns
|
||||
*/
|
||||
hasActiveItem(): boolean;
|
||||
get active(): boolean;
|
||||
set active(v: boolean);
|
||||
onActiveChanged(): void;
|
||||
setOptions(menuOptions: MenuOptions): void;
|
||||
/**
|
||||
* 初始化
|
||||
*/
|
||||
init(): void;
|
||||
initGroups(): void;
|
||||
initTitle(): void;
|
||||
private calculateBorderInfo;
|
||||
updateBg(): void;
|
||||
update(): void;
|
||||
get menuName(): string;
|
||||
get plugin(): ContextMenuPlugin;
|
||||
set plugin(v: ContextMenuPlugin);
|
||||
/**
|
||||
* 显示菜单
|
||||
*/
|
||||
open(global: Point): void;
|
||||
/**
|
||||
* 关闭菜单
|
||||
*/
|
||||
close(): void;
|
||||
/**
|
||||
* 打开子菜单
|
||||
* @param subMenu
|
||||
* @param global
|
||||
*/
|
||||
private openSub;
|
||||
}
|
||||
declare class MenuGroup extends Container {
|
||||
private gutter;
|
||||
config: MenuGroupOptions;
|
||||
menu: ContextMenu;
|
||||
items: ContextMenuItem[];
|
||||
constructor(menu: ContextMenu, config: MenuGroupOptions);
|
||||
private init;
|
||||
hasActiveItem(): boolean;
|
||||
get maxItemNameWidth(): number;
|
||||
get maxShortcutWidth(): number;
|
||||
get totalGutter(): number;
|
||||
get totalHeight(): number;
|
||||
update(): void;
|
||||
updateItemBox(maxItemWidth: number): void;
|
||||
}
|
||||
/**
|
||||
* 菜单项
|
||||
*/
|
||||
declare class ContextMenuItem extends Container {
|
||||
menu: ContextMenu;
|
||||
config: MenuItemOptions;
|
||||
/**
|
||||
* 名称文本
|
||||
*/
|
||||
nameText: Text;
|
||||
/**
|
||||
* 快捷键文本
|
||||
*/
|
||||
shortcutKeyText?: Text;
|
||||
private gutter;
|
||||
arrowText?: Text;
|
||||
box: Graphics;
|
||||
subMenu?: ContextMenu;
|
||||
_active: boolean;
|
||||
constructor(menu: ContextMenu, config: MenuItemOptions);
|
||||
registerEventHandler(): void;
|
||||
get active(): boolean;
|
||||
set active(v: boolean);
|
||||
onActiveChanged(): void;
|
||||
get textWidth(): number;
|
||||
get nameGraphic(): Text;
|
||||
get totalHeight(): number;
|
||||
get nameBounds(): Rectangle;
|
||||
get shortcutKeyBounds(): Rectangle;
|
||||
get style(): MenuCompletionItemStyle;
|
||||
private checkPadding;
|
||||
private toWholePadding;
|
||||
get paddingTop(): number;
|
||||
get paddingBottom(): number;
|
||||
get paddingLeft(): number;
|
||||
get paddingRight(): number;
|
||||
get hoverColor(): string;
|
||||
get fontSize(): number;
|
||||
get fontColor(): string;
|
||||
initShortcutKeyText(): Text | undefined;
|
||||
initSubMenu(): void;
|
||||
updateBackground(width: number, height: number): void;
|
||||
updateBox(width: number, height: number): void;
|
||||
update(): void;
|
||||
}
|
||||
export {};
|
146
lib/ui/Menu.d.ts
vendored
Normal file
146
lib/ui/Menu.d.ts
vendored
Normal file
@ -0,0 +1,146 @@
|
||||
/**
|
||||
* 菜单配置项
|
||||
*/
|
||||
export interface MenuOptions {
|
||||
/**
|
||||
* 菜单名称,需唯一
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* 菜单标题
|
||||
*/
|
||||
title?: string;
|
||||
/**
|
||||
* 菜单分组
|
||||
*/
|
||||
groups: MenuGroupOptions[];
|
||||
/**
|
||||
* 菜单样式
|
||||
*/
|
||||
style?: MenuStyleOptions;
|
||||
}
|
||||
/**
|
||||
* 菜单分组
|
||||
*/
|
||||
export interface MenuGroupOptions {
|
||||
/**
|
||||
* 分组命名
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* 菜单项
|
||||
*/
|
||||
items: MenuItemOptions[];
|
||||
}
|
||||
export interface MenuCompletionOptions extends MenuOptions {
|
||||
style: MenuCompletionStyleOptions;
|
||||
}
|
||||
/**
|
||||
* 菜单样式配置项
|
||||
*/
|
||||
export interface MenuStyleOptions {
|
||||
/**
|
||||
* 菜单标题样式
|
||||
*/
|
||||
titleStyle?: MenuItemStyle;
|
||||
/**
|
||||
* 菜单背景色
|
||||
*/
|
||||
backgroundColor?: string;
|
||||
/**
|
||||
* 菜单边框线宽度,默认1,0为无线框
|
||||
*/
|
||||
borderWidth?: number;
|
||||
/**
|
||||
* 菜单边框颜色
|
||||
*/
|
||||
borderColor?: string;
|
||||
/**
|
||||
* 包围框是否圆角,圆角的半径,0为直角
|
||||
*/
|
||||
borderRoundRadius?: number;
|
||||
/**
|
||||
* 菜单项样式
|
||||
*/
|
||||
itemStyle?: MenuItemStyle;
|
||||
}
|
||||
export interface MenuCompletionStyleOptions extends MenuStyleOptions {
|
||||
titleStyle: MenuItemStyle;
|
||||
backgroundColor: string;
|
||||
border: boolean;
|
||||
borderWidth: number;
|
||||
borderColor: string;
|
||||
borderRoundRadius: number;
|
||||
itemStyle: MenuCompletionItemStyle;
|
||||
}
|
||||
export interface MenuItemOptions {
|
||||
/**
|
||||
* 名称
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* 是否禁用,默认不禁用
|
||||
*/
|
||||
disabled?: boolean;
|
||||
/**
|
||||
* 是否显示,默认显示
|
||||
*/
|
||||
visible?: boolean;
|
||||
/**
|
||||
* 快捷键
|
||||
*/
|
||||
shortcutKeys?: string[];
|
||||
/**
|
||||
* 菜单逻辑处理
|
||||
*/
|
||||
handler?: () => void;
|
||||
fontColor?: string;
|
||||
/**
|
||||
* 子菜单
|
||||
*/
|
||||
subMenu?: MenuOptions;
|
||||
}
|
||||
export interface MenuItemStyle {
|
||||
/**
|
||||
* 字体大小
|
||||
*/
|
||||
fontSize: number;
|
||||
/**
|
||||
* 字体颜色
|
||||
*/
|
||||
fontColor?: string;
|
||||
/**
|
||||
* hover颜色
|
||||
*/
|
||||
hoverColor?: string;
|
||||
/**
|
||||
* 禁用下字体颜色
|
||||
*/
|
||||
disabledFontColor?: string;
|
||||
/**
|
||||
* 内边距
|
||||
*/
|
||||
padding: number[] | number;
|
||||
}
|
||||
export interface MenuCompletionItemStyle extends MenuItemStyle {
|
||||
/**
|
||||
* 文字颜色
|
||||
*/
|
||||
fontColor: string;
|
||||
/**
|
||||
* 激活颜色
|
||||
*/
|
||||
hoverColor: string;
|
||||
/**
|
||||
* 禁用下字体颜色
|
||||
*/
|
||||
disabledFontColor: string;
|
||||
}
|
||||
/**
|
||||
* 默认的白色样式
|
||||
*/
|
||||
export declare const DefaultWhiteStyleOptions: MenuCompletionStyleOptions;
|
||||
/**
|
||||
* 默认的白色菜单配置
|
||||
*/
|
||||
export declare const DefaultWhiteMenuOptions: MenuCompletionOptions;
|
2
lib/ui/index.d.ts
vendored
Normal file
2
lib/ui/index.d.ts
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
export * from './ContextMenu';
|
||||
export * from './Menu';
|
232
lib/utils/GraphicUtils.d.ts
vendored
Normal file
232
lib/utils/GraphicUtils.d.ts
vendored
Normal file
@ -0,0 +1,232 @@
|
||||
import { Container, DisplayObject, IPointData, Point, Rectangle } from 'pixi.js';
|
||||
/**
|
||||
* 递归父节点执行逻辑
|
||||
* @param obj
|
||||
* @param handler
|
||||
*/
|
||||
export declare function recursiveParents(obj: DisplayObject, handler: (parent: Container) => void): void;
|
||||
/**
|
||||
* 递归父节点查询父节点对象
|
||||
* @param obj
|
||||
* @param finder
|
||||
* @returns
|
||||
*/
|
||||
export declare function recursiveFindParent(obj: DisplayObject, finder: (parent: Container) => boolean): Container | null;
|
||||
/**
|
||||
* 递归子节点执行逻辑
|
||||
* @param container
|
||||
* @param handler
|
||||
*/
|
||||
export declare function recursiveChildren(container: Container, handler: (child: DisplayObject) => void): void;
|
||||
/**
|
||||
* 递归子节点查询子节点对象
|
||||
*/
|
||||
export declare function recursiveFindChild(container: Container, finder: (child: DisplayObject) => boolean): DisplayObject | null;
|
||||
export interface BezierParam {
|
||||
p1: IPointData;
|
||||
p2: IPointData;
|
||||
cp1: IPointData;
|
||||
cp2: IPointData;
|
||||
}
|
||||
/**
|
||||
* 判断贝塞尔曲线数据是否正确
|
||||
* @param points
|
||||
*/
|
||||
export declare function assertBezierPoints(points: IPointData[]): void;
|
||||
/**
|
||||
* 转换为贝塞尔曲线参数
|
||||
* @param points
|
||||
* @returns
|
||||
*/
|
||||
export declare function convertToBezierParams(points: IPointData[]): BezierParam[];
|
||||
/**
|
||||
* 根据分段数计算贝塞尔曲线所有点坐标
|
||||
* @param basePoints
|
||||
* @param segmentsCount
|
||||
* @returns
|
||||
*/
|
||||
export declare function calculateBezierPoints(basePoints: IPointData[], segmentsCount: number): Point[];
|
||||
/**
|
||||
* 根据分段数计算贝塞尔曲线所有点坐标
|
||||
* @param basePoints
|
||||
* @param segmentsCount
|
||||
* @returns
|
||||
*/
|
||||
export declare function calculateOneBezierPoints(p1: IPointData, p2: IPointData, cp1: IPointData, cp2: IPointData, segmentsCount: number): Point[];
|
||||
/**
|
||||
* 计算矩形中点
|
||||
*/
|
||||
export declare function getRectangleCenter(rectangle: Rectangle): Point;
|
||||
/**
|
||||
* 计算两个矩形中心对齐的坐标, PS: 计算的是较大包围框的中心
|
||||
* @param rect1
|
||||
* @param rect2
|
||||
* @returns
|
||||
*/
|
||||
export declare function getCenterOfTwoRectangle(rect1: Rectangle, rect2: Rectangle): Point;
|
||||
/**
|
||||
* 序列化图形变换
|
||||
* @param obj
|
||||
* @returns
|
||||
*/
|
||||
export declare function serializeTransform(obj: DisplayObject): number[];
|
||||
/**
|
||||
* 反序列化变换数据到图形对象
|
||||
* @param obj
|
||||
* @param transform
|
||||
*/
|
||||
export declare function deserializeTransformInto(obj: DisplayObject, transform: number[]): void;
|
||||
/**
|
||||
* 将直线转换为多边形
|
||||
* @param p1
|
||||
* @param p2
|
||||
* @param thick
|
||||
* @returns
|
||||
*/
|
||||
export declare function convertLineToPolygonPoints(p1: IPointData, p2: IPointData, thick: number): IPointData[];
|
||||
/**
|
||||
* 转换矩形为多边形点坐标
|
||||
* @param rect 矩形
|
||||
* @returns
|
||||
*/
|
||||
export declare function convertRectangleToPolygonPoints(rect: Rectangle): IPointData[];
|
||||
/**
|
||||
* 计算线段中点坐标
|
||||
* @param p1
|
||||
* @param p2
|
||||
* @returns
|
||||
*/
|
||||
export declare function calculateLineMidpoint(p1: IPointData, p2: IPointData): Point;
|
||||
/**
|
||||
* 计算线段细分坐标--线段分成几份
|
||||
* @param p1
|
||||
* @param p2
|
||||
* @param knife
|
||||
* @returns
|
||||
*/
|
||||
export declare function calculateLineSegmentingPoint(p1: IPointData, p2: IPointData, knife: number): IPointData[];
|
||||
/**
|
||||
* 计算点到直线距离
|
||||
* @param p1
|
||||
* @param p2
|
||||
* @param p
|
||||
*/
|
||||
export declare function calculateDistanceFromPointToLine(p1: IPointData, p2: IPointData, p: IPointData): number;
|
||||
/**
|
||||
* 计算点到直线的垂足坐标
|
||||
* @param p
|
||||
* @param p1
|
||||
* @param p2
|
||||
*/
|
||||
export declare function calculateFootPointFromPointToLine(p1: IPointData, p2: IPointData, p: IPointData): Point;
|
||||
/**
|
||||
* 计算直线与圆的交点
|
||||
* 1用直线到圆心的距离和半径相比,判断是否和圆有交点;
|
||||
* 2求出圆心在直线上面的垂点;
|
||||
* 3算出直线的单位向量e;
|
||||
* 4求出一侧交点(Intersection)到projectPoint的长度(sideLength);
|
||||
* 5求出sideLength和这侧端点到projectPoint距离的比例(ratio);
|
||||
* 6projectPoint +/- ratio * e = 两侧交点;
|
||||
* @param p0 圆心坐标
|
||||
* @param radius 圆半径
|
||||
* @param p1 直线坐标1
|
||||
* @param p2 直线坐标2
|
||||
* @returns 交点坐标,可能2/1/0个
|
||||
*/
|
||||
export declare function calculateIntersectionPointOfCircleAndLine(p0: IPointData, radius: number, p1: IPointData, p2: IPointData): Point[];
|
||||
/**
|
||||
* 计算圆心与圆心外一点与圆的交点(取圆心到点的向量与圆的交点)
|
||||
* @param p0 圆心坐标
|
||||
* @param radius 圆半径
|
||||
* @param p 点坐标
|
||||
* @returns
|
||||
*/
|
||||
export declare function calculateIntersectionPointOfCircleAndPoint(p0: IPointData, radius: number, p: IPointData): Point;
|
||||
/**
|
||||
* 计算点基于点的镜像点坐标
|
||||
* @param bp 基准点
|
||||
* @param p 待镜像的点坐标
|
||||
* @param distance 镜像点到基准点的距离,默认为p到基准点的距离,即对称
|
||||
* @returns
|
||||
*/
|
||||
export declare function calculateMirrorPoint(bp: IPointData, p: IPointData, distance?: number): Point;
|
||||
/**
|
||||
* 计算基于给定轴的给定点的镜像点坐标
|
||||
* @param pa 给定轴线的坐标
|
||||
* @param pb 给定轴线的坐标
|
||||
* @param p 待镜像点坐标
|
||||
* @param distance
|
||||
* @returns
|
||||
*/
|
||||
export declare function calculateMirrorPointBasedOnAxis(pa: IPointData, pb: IPointData, p: IPointData, distance?: number): Point;
|
||||
/**
|
||||
* 计算直线与水平夹角,角度按顺时针,从0开始
|
||||
* @param p1
|
||||
* @param p2
|
||||
* @returns 角度,范围[0, 360)
|
||||
*/
|
||||
export declare function angleToAxisx(p1: IPointData, p2: IPointData): number;
|
||||
/**
|
||||
* 计算两线夹角,pc与pa,pb的夹角,顺时针为正,逆时针为负
|
||||
* @param pa 交点
|
||||
* @param pb 锚定
|
||||
* @param pc
|
||||
* @returns 夹角, [-180, 180]
|
||||
*/
|
||||
export declare function angleOfIncludedAngle(pa: IPointData, pb: IPointData, pc: IPointData): number;
|
||||
/**
|
||||
* 计算两点连线的法向量
|
||||
* @param point1
|
||||
* @param point2
|
||||
* @returns 单位法向量
|
||||
*/
|
||||
export declare function getNormalVector(point1: IPointData, point2: IPointData): number[];
|
||||
/**
|
||||
* 点延向量方向移动
|
||||
* @param point
|
||||
* @param normal 单位向量
|
||||
* @param length 平移长度
|
||||
* @returns 移动后的点
|
||||
*/
|
||||
export declare function movePointAlongNormal(point: IPointData, normal: number[], length: number): Point;
|
||||
/**
|
||||
* 计算两组点各自组成直线的相交点(若两线平行 返回第一组坐标第一个点)
|
||||
* @param line1 两点坐标列表
|
||||
* @param line2 两点坐标列表
|
||||
* @returns 相交点
|
||||
*/
|
||||
export declare function getIntersectionPoint(line1: number[], line2: number[]): Point;
|
||||
/**
|
||||
* 是否平行线
|
||||
* @param p1
|
||||
* @param p2
|
||||
* @param pa
|
||||
* @param pb
|
||||
* @returns
|
||||
*/
|
||||
export declare function isParallelLines(p1: IPointData, p2: IPointData, pa: IPointData, pb: IPointData): boolean;
|
||||
/**
|
||||
* 点是否在线段上
|
||||
* @param p1
|
||||
* @param p2
|
||||
* @param p
|
||||
* @returns
|
||||
*/
|
||||
export declare function isPointOnLine(p1: IPointData, p2: IPointData, p: IPointData): boolean;
|
||||
/**
|
||||
* 两条线段是否存在包含关系
|
||||
* @param line1
|
||||
* @param line2
|
||||
* @returns
|
||||
*/
|
||||
export declare function isLineContainOther(line1: {
|
||||
p1: IPointData;
|
||||
p2: IPointData;
|
||||
}, line2: {
|
||||
p1: IPointData;
|
||||
p2: IPointData;
|
||||
}): boolean;
|
||||
/** 均分线段, 返回各线段端点 */
|
||||
export declare function splitLineEvenly(p1: IPointData, p2: IPointData, count: number): IPointData[][];
|
||||
export declare function splitPolyline(points: IPointData[], count: number): IPointData[][];
|
||||
export declare function getParallelOfPolyline(points: IPointData[], offset: number, side: 'L' | 'R'): IPointData[];
|
119
lib/utils/IntersectUtils.d.ts
vendored
Normal file
119
lib/utils/IntersectUtils.d.ts
vendored
Normal file
@ -0,0 +1,119 @@
|
||||
import { IPointData, Rectangle } from 'pixi.js';
|
||||
/**
|
||||
* 根据点到直线的垂直距离计算碰撞
|
||||
* @param pa 线段a端坐标
|
||||
* @param pb 线段b端坐标
|
||||
* @param p 点坐标
|
||||
* @param lineWidth 线宽
|
||||
* @param exact 是否精确(使用给定线宽,否则线宽会设置为8)
|
||||
* @returns
|
||||
*/
|
||||
export declare function linePoint(pa: IPointData, pb: IPointData, p: IPointData, lineWidth: number, exact?: boolean): boolean;
|
||||
/**
|
||||
* 折线与点碰撞
|
||||
* @param points 折线端点列表
|
||||
* @param p 点座标
|
||||
* @param lineWidth 线宽
|
||||
*/
|
||||
export declare function polylinePoint(points: IPointData[], p: IPointData, lineWidth: number): boolean;
|
||||
/**
|
||||
* 线线碰撞检测
|
||||
* @param pa 线段1a端坐标
|
||||
* @param pb 线段1b端坐标
|
||||
* @param p1 线段2a端坐标
|
||||
* @param p2 线段2b端坐标
|
||||
* @returns
|
||||
*/
|
||||
export declare function lineLine(pa: IPointData, pb: IPointData, p1: IPointData, p2: IPointData): boolean;
|
||||
/**
|
||||
* 点和矩形碰撞检测
|
||||
* @param p 点作弊
|
||||
* @param rect 矩形
|
||||
* @returns
|
||||
*/
|
||||
export declare function pointBox(p: IPointData, rect: Rectangle): boolean;
|
||||
/**
|
||||
* 线和矩形碰撞检测
|
||||
* @param pa 线段a端坐标
|
||||
* @param pb 线段b端坐标
|
||||
* @param rect 矩形
|
||||
* @returns
|
||||
*/
|
||||
export declare function lineBox(pa: IPointData, pb: IPointData, rect: Rectangle): boolean;
|
||||
/**
|
||||
* 多线段和矩形碰撞检测
|
||||
* @param points
|
||||
* @param rect
|
||||
* @returns false / 碰撞的线段序号
|
||||
*/
|
||||
export declare function polylineBox(points: IPointData[], rect: Rectangle): boolean;
|
||||
/**
|
||||
* 两点碰撞检测
|
||||
* @param p1
|
||||
* @param p2
|
||||
* @param tolerance
|
||||
* @returns
|
||||
*/
|
||||
export declare function pointPoint2(p1: IPointData, p2: IPointData, tolerance: number): boolean;
|
||||
/**
|
||||
* 两点碰撞检测
|
||||
* @param x1
|
||||
* @param y1
|
||||
* @param x2
|
||||
* @param y2
|
||||
* @param tolerance 容忍度/两点半径和
|
||||
* @returns
|
||||
*/
|
||||
export declare function pointPoint(x1: number, y1: number, x2: number, y2: number, tolerance: number): boolean;
|
||||
/**
|
||||
* 两点距离
|
||||
* @param x1
|
||||
* @param y1
|
||||
* @param x2
|
||||
* @param y2
|
||||
* @returns
|
||||
*/
|
||||
export declare function distance(x1: number, y1: number, x2: number, y2: number): number;
|
||||
/**
|
||||
* 两点距离
|
||||
* @param p1
|
||||
* @param p2
|
||||
* @returns
|
||||
*/
|
||||
export declare function distance2(p1: IPointData, p2: IPointData): number;
|
||||
/**
|
||||
* 圆和点的碰撞检测
|
||||
* @param x1 圆心x
|
||||
* @param y1 圆心y
|
||||
* @param r1 圆半径
|
||||
* @param x2 点x
|
||||
* @param y2 点y
|
||||
* @returns
|
||||
*/
|
||||
export declare function circlePoint(x1: number, y1: number, r1: number, x2: number, y2: number): boolean;
|
||||
/**
|
||||
* 圆和点的碰撞检测--不包括圆内部
|
||||
*/
|
||||
export declare function circlePoint2(x1: number, y1: number, r1: number, x2: number, y2: number, tolerance: number): boolean;
|
||||
/**
|
||||
* 点和多边形碰撞检测
|
||||
*/
|
||||
export declare function pointPolygon(p: IPointData, points: IPointData[], lineWidth: number): boolean;
|
||||
/**
|
||||
* 线和多边形碰撞检测
|
||||
* @param p1
|
||||
* @param p2
|
||||
* @param points
|
||||
* @param tolerance 多边形包围线宽
|
||||
* @returns
|
||||
*/
|
||||
export declare function linePolygon(p1: IPointData, p2: IPointData, points: IPointData[], lineWidth: number, polygonWidth: number): boolean;
|
||||
/**
|
||||
* 多边线与多边形碰撞检测
|
||||
* @param polylinePoints 多边线所有点坐标
|
||||
* @param polygonPoints 多边形所有点坐标
|
||||
* @param polylineWidth 多边线的线宽
|
||||
* @param polygonWidth 多边形线宽
|
||||
* @returns
|
||||
*/
|
||||
export declare function polylinePolygon(polylinePoints: IPointData[], polygonPoints: IPointData[], polylineWidth: number, polygonWidth: number): boolean;
|
5
lib/utils/debounce.d.ts
vendored
Normal file
5
lib/utils/debounce.d.ts
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
export interface DebouncedFunction<F extends (...args: any[]) => any> {
|
||||
(context: ThisParameterType<F>, ...args: Parameters<F>): void;
|
||||
cancel: () => void;
|
||||
}
|
||||
export declare function debounce<F extends (...args: Parameters<F>) => any>(fn: F, waitMs?: number): DebouncedFunction<F>;
|
26
lib/utils/index.d.ts
vendored
Normal file
26
lib/utils/index.d.ts
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
import { Point, Rectangle } from 'pixi.js';
|
||||
export * from './GraphicUtils';
|
||||
export * from './IntersectUtils';
|
||||
export * from './debounce';
|
||||
export declare const UP: Point;
|
||||
export declare const DOWN: Point;
|
||||
export declare const LEFT: Point;
|
||||
export declare const RIGHT: Point;
|
||||
/**
|
||||
* 越界结果
|
||||
*/
|
||||
export declare class OutOfBound {
|
||||
left: boolean;
|
||||
top: boolean;
|
||||
right: boolean;
|
||||
bottom: boolean;
|
||||
constructor(left: boolean, top: boolean, right: boolean, bottom: boolean);
|
||||
static check(rect: Rectangle, bound: Rectangle): OutOfBound;
|
||||
static none(): OutOfBound;
|
||||
static leftOut(): OutOfBound;
|
||||
static topOut(): OutOfBound;
|
||||
static rightOut(): OutOfBound;
|
||||
static bottomOut(): OutOfBound;
|
||||
static leftTopOut(): OutOfBound;
|
||||
static rightBottomOut(): OutOfBound;
|
||||
}
|
55
package.json
55
package.json
@ -1,50 +1,43 @@
|
||||
{
|
||||
"name": "graphic-pixi",
|
||||
"version": "0.0.1",
|
||||
"version": "0.1.18",
|
||||
"description": "基于pixijs的图形应用、绘制应用框架",
|
||||
"productName": "Graphic-pixi",
|
||||
"author": "walker <shengxuqiang@joylink.club>",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"main": "lib/index.js",
|
||||
"types": "lib/index.d.ts",
|
||||
"scripts": {
|
||||
"lint": "eslint --ext .js,.ts,.vue ./",
|
||||
"format": "prettier --write \"**/*.{js,ts,vue,scss,html,md,json}\" --ignore-path .gitignore",
|
||||
"test": "echo \"No test specified\" && exit 0",
|
||||
"dev": "quasar dev",
|
||||
"proto": "node scripts/proto.cjs",
|
||||
"build": "quasar build"
|
||||
"build": "rollup -c rollup.config.mjs"
|
||||
},
|
||||
"files": [
|
||||
"lib",
|
||||
"*.d.ts"
|
||||
],
|
||||
"dependencies": {
|
||||
"@pixi/graphics-extras": "^7.2.4",
|
||||
"@quasar/extras": "^1.0.0",
|
||||
"@pixi/graphics-extras": "^7.3.2",
|
||||
"@pixi/utils": "^7.3.2",
|
||||
"@stomp/stompjs": "^7.0.0",
|
||||
"alova": "^2.7.1",
|
||||
"axios": "^1.4.0",
|
||||
"google-protobuf": "^3.21.2",
|
||||
"js-base64": "^3.7.5",
|
||||
"pinia": "^2.0.11",
|
||||
"mqtt": "^5.2.1",
|
||||
"pixi-viewport": "^5.0.1",
|
||||
"pixi.js": "^7.2.4",
|
||||
"quasar": "^2.6.0",
|
||||
"vue": "^3.0.0",
|
||||
"vue-router": "^4.0.0"
|
||||
"pixi.js": "^7.3.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@quasar/app-vite": "^1.0.0",
|
||||
"@types/google-protobuf": "^3.15.6",
|
||||
"@rollup/plugin-alias": "^5.1.0",
|
||||
"@rollup/plugin-replace": "^5.0.5",
|
||||
"@rollup/plugin-typescript": "^11.1.5",
|
||||
"@types/node": "^12.20.21",
|
||||
"@typescript-eslint/eslint-plugin": "^5.10.0",
|
||||
"@typescript-eslint/parser": "^5.10.0",
|
||||
"autoprefixer": "^10.4.2",
|
||||
"eslint": "^8.10.0",
|
||||
"eslint-config-prettier": "^8.1.0",
|
||||
"eslint-plugin-vue": "^9.0.0",
|
||||
"prettier": "^2.5.1",
|
||||
"protoc-gen-ts": "^0.8.6",
|
||||
"ts-md5": "^1.3.1",
|
||||
"typescript": "^4.5.4"
|
||||
"eslint": "^8.55.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-prettier": "^5.0.1",
|
||||
"prettier": "^3.1.1",
|
||||
"rollup": "^4.8.0",
|
||||
"rollup-plugin-dts": "^6.1.0",
|
||||
"typescript": "^5.3.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18 || ^16 || ^14.19",
|
||||
"node": ">= 14.19",
|
||||
"npm": ">= 6.13.4",
|
||||
"yarn": ">= 1.21.1"
|
||||
}
|
||||
|
@ -1,27 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// https://github.com/michael-ciniawsky/postcss-load-config
|
||||
|
||||
module.exports = {
|
||||
plugins: [
|
||||
// https://github.com/postcss/autoprefixer
|
||||
require('autoprefixer')({
|
||||
overrideBrowserslist: [
|
||||
'last 4 Chrome versions',
|
||||
'last 4 Firefox versions',
|
||||
'last 4 Edge versions',
|
||||
'last 4 Safari versions',
|
||||
'last 4 Android versions',
|
||||
'last 4 ChromeAndroid versions',
|
||||
'last 4 FirefoxAndroid versions',
|
||||
'last 4 iOS versions'
|
||||
]
|
||||
})
|
||||
|
||||
// https://github.com/elchininet/postcss-rtlcss
|
||||
// If you want to support RTL css, then
|
||||
// 1. yarn/npm install postcss-rtlcss
|
||||
// 2. optionally set quasar.config.js > framework > lang to an RTL language
|
||||
// 3. uncomment the following line:
|
||||
// require('postcss-rtlcss')
|
||||
]
|
||||
}
|
Binary file not shown.
Before Width: | Height: | Size: 63 KiB |
Binary file not shown.
Before Width: | Height: | Size: 12 KiB |
Binary file not shown.
Before Width: | Height: | Size: 859 B |
Binary file not shown.
Before Width: | Height: | Size: 2.0 KiB |
Binary file not shown.
Before Width: | Height: | Size: 9.4 KiB |
208
quasar.config.js
208
quasar.config.js
@ -1,208 +0,0 @@
|
||||
/* eslint-env node */
|
||||
|
||||
/*
|
||||
* This file runs in a Node context (it's NOT transpiled by Babel), so use only
|
||||
* the ES6 features that are supported by your Node version. https://node.green/
|
||||
*/
|
||||
|
||||
// Configuration for your app
|
||||
// https://v2.quasar.dev/quasar-cli-vite/quasar-config-js
|
||||
|
||||
const { configure } = require('quasar/wrappers');
|
||||
|
||||
module.exports = configure(function (/* ctx */) {
|
||||
return {
|
||||
eslint: {
|
||||
// fix: true,
|
||||
// include: [],
|
||||
// exclude: [],
|
||||
// rawOptions: {},
|
||||
warnings: true,
|
||||
errors: true,
|
||||
exclude: ['src/examples/app/protos/*'],
|
||||
},
|
||||
|
||||
// https://v2.quasar.dev/quasar-cli-vite/prefetch-feature
|
||||
// preFetch: true,
|
||||
|
||||
// app boot file (/src/boot)
|
||||
// --> boot files are part of "main.js"
|
||||
// https://v2.quasar.dev/quasar-cli-vite/boot-files
|
||||
boot: ['axios', '@pixi/graphics-extras'],
|
||||
|
||||
// https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#css
|
||||
css: ['app.scss'],
|
||||
|
||||
// https://github.com/quasarframework/quasar/tree/dev/extras
|
||||
extras: [
|
||||
// 'ionicons-v4',
|
||||
// 'mdi-v5',
|
||||
// 'fontawesome-v6',
|
||||
// 'eva-icons',
|
||||
// 'themify',
|
||||
// 'line-awesome',
|
||||
// 'roboto-font-latin-ext', // this or either 'roboto-font', NEVER both!
|
||||
|
||||
'roboto-font', // optional, you are not bound to it
|
||||
'material-icons', // optional, you are not bound to it
|
||||
],
|
||||
|
||||
// Full list of options: https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#build
|
||||
build: {
|
||||
target: {
|
||||
browser: ['es2019', 'edge88', 'firefox78', 'chrome87', 'safari13.1'],
|
||||
node: 'node16',
|
||||
},
|
||||
|
||||
vueRouterMode: 'history', // available values: 'hash', 'history'
|
||||
// vueRouterBase,
|
||||
// vueDevtools,
|
||||
// vueOptionsAPI: false,
|
||||
|
||||
// rebuildCache: true, // rebuilds Vite/linter/etc cache on startup
|
||||
|
||||
// publicPath: '/',
|
||||
// analyze: true,
|
||||
// env: {},
|
||||
// rawDefine: {}
|
||||
// ignorePublicFolder: true,
|
||||
// minify: false,
|
||||
// polyfillModulePreload: true,
|
||||
// distDir
|
||||
|
||||
// extendViteConf (viteConf) {},
|
||||
// viteVuePluginOptions: {},
|
||||
|
||||
// vitePlugins: [
|
||||
// [ 'package-name', { ..options.. } ]
|
||||
// ]
|
||||
},
|
||||
|
||||
// Full list of options: https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#devServer
|
||||
devServer: {
|
||||
// https: true
|
||||
port: 9999,
|
||||
open: false, // opens browser window automatically
|
||||
},
|
||||
|
||||
// https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#framework
|
||||
framework: {
|
||||
config: {
|
||||
notify: {
|
||||
position: 'top',
|
||||
timeout: 2000,
|
||||
progress: true,
|
||||
},
|
||||
},
|
||||
|
||||
// iconSet: 'material-icons', // Quasar icon set
|
||||
lang: 'zh-CN', // Quasar language pack
|
||||
|
||||
// For special cases outside of where the auto-import strategy can have an impact
|
||||
// (like functional components as one of the examples),
|
||||
// you can manually specify Quasar components/directives to be available everywhere:
|
||||
//
|
||||
// components: [],
|
||||
// directives: [],
|
||||
|
||||
// Quasar plugins
|
||||
plugins: ['Notify', 'Dialog', 'Dark', 'AppFullscreen'],
|
||||
},
|
||||
|
||||
// animations: 'all', // --- includes all animations
|
||||
// https://v2.quasar.dev/options/animations
|
||||
animations: [],
|
||||
|
||||
// https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#sourcefiles
|
||||
// sourceFiles: {
|
||||
// rootComponent: 'src/App.vue',
|
||||
// router: 'src/router/index',
|
||||
// store: 'src/store/index',
|
||||
// registerServiceWorker: 'src-pwa/register-service-worker',
|
||||
// serviceWorker: 'src-pwa/custom-service-worker',
|
||||
// pwaManifestFile: 'src-pwa/manifest.json',
|
||||
// electronMain: 'src-electron/electron-main',
|
||||
// electronPreload: 'src-electron/electron-preload'
|
||||
// },
|
||||
|
||||
// https://v2.quasar.dev/quasar-cli-vite/developing-ssr/configuring-ssr
|
||||
ssr: {
|
||||
// ssrPwaHtmlFilename: 'offline.html', // do NOT use index.html as name!
|
||||
// will mess up SSR
|
||||
|
||||
// extendSSRWebserverConf (esbuildConf) {},
|
||||
// extendPackageJson (json) {},
|
||||
|
||||
pwa: false,
|
||||
|
||||
// manualStoreHydration: true,
|
||||
// manualPostHydrationTrigger: true,
|
||||
|
||||
prodPort: 3000, // The default port that the production server should use
|
||||
// (gets superseded if process.env.PORT is specified at runtime)
|
||||
|
||||
middlewares: [
|
||||
'render', // keep this as last one
|
||||
],
|
||||
},
|
||||
|
||||
// https://v2.quasar.dev/quasar-cli-vite/developing-pwa/configuring-pwa
|
||||
pwa: {
|
||||
workboxMode: 'generateSW', // or 'injectManifest'
|
||||
injectPwaMetaTags: true,
|
||||
swFilename: 'sw.js',
|
||||
manifestFilename: 'manifest.json',
|
||||
useCredentialsForManifestTag: false,
|
||||
// useFilenameHashes: true,
|
||||
// extendGenerateSWOptions (cfg) {}
|
||||
// extendInjectManifestOptions (cfg) {},
|
||||
// extendManifestJson (json) {}
|
||||
// extendPWACustomSWConf (esbuildConf) {}
|
||||
},
|
||||
|
||||
// Full list of options: https://v2.quasar.dev/quasar-cli-vite/developing-cordova-apps/configuring-cordova
|
||||
cordova: {
|
||||
// noIosLegacyBuildFlag: true, // uncomment only if you know what you are doing
|
||||
},
|
||||
|
||||
// Full list of options: https://v2.quasar.dev/quasar-cli-vite/developing-capacitor-apps/configuring-capacitor
|
||||
capacitor: {
|
||||
hideSplashscreen: true,
|
||||
},
|
||||
|
||||
// Full list of options: https://v2.quasar.dev/quasar-cli-vite/developing-electron-apps/configuring-electron
|
||||
electron: {
|
||||
// extendElectronMainConf (esbuildConf)
|
||||
// extendElectronPreloadConf (esbuildConf)
|
||||
|
||||
inspectPort: 5858,
|
||||
|
||||
bundler: 'packager', // 'packager' or 'builder'
|
||||
|
||||
packager: {
|
||||
// https://github.com/electron-userland/electron-packager/blob/master/docs/api.md#options
|
||||
// OS X / Mac App Store
|
||||
// appBundleId: '',
|
||||
// appCategoryType: '',
|
||||
// osxSign: '',
|
||||
// protocol: 'myapp://path',
|
||||
// Windows only
|
||||
// win32metadata: { ... }
|
||||
},
|
||||
|
||||
builder: {
|
||||
// https://www.electron.build/configuration/configuration
|
||||
|
||||
appId: 'graphic-pixi',
|
||||
},
|
||||
},
|
||||
|
||||
// Full list of options: https://v2.quasar.dev/quasar-cli-vite/developing-browser-extensions/configuring-bex
|
||||
bex: {
|
||||
contentScripts: ['my-content-script'],
|
||||
|
||||
// extendBexScriptsConf (esbuildConf) {}
|
||||
// extendBexManifestJson (json) {}
|
||||
},
|
||||
};
|
||||
});
|
30
rollup.config.mjs
Normal file
30
rollup.config.mjs
Normal file
@ -0,0 +1,30 @@
|
||||
import typescript from '@rollup/plugin-typescript';
|
||||
|
||||
/**
|
||||
* @type {import('rollup').RollupOptions}
|
||||
*/
|
||||
const config = {
|
||||
input: ['src/index.ts'],
|
||||
output: {
|
||||
dir: 'lib',
|
||||
format: 'esm',
|
||||
},
|
||||
external: [
|
||||
'pixi.js',
|
||||
'pixi-viewport',
|
||||
'@stomp/stompjs',
|
||||
'mqtt',
|
||||
'eventemitter3',
|
||||
'@pixi/graphics-extras',
|
||||
],
|
||||
logLevel: 'debug',
|
||||
plugins: [
|
||||
typescript({
|
||||
declarationDir: 'lib',
|
||||
include: ['src/**/*'],
|
||||
tsconfig: './tsconfig.json',
|
||||
}),
|
||||
],
|
||||
};
|
||||
|
||||
export default config;
|
@ -1,95 +0,0 @@
|
||||
/**
|
||||
* 将proto文件编译到 src/proto/
|
||||
*/
|
||||
const { readdirSync } = require('fs');
|
||||
const { resolve } = require('path');
|
||||
const os = require('os');
|
||||
|
||||
const { exec } = require('child_process');
|
||||
|
||||
const protocDir = resolve(
|
||||
__dirname,
|
||||
'../src/examples/app/app_message/protoc-22.2'
|
||||
);
|
||||
const protoFileDir = resolve(
|
||||
__dirname,
|
||||
'../src/examples/app/app_message/protos'
|
||||
);
|
||||
const destDir = resolve(__dirname, '../src/examples/app/protos');
|
||||
|
||||
/**
|
||||
* 递归处理所有proto文件生成
|
||||
* @param {*} file 文件
|
||||
* @param {*} path 目录
|
||||
*/
|
||||
function recursiveGenerate(file, path = [], cmds = []) {
|
||||
if (file.isFile()) {
|
||||
// 文件,生成
|
||||
if (file.name.endsWith('.proto')) {
|
||||
cmds.push(buildGenerateCmd(file.name, path));
|
||||
} else {
|
||||
console.warn('不是proto文件', file.name);
|
||||
}
|
||||
} else if (file.isDirectory()) {
|
||||
// 文件夹,递归
|
||||
readdirSync(resolve(protoFileDir, ...path, file.name), {
|
||||
withFileTypes: true,
|
||||
}).forEach((f) => {
|
||||
const subPath = [...path, file.name];
|
||||
recursiveGenerate(f, subPath, cmds);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const isLinux = os.type().toLowerCase().includes('linux');
|
||||
|
||||
function buildGenerateCmd(name, path = []) {
|
||||
const protoPath = resolve(protoFileDir, ...path);
|
||||
const tsPath = resolve(destDir, ...path);
|
||||
|
||||
let cmd = ['protoc', `-I=${protoPath}`, `--ts_out=${tsPath}`, `${name}`];
|
||||
let cmdStr = cmd.join(' ');
|
||||
return cmdStr;
|
||||
}
|
||||
|
||||
function main() {
|
||||
const protocBin = resolve(
|
||||
protocDir,
|
||||
`bin/${isLinux ? 'linux-x86_64' : 'win64'}`
|
||||
);
|
||||
const prepareCmds = [];
|
||||
const setPathCmd = isLinux
|
||||
? ['export', `PATH=${protocBin}:${protocDir}:"$PATH"`].join(' ')
|
||||
: ['set', `PATH=${protocBin};${protocDir};%PATH%`].join(' ');
|
||||
const protocVersionCmd = ['protoc', '--version'].join(' ');
|
||||
prepareCmds.push(setPathCmd);
|
||||
prepareCmds.push(protocVersionCmd);
|
||||
|
||||
readdirSync(protoFileDir, {
|
||||
withFileTypes: true,
|
||||
}).forEach((f) => {
|
||||
recursiveGenerate(f, [], prepareCmds);
|
||||
});
|
||||
|
||||
console.log(prepareCmds);
|
||||
|
||||
exec(
|
||||
prepareCmds.join(' && '),
|
||||
{
|
||||
maxBuffer: 1024 * 2000,
|
||||
},
|
||||
(err, stdout, stderr) => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
throw err;
|
||||
} else if (stderr.length > 0) {
|
||||
console.error(stderr.toString());
|
||||
throw new Error(stderr.toString());
|
||||
} else {
|
||||
console.log(stdout);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
main();
|
@ -1,7 +0,0 @@
|
||||
<template>
|
||||
<router-view />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
||||
</script>
|
110
src/app/BasicOperation.ts
Normal file
110
src/app/BasicOperation.ts
Normal file
@ -0,0 +1,110 @@
|
||||
import { GraphicData, JlGraphic } from '../core';
|
||||
import { JlOperation } from '../operation';
|
||||
import { ICanvasProperties, IGraphicApp, IJlCanvas } from './JlGraphicApp';
|
||||
|
||||
/**
|
||||
* 更新画布操作
|
||||
*/
|
||||
export class UpdateCanvasOperation extends JlOperation {
|
||||
obj: IJlCanvas;
|
||||
old: ICanvasProperties;
|
||||
data: ICanvasProperties;
|
||||
description = '';
|
||||
|
||||
constructor(
|
||||
app: IGraphicApp,
|
||||
obj: IJlCanvas,
|
||||
old: ICanvasProperties,
|
||||
data: ICanvasProperties
|
||||
) {
|
||||
super(app, 'update-canvas');
|
||||
this.app = app;
|
||||
this.obj = obj;
|
||||
this.old = old;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
undo(): JlGraphic[] {
|
||||
this.obj.update(this.old);
|
||||
return [];
|
||||
}
|
||||
redo(): JlGraphic[] {
|
||||
this.obj.update(this.data);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 创建图形操作
|
||||
*/
|
||||
export class GraphicCreateOperation extends JlOperation {
|
||||
obj: JlGraphic[];
|
||||
description = '';
|
||||
|
||||
constructor(app: IGraphicApp, obj: JlGraphic[]) {
|
||||
super(app, 'graphic-create');
|
||||
this.app = app;
|
||||
this.obj = obj;
|
||||
}
|
||||
|
||||
undo(): JlGraphic[] | void {
|
||||
this.app.deleteGraphics(...this.obj);
|
||||
}
|
||||
redo(): JlGraphic[] {
|
||||
this.app.addGraphics(...this.obj);
|
||||
return this.obj;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 删除图形操作
|
||||
*/
|
||||
export class GraphicDeleteOperation extends JlOperation {
|
||||
obj: JlGraphic[];
|
||||
|
||||
constructor(app: IGraphicApp, obj: JlGraphic[]) {
|
||||
super(app, 'graphic-delete');
|
||||
this.app = app;
|
||||
this.obj = obj;
|
||||
}
|
||||
|
||||
undo(): JlGraphic[] {
|
||||
this.app.addGraphics(...this.obj);
|
||||
return this.obj;
|
||||
}
|
||||
redo(): void {
|
||||
this.app.deleteGraphics(...this.obj);
|
||||
}
|
||||
}
|
||||
|
||||
export class GraphicDataUpdateOperation extends JlOperation {
|
||||
obj: JlGraphic[];
|
||||
oldData: GraphicData[];
|
||||
newData: GraphicData[];
|
||||
constructor(
|
||||
app: IGraphicApp,
|
||||
obj: JlGraphic[],
|
||||
oldData: GraphicData[],
|
||||
newData: GraphicData[]
|
||||
) {
|
||||
super(app, 'graphic-drag');
|
||||
this.obj = [...obj];
|
||||
this.oldData = oldData;
|
||||
this.newData = newData;
|
||||
}
|
||||
|
||||
undo(): void | JlGraphic[] {
|
||||
for (let i = 0; i < this.obj.length; i++) {
|
||||
const g = this.obj[i];
|
||||
// g.exitChildEdit();
|
||||
g.updateData(this.oldData[i]);
|
||||
}
|
||||
return this.obj;
|
||||
}
|
||||
redo(): void | JlGraphic[] {
|
||||
for (let i = 0; i < this.obj.length; i++) {
|
||||
const g = this.obj[i];
|
||||
// g.exitChildEdit();
|
||||
g.updateData(this.newData[i]);
|
||||
}
|
||||
return this.obj;
|
||||
}
|
||||
}
|
@ -11,7 +11,6 @@ import {
|
||||
} from 'pixi.js';
|
||||
import { GraphicIdGenerator } from '../core/IdGenerator';
|
||||
import { GraphicData, GraphicTemplate, JlGraphic } from '../core/JlGraphic';
|
||||
import { JlOperation } from '../operation/JlOperation';
|
||||
import {
|
||||
AppDragEvent,
|
||||
AppInteractionPlugin,
|
||||
@ -23,12 +22,25 @@ import {
|
||||
} from '../plugins';
|
||||
import { CommonMouseTool } from '../plugins/CommonMousePlugin';
|
||||
import { MenuItemOptions } from '../ui/Menu';
|
||||
import { DOWN, LEFT, RIGHT, UP, recursiveChildren } from '../utils';
|
||||
import {
|
||||
DOWN,
|
||||
DebouncedFunction,
|
||||
LEFT,
|
||||
RIGHT,
|
||||
UP,
|
||||
debounce,
|
||||
recursiveChildren,
|
||||
} from '../utils';
|
||||
import {
|
||||
GraphicDataUpdateOperation,
|
||||
UpdateCanvasOperation,
|
||||
} from './BasicOperation';
|
||||
import {
|
||||
GraphicApp,
|
||||
GraphicAppOptions,
|
||||
ICanvasProperties,
|
||||
JlCanvas,
|
||||
IGraphicApp,
|
||||
IJlCanvas,
|
||||
} from './JlGraphicApp';
|
||||
|
||||
/**
|
||||
@ -39,7 +51,7 @@ export abstract class GraphicDrawAssistant<
|
||||
GD extends GraphicData
|
||||
> extends AppInteractionPlugin {
|
||||
readonly __GraphicDrawAssistant = true;
|
||||
app: JlDrawApp;
|
||||
app: IDrawApp;
|
||||
type: string; // 图形对象类型
|
||||
description: string; // 描述
|
||||
icon: string; // 界面显示的图标
|
||||
@ -58,7 +70,7 @@ export abstract class GraphicDrawAssistant<
|
||||
}
|
||||
|
||||
constructor(
|
||||
graphicApp: JlDrawApp,
|
||||
graphicApp: IDrawApp,
|
||||
graphicTemplate: GT,
|
||||
icon: string,
|
||||
description: string
|
||||
@ -72,12 +84,12 @@ export abstract class GraphicDrawAssistant<
|
||||
this.app.registerGraphicTemplates(this.graphicTemplate);
|
||||
}
|
||||
|
||||
public get canvas(): JlCanvas {
|
||||
public get canvas(): IJlCanvas {
|
||||
return this.app.canvas;
|
||||
}
|
||||
|
||||
bind(): void {
|
||||
this.app._drawing = true;
|
||||
this.app.drawing = true;
|
||||
const canvas = this.canvas;
|
||||
canvas.addChild(this.container);
|
||||
canvas.on('mousedown', this.onLeftDown, this);
|
||||
@ -113,7 +125,7 @@ export abstract class GraphicDrawAssistant<
|
||||
this.app.removeKeyboardListener(this.escListener);
|
||||
|
||||
this.app.viewport.plugins.remove('drag');
|
||||
this.app._drawing = false;
|
||||
this.app.drawing = false;
|
||||
}
|
||||
|
||||
onLeftDown(e: FederatedMouseEvent) {}
|
||||
@ -131,7 +143,7 @@ export abstract class GraphicDrawAssistant<
|
||||
/**
|
||||
* 获取下一个id
|
||||
*/
|
||||
nextId(): string {
|
||||
nextId(): number {
|
||||
return GraphicIdGenerator.next();
|
||||
}
|
||||
|
||||
@ -152,9 +164,7 @@ export abstract class GraphicDrawAssistant<
|
||||
* 保存创建的图形对象
|
||||
*/
|
||||
storeGraphic(...graphics: JlGraphic[]): void {
|
||||
this.app.addGraphics(...graphics);
|
||||
// 创建图形对象操作记录
|
||||
this.app.opRecord.record(new GraphicCreateOperation(this.app, graphics));
|
||||
this.app.addGraphicAndRecord(...graphics);
|
||||
}
|
||||
/**
|
||||
* 创建并添加到图形App
|
||||
@ -189,21 +199,64 @@ export abstract class GraphicDrawAssistant<
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 绘制助手类型
|
||||
*/
|
||||
export type DrawAssistant = GraphicDrawAssistant<GraphicTemplate, GraphicData>;
|
||||
|
||||
export interface IDrawAppOptions {
|
||||
/**
|
||||
* 绘制辅助交互插件
|
||||
/**
|
||||
* 绘制配置选项
|
||||
*/
|
||||
drawAssistants: DrawAssistant[];
|
||||
}
|
||||
export type DrawAppOptions = GraphicAppOptions;
|
||||
|
||||
export type DrawAppOptions = GraphicAppOptions & IDrawAppOptions;
|
||||
/**
|
||||
* 绘制应用接口
|
||||
*/
|
||||
export interface IDrawApp extends IGraphicApp {
|
||||
/**
|
||||
* 是否正在绘制图形
|
||||
*/
|
||||
get drawing(): boolean;
|
||||
/**
|
||||
* 更新绘制中状态
|
||||
*/
|
||||
set drawing(value: boolean);
|
||||
/**
|
||||
* 设置配置选项
|
||||
* @param options
|
||||
*/
|
||||
setOptions(options: DrawAppOptions): void;
|
||||
/**
|
||||
* 获取绘制助手
|
||||
*/
|
||||
getDrawAssistant<DA extends DrawAssistant>(graphicType: string): DA;
|
||||
/**
|
||||
* 更新画布并记录
|
||||
* @param data
|
||||
*/
|
||||
updateCanvasAndRecord(data: ICanvasProperties): void;
|
||||
/**
|
||||
* 更新图形并记录
|
||||
* @param g
|
||||
* @param data
|
||||
*/
|
||||
updateGraphicAndRecord(g: JlGraphic, data: GraphicData): void;
|
||||
/**
|
||||
* 绑定form表单对象
|
||||
* @param form
|
||||
*/
|
||||
bindFormData(form: GraphicData): void;
|
||||
/**
|
||||
* 解绑form表单对象
|
||||
* @param form
|
||||
*/
|
||||
unbindFormData(form: GraphicData): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* 绘制应用
|
||||
*/
|
||||
export class JlDrawApp extends GraphicApp {
|
||||
export class JlDrawApp extends GraphicApp implements IDrawApp {
|
||||
font: BitmapFont = BitmapFont.from(
|
||||
'coordinates',
|
||||
{
|
||||
@ -223,8 +276,17 @@ export class JlDrawApp extends GraphicApp {
|
||||
drawAssistants: DrawAssistant[] = [];
|
||||
_drawing = false;
|
||||
|
||||
constructor(dom: HTMLElement) {
|
||||
super(dom);
|
||||
private debouncedFormDataUpdator: DebouncedFunction<(g: JlGraphic) => void>;
|
||||
|
||||
get drawing(): boolean {
|
||||
return this._drawing;
|
||||
}
|
||||
set drawing(value: boolean) {
|
||||
this._drawing = value;
|
||||
}
|
||||
|
||||
constructor(options: DrawAppOptions) {
|
||||
super(options);
|
||||
|
||||
this.appendDrawStatesDisplay();
|
||||
|
||||
@ -232,11 +294,13 @@ export class JlDrawApp extends GraphicApp {
|
||||
this.appOperationRecord();
|
||||
// 绑定通用键盘操作
|
||||
this.bindKeyboardOperation();
|
||||
this.formDataSyncListen();
|
||||
|
||||
this.debouncedFormDataUpdator = debounce(this.doFormDataUpdate, 60);
|
||||
}
|
||||
|
||||
setOptions(options: DrawAppOptions): void {
|
||||
super.setOptions(options);
|
||||
// this.registerInteractionPlugin(...options.drawAssistants);
|
||||
}
|
||||
|
||||
registerInteractionPlugin(...plugins: InteractionPlugin[]): void {
|
||||
@ -310,8 +374,8 @@ export class JlDrawApp extends GraphicApp {
|
||||
* 绘制状态信息显示
|
||||
*/
|
||||
private appendDrawStatesDisplay(): void {
|
||||
this.app.stage.addChild(this.coordinates);
|
||||
this.app.stage.addChild(this.scaleText);
|
||||
this.pixi.stage.addChild(this.coordinates);
|
||||
this.pixi.stage.addChild(this.scaleText);
|
||||
const bound = this.coordinates.getLocalBounds();
|
||||
this.scaleText.position.set(bound.width + 10, 0);
|
||||
this.canvas.on('mousemove', (e) => {
|
||||
@ -336,7 +400,7 @@ export class JlDrawApp extends GraphicApp {
|
||||
new KeyListener({
|
||||
value: 'KeyA',
|
||||
combinations: [CombinationKey.Ctrl],
|
||||
onPress: (e: KeyboardEvent, app: GraphicApp) => {
|
||||
onPress: (e: KeyboardEvent, app: IGraphicApp) => {
|
||||
if (e.ctrlKey) {
|
||||
(app as JlDrawApp).selectAllGraphics();
|
||||
}
|
||||
@ -349,8 +413,8 @@ export class JlDrawApp extends GraphicApp {
|
||||
new KeyListener({
|
||||
value: 'KeyD',
|
||||
combinations: [CombinationKey.Shift],
|
||||
onPress: (e: KeyboardEvent, app: GraphicApp) => {
|
||||
app.graphicCopyPlugin.init();
|
||||
onPress: (e: KeyboardEvent, app: IGraphicApp) => {
|
||||
this.graphicCopyPlugin.init();
|
||||
},
|
||||
})
|
||||
);
|
||||
@ -360,7 +424,7 @@ export class JlDrawApp extends GraphicApp {
|
||||
value: 'KeyZ',
|
||||
global: true,
|
||||
combinations: [CombinationKey.Ctrl],
|
||||
onPress: (e: KeyboardEvent, app: GraphicApp) => {
|
||||
onPress: (e: KeyboardEvent, app: IGraphicApp) => {
|
||||
app.opRecord.undo();
|
||||
},
|
||||
})
|
||||
@ -371,7 +435,7 @@ export class JlDrawApp extends GraphicApp {
|
||||
value: 'KeyZ',
|
||||
global: true,
|
||||
combinations: [CombinationKey.Ctrl, CombinationKey.Shift],
|
||||
onPress: (e: KeyboardEvent, app: GraphicApp) => {
|
||||
onPress: (e: KeyboardEvent, app: IGraphicApp) => {
|
||||
app.opRecord.redo();
|
||||
},
|
||||
})
|
||||
@ -380,8 +444,8 @@ export class JlDrawApp extends GraphicApp {
|
||||
this.addKeyboardListener(
|
||||
new KeyListener({
|
||||
value: 'Delete',
|
||||
onPress: (e: KeyboardEvent, app: GraphicApp) => {
|
||||
(app as JlDrawApp).deleteSelectedGraphics();
|
||||
onPress: (e: KeyboardEvent, app: IGraphicApp) => {
|
||||
app.deleteGraphicAndRecord(...app.selectedGraphics);
|
||||
},
|
||||
})
|
||||
);
|
||||
@ -389,10 +453,10 @@ export class JlDrawApp extends GraphicApp {
|
||||
new KeyListener({
|
||||
value: 'ArrowUp',
|
||||
pressTriggerAsOriginalEvent: true,
|
||||
onPress: (e: KeyboardEvent, app: GraphicApp) => {
|
||||
onPress: (e: KeyboardEvent, app: IGraphicApp) => {
|
||||
updateGraphicPositionOnKeyboardEvent(app, UP);
|
||||
},
|
||||
onRelease: (e: KeyboardEvent, app: GraphicApp) => {
|
||||
onRelease: (e: KeyboardEvent, app: IGraphicApp) => {
|
||||
recordGraphicMoveOperation(app);
|
||||
},
|
||||
})
|
||||
@ -401,10 +465,10 @@ export class JlDrawApp extends GraphicApp {
|
||||
new KeyListener({
|
||||
value: 'ArrowDown',
|
||||
pressTriggerAsOriginalEvent: true,
|
||||
onPress: (e: KeyboardEvent, app: GraphicApp) => {
|
||||
onPress: (e: KeyboardEvent, app: IGraphicApp) => {
|
||||
updateGraphicPositionOnKeyboardEvent(app, DOWN);
|
||||
},
|
||||
onRelease: (e: KeyboardEvent, app: GraphicApp) => {
|
||||
onRelease: (e: KeyboardEvent, app: IGraphicApp) => {
|
||||
recordGraphicMoveOperation(app);
|
||||
},
|
||||
})
|
||||
@ -413,10 +477,10 @@ export class JlDrawApp extends GraphicApp {
|
||||
new KeyListener({
|
||||
value: 'ArrowLeft',
|
||||
pressTriggerAsOriginalEvent: true,
|
||||
onPress: (e: KeyboardEvent, app: GraphicApp) => {
|
||||
onPress: (e: KeyboardEvent, app: IGraphicApp) => {
|
||||
updateGraphicPositionOnKeyboardEvent(app, LEFT);
|
||||
},
|
||||
onRelease: (e: KeyboardEvent, app: GraphicApp) => {
|
||||
onRelease: (e: KeyboardEvent, app: IGraphicApp) => {
|
||||
recordGraphicMoveOperation(app);
|
||||
},
|
||||
})
|
||||
@ -425,23 +489,16 @@ export class JlDrawApp extends GraphicApp {
|
||||
new KeyListener({
|
||||
value: 'ArrowRight',
|
||||
pressTriggerAsOriginalEvent: true,
|
||||
onPress: (e: KeyboardEvent, app: GraphicApp) => {
|
||||
onPress: (e: KeyboardEvent, app: IGraphicApp) => {
|
||||
updateGraphicPositionOnKeyboardEvent(app, RIGHT);
|
||||
},
|
||||
onRelease: (e: KeyboardEvent, app: GraphicApp) => {
|
||||
onRelease: (e: KeyboardEvent, app: IGraphicApp) => {
|
||||
recordGraphicMoveOperation(app);
|
||||
},
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 全选
|
||||
*/
|
||||
selectAllGraphics() {
|
||||
this.updateSelected(...this.queryStore.getAllGraphics());
|
||||
}
|
||||
|
||||
/**
|
||||
* 图形对象存储处理,默认添加图形交互
|
||||
* @param graphic
|
||||
@ -450,18 +507,60 @@ export class JlDrawApp extends GraphicApp {
|
||||
graphic.eventMode = 'static';
|
||||
graphic.selectable = true;
|
||||
graphic.draggable = true;
|
||||
graphic.on('repaint', () => {
|
||||
this.handleFormDataUpdate(graphic);
|
||||
});
|
||||
graphic.on('transformend', () => {
|
||||
this.handleFormDataUpdate(graphic);
|
||||
});
|
||||
}
|
||||
|
||||
formData: GraphicData | undefined = undefined;
|
||||
|
||||
/**
|
||||
* 绑定form表单对象
|
||||
* @param form
|
||||
*/
|
||||
bindFormData(form: GraphicData): void {
|
||||
this.formData = form;
|
||||
if (this.formData && this.selectedGraphics.length == 1) {
|
||||
if (this.formData.graphicType == this.selectedGraphics[0].type) {
|
||||
this.formData.copyFrom(this.selectedGraphics[0].saveData());
|
||||
} else {
|
||||
this.formData = undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除选中图形对象
|
||||
* 移除form绑定
|
||||
* @param form
|
||||
*/
|
||||
deleteSelectedGraphics() {
|
||||
const deletes = this.deleteGraphics(...this.selectedGraphics);
|
||||
if (deletes.length > 0) {
|
||||
// 删除图形对象操作记录
|
||||
this.opRecord.record(new GraphicDeleteOperation(this, deletes));
|
||||
} else {
|
||||
console.debug('没有删除元素,不记录');
|
||||
unbindFormData(form: GraphicData): void {
|
||||
if (this.formData == form) {
|
||||
this.formData = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
private formDataSyncListen(): void {
|
||||
this.on('graphicselected', () => {
|
||||
if (this.selectedGraphics.length == 1) {
|
||||
this.handleFormDataUpdate(this.selectedGraphics[0]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理表单数据更新(使用debounce限流)
|
||||
*/
|
||||
private handleFormDataUpdate(g: JlGraphic): void {
|
||||
this.debouncedFormDataUpdator(this, g);
|
||||
}
|
||||
|
||||
private doFormDataUpdate(g: JlGraphic): void {
|
||||
if (this.selectedGraphics.length > 1) return;
|
||||
if (this.formData && g.type === this.formData.graphicType) {
|
||||
this.formData.copyFrom(g.saveData());
|
||||
}
|
||||
}
|
||||
|
||||
@ -487,7 +586,7 @@ export class JlDrawApp extends GraphicApp {
|
||||
let dragStartDatas: GraphicData[] = [];
|
||||
|
||||
function handleArrowKeyMoveGraphics(
|
||||
app: GraphicApp,
|
||||
app: IGraphicApp,
|
||||
handler: (obj: DisplayObject) => void
|
||||
) {
|
||||
if (
|
||||
@ -506,7 +605,10 @@ function handleArrowKeyMoveGraphics(
|
||||
}
|
||||
}
|
||||
|
||||
function updateGraphicPositionOnKeyboardEvent(app: GraphicApp, dp: IPointData) {
|
||||
function updateGraphicPositionOnKeyboardEvent(
|
||||
app: IGraphicApp,
|
||||
dp: IPointData
|
||||
) {
|
||||
let dragStart = false;
|
||||
if (dragStartDatas.length === 0) {
|
||||
dragStartDatas = app.selectedGraphics.map((g) => g.saveData());
|
||||
@ -541,7 +643,7 @@ function updateGraphicPositionOnKeyboardEvent(app: GraphicApp, dp: IPointData) {
|
||||
}
|
||||
});
|
||||
}
|
||||
function recordGraphicMoveOperation(app: GraphicApp) {
|
||||
function recordGraphicMoveOperation(app: IGraphicApp) {
|
||||
if (
|
||||
dragStartDatas.length > 0 &&
|
||||
dragStartDatas.length === app.selectedGraphics.length
|
||||
@ -570,110 +672,3 @@ function recordGraphicMoveOperation(app: GraphicApp) {
|
||||
}
|
||||
dragStartDatas = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新画布操作
|
||||
*/
|
||||
export class UpdateCanvasOperation extends JlOperation {
|
||||
obj: JlCanvas;
|
||||
old: ICanvasProperties;
|
||||
data: ICanvasProperties;
|
||||
description = '';
|
||||
|
||||
constructor(
|
||||
app: GraphicApp,
|
||||
obj: JlCanvas,
|
||||
old: ICanvasProperties,
|
||||
data: ICanvasProperties
|
||||
) {
|
||||
super(app, 'update-canvas');
|
||||
this.app = app;
|
||||
this.obj = obj;
|
||||
this.old = old;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
undo(): JlGraphic[] {
|
||||
this.obj.update(this.old);
|
||||
return [];
|
||||
}
|
||||
redo(): JlGraphic[] {
|
||||
this.obj.update(this.data);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 创建图形操作
|
||||
*/
|
||||
export class GraphicCreateOperation extends JlOperation {
|
||||
obj: JlGraphic[];
|
||||
description = '';
|
||||
|
||||
constructor(app: GraphicApp, obj: JlGraphic[]) {
|
||||
super(app, 'graphic-create');
|
||||
this.app = app;
|
||||
this.obj = obj;
|
||||
}
|
||||
|
||||
undo(): JlGraphic[] | void {
|
||||
this.app.deleteGraphics(...this.obj);
|
||||
}
|
||||
redo(): JlGraphic[] {
|
||||
this.app.addGraphics(...this.obj);
|
||||
return this.obj;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 删除图形操作
|
||||
*/
|
||||
export class GraphicDeleteOperation extends JlOperation {
|
||||
obj: JlGraphic[];
|
||||
|
||||
constructor(app: GraphicApp, obj: JlGraphic[]) {
|
||||
super(app, 'graphic-delete');
|
||||
this.app = app;
|
||||
this.obj = obj;
|
||||
}
|
||||
|
||||
undo(): JlGraphic[] {
|
||||
this.app.addGraphics(...this.obj);
|
||||
return this.obj;
|
||||
}
|
||||
redo(): void {
|
||||
this.app.deleteGraphics(...this.obj);
|
||||
}
|
||||
}
|
||||
|
||||
export class GraphicDataUpdateOperation extends JlOperation {
|
||||
obj: JlGraphic[];
|
||||
oldData: GraphicData[];
|
||||
newData: GraphicData[];
|
||||
constructor(
|
||||
app: GraphicApp,
|
||||
obj: JlGraphic[],
|
||||
oldData: GraphicData[],
|
||||
newData: GraphicData[]
|
||||
) {
|
||||
super(app, 'graphic-drag');
|
||||
this.obj = [...obj];
|
||||
this.oldData = oldData;
|
||||
this.newData = newData;
|
||||
}
|
||||
|
||||
undo(): void | JlGraphic[] {
|
||||
for (let i = 0; i < this.obj.length; i++) {
|
||||
const g = this.obj[i];
|
||||
// g.exitChildEdit();
|
||||
g.updateData(this.oldData[i]);
|
||||
}
|
||||
return this.obj;
|
||||
}
|
||||
redo(): void | JlGraphic[] {
|
||||
for (let i = 0; i < this.obj.length; i++) {
|
||||
const g = this.obj[i];
|
||||
// g.exitChildEdit();
|
||||
g.updateData(this.newData[i]);
|
||||
}
|
||||
return this.obj;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,49 @@
|
||||
import {
|
||||
DrawAppOptions,
|
||||
DrawAssistant,
|
||||
GraphicDrawAssistant,
|
||||
IDrawApp,
|
||||
JlDrawApp,
|
||||
} from './JlDrawApp';
|
||||
import {
|
||||
AppConsts,
|
||||
GraphicApp,
|
||||
GraphicAppOptions,
|
||||
ICanvasProperties,
|
||||
IGraphicApp,
|
||||
IGraphicScene,
|
||||
IGraphicStorage,
|
||||
IJlCanvas,
|
||||
IGridBackground
|
||||
} from './JlGraphicApp';
|
||||
import { GraphicDataUpdateOperation } from './BasicOperation';
|
||||
|
||||
/**
|
||||
* 实例化图形app
|
||||
* @param options
|
||||
* @returns
|
||||
*/
|
||||
export function newGraphicApp(options: GraphicAppOptions): IGraphicApp {
|
||||
return new GraphicApp(options);
|
||||
}
|
||||
|
||||
/**
|
||||
* 实例化绘图app
|
||||
* @param options
|
||||
* @returns
|
||||
*/
|
||||
export function newDrawApp(options: DrawAppOptions): IDrawApp {
|
||||
return new JlDrawApp(options);
|
||||
}
|
||||
|
||||
export { AppConsts, GraphicDrawAssistant, GraphicDataUpdateOperation };
|
||||
export type {
|
||||
DrawAssistant,
|
||||
ICanvasProperties,
|
||||
IDrawApp,
|
||||
IGraphicApp,
|
||||
IGraphicScene,
|
||||
IGraphicStorage,
|
||||
IJlCanvas,
|
||||
IGridBackground
|
||||
};
|
@ -1,15 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 356 360">
|
||||
<path
|
||||
d="M43.4 303.4c0 3.8-2.3 6.3-7.1 6.3h-15v-22h14.4c4.3 0 6.2 2.2 6.2 5.2 0 2.6-1.5 4.4-3.4 5 2.8.4 4.9 2.5 4.9 5.5zm-8-13H24.1v6.9H35c2.1 0 4-1.3 4-3.8 0-2.2-1.3-3.1-3.7-3.1zm5.1 12.6c0-2.3-1.8-3.7-4-3.7H24.2v7.7h11.7c3.4 0 4.6-1.8 4.6-4zm36.3 4v2.7H56v-22h20.6v2.7H58.9v6.8h14.6v2.3H58.9v7.5h17.9zm23-5.8v8.5H97v-8.5l-11-13.4h3.4l8.9 11 8.8-11h3.4l-10.8 13.4zm19.1-1.8V298c0-7.9 5.2-10.7 12.7-10.7 7.5 0 13 2.8 13 10.7v1.4c0 7.9-5.5 10.8-13 10.8s-12.7-3-12.7-10.8zm22.7 0V298c0-5.7-3.9-8-10-8-6 0-9.8 2.3-9.8 8v1.4c0 5.8 3.8 8.1 9.8 8.1 6 0 10-2.3 10-8.1zm37.2-11.6v21.9h-2.9l-15.8-17.9v17.9h-2.8v-22h3l15.6 18v-18h2.9zm37.9 10.2v1.3c0 7.8-5.2 10.4-12.4 10.4H193v-22h11.2c7.2 0 12.4 2.8 12.4 10.3zm-3 0c0-5.3-3.3-7.6-9.4-7.6h-8.4V307h8.4c6 0 9.5-2 9.5-7.7V298zm50.8-7.6h-9.7v19.3h-3v-19.3h-9.7v-2.6h22.4v2.6zm34.4-2.6v21.9h-3v-10.1h-16.8v10h-2.8v-21.8h2.8v9.2H296v-9.2h2.9zm34.9 19.2v2.7h-20.7v-22h20.6v2.7H316v6.8h14.5v2.3H316v7.5h17.8zM24 340.2v7.3h13.9v2.4h-14v9.6H21v-22h20v2.7H24zm41.5 11.4h-9.8v7.9H53v-22h13.3c5.1 0 8 1.9 8 6.8 0 3.7-2 6.3-5.6 7l6 8.2h-3.3l-5.8-8zm-9.8-2.6H66c3.1 0 5.3-1.5 5.3-4.7 0-3.3-2.2-4.1-5.3-4.1H55.7v8.8zm47.9 6.2H89l-2 4.3h-3.2l10.7-22.2H98l10.7 22.2h-3.2l-2-4.3zm-1-2.3l-6.3-13-6 13h12.2zm46.3-15.3v21.9H146v-17.2L135.7 358h-2.1l-10.2-15.6v17h-2.8v-21.8h3l11 16.9 11.3-17h3zm35 19.3v2.6h-20.7v-22h20.6v2.7H166v6.8h14.5v2.3H166v7.6h17.8zm47-19.3l-8.3 22h-3l-7.1-18.6-7 18.6h-3l-8.2-22h3.3L204 356l6.8-18.5h3.4L221 356l6.6-18.5h3.3zm10 11.6v-1.4c0-7.8 5.2-10.7 12.7-10.7 7.6 0 13 2.9 13 10.7v1.4c0 7.9-5.4 10.8-13 10.8-7.5 0-12.7-3-12.7-10.8zm22.8 0v-1.4c0-5.7-4-8-10-8s-9.9 2.3-9.9 8v1.4c0 5.8 3.8 8.2 9.8 8.2 6.1 0 10-2.4 10-8.2zm28.3 2.4h-9.8v7.9h-2.8v-22h13.2c5.2 0 8 1.9 8 6.8 0 3.7-2 6.3-5.6 7l6 8.2h-3.3l-5.8-8zm-9.8-2.6h10.2c3 0 5.2-1.5 5.2-4.7 0-3.3-2.1-4.1-5.2-4.1h-10.2v8.8zm40.3-1.5l-6.8 5.6v6.4h-2.9v-22h2.9v12.3l15.2-12.2h3.7l-9.9 8.1 10.3 13.8h-3.6l-8.9-12z" />
|
||||
<path fill="#050A14"
|
||||
d="M188.4 71.7a10.4 10.4 0 01-20.8 0 10.4 10.4 0 1120.8 0zM224.2 45c-2.2-3.9-5-7.5-8.2-10.7l-12 7c-3.7-3.2-8-5.7-12.6-7.3a49.4 49.4 0 00-9.7 13.9 59 59 0 0140.1 14l7.6-4.4a57 57 0 00-5.2-12.5zM178 125.1c4.5 0 9-.6 13.4-1.7v-14a40 40 0 0012.5-7.2 47.7 47.7 0 00-7.1-15.3 59 59 0 01-32.2 27.7v8.7c4.4 1.2 8.9 1.8 13.4 1.8zM131.8 45c-2.3 4-4 8.1-5.2 12.5l12 7a40 40 0 000 14.4c5.7 1.5 11.3 2 16.9 1.5a59 59 0 01-8-41.7l-7.5-4.3c-3.2 3.2-6 6.7-8.2 10.6z" />
|
||||
<path fill="#00B4FF"
|
||||
d="M224.2 98.4c2.3-3.9 4-8 5.2-12.4l-12-7a40 40 0 000-14.5c-5.7-1.5-11.3-2-16.9-1.5a59 59 0 018 41.7l7.5 4.4c3.2-3.2 6-6.8 8.2-10.7zm-92.4 0c2.2 4 5 7.5 8.2 10.7l12-7a40 40 0 0012.6 7.3c4-4.1 7.3-8.8 9.7-13.8a59 59 0 01-40-14l-7.7 4.4c1.2 4.3 3 8.5 5.2 12.4zm46.2-80c-4.5 0-9 .5-13.4 1.7V34a40 40 0 00-12.5 7.2c1.5 5.7 4 10.8 7.1 15.4a59 59 0 0132.2-27.7V20a53.3 53.3 0 00-13.4-1.8z" />
|
||||
<path fill="#00B4FF"
|
||||
d="M178 9.2a62.6 62.6 0 11-.1 125.2A62.6 62.6 0 01178 9.2m0-9.2a71.7 71.7 0 100 143.5A71.7 71.7 0 00178 0z" />
|
||||
<path fill="#050A14"
|
||||
d="M96.6 212v4.3c-9.2-.8-15.4-5.8-15.4-17.8V180h4.6v18.4c0 8.6 4 12.6 10.8 13.5zm16-31.9v18.4c0 8.9-4.3 12.8-10.9 13.5v4.4c9.2-.7 15.5-5.6 15.5-18v-18.3h-4.7zM62.2 199v-2.2c0-12.7-8.8-17.4-21-17.4-12.1 0-20.7 4.7-20.7 17.4v2.2c0 12.8 8.6 17.6 20.7 17.6 1.5 0 3-.1 4.4-.3l11.8 6.2 2-3.3-8.2-4-6.4-3.1a32 32 0 01-3.6.2c-9.8 0-16-3.9-16-13.3v-2.2c0-9.3 6.2-13.1 16-13.1 9.9 0 16.3 3.8 16.3 13.1v2.2c0 5.3-2.1 8.7-5.6 10.8l4.8 2.4c3.4-2.8 5.5-7 5.5-13.2zM168 215.6h5.1L156 179.7h-4.8l17 36zM143 205l7.4-15.7-2.4-5-15.1 31.4h5.1l3.3-7h18.3l-1.8-3.7H143zm133.7 10.7h5.2l-17.3-35.9h-4.8l17 36zm-25-10.7l7.4-15.7-2.4-5-15.1 31.4h5.1l3.3-7h18.3l-1.7-3.7h-14.8zm73.8-2.5c6-1.2 9-5.4 9-11.4 0-8-4.5-10.9-12.9-10.9h-21.4v35.5h4.6v-31.3h16.5c5 0 8.5 1.4 8.5 6.7 0 5.2-3.5 7.7-8.5 7.7h-11.4v4.1h10.7l9.3 12.8h5.5l-9.9-13.2zm-117.4 9.9c-9.7 0-14.7-2.5-18.6-6.3l-2.2 3.8c5.1 5 11 6.7 21 6.7 1.6 0 3.1-.1 4.6-.3l-1.9-4h-3zm18.4-7c0-6.4-4.7-8.6-13.8-9.4l-10.1-1c-6.7-.7-9.3-2.2-9.3-5.6 0-2.5 1.4-4 4.6-5l-1.8-3.8c-4.7 1.4-7.5 4.2-7.5 8.9 0 5.2 3.4 8.7 13 9.6l11.3 1.2c6.4.6 8.9 2 8.9 5.4 0 2.7-2.1 4.7-6 5.8l1.8 3.9c5.3-1.6 8.9-4.7 8.9-10zm-20.3-21.9c7.9 0 13.3 1.8 18.1 5.7l1.8-3.9a30 30 0 00-19.6-5.9c-2 0-4 .1-5.7.3l1.9 4 3.5-.2z" />
|
||||
<path fill="#00B4FF"
|
||||
d="M.5 251.9c29.6-.5 59.2-.8 88.8-1l88.7-.3 88.7.3 44.4.4 44.4.6-44.4.6-44.4.4-88.7.3-88.7-.3a7981 7981 0 01-88.8-1z" />
|
||||
<path fill="none" d="M-565.2 324H-252v15.8h-313.2z" />
|
||||
</svg>
|
Before Width: | Height: | Size: 4.4 KiB |
@ -1,7 +0,0 @@
|
||||
import { boot } from 'quasar/wrappers';
|
||||
import * as GraphicsExtras from '@pixi/graphics-extras';
|
||||
// "async" is optional;
|
||||
// more info on params: https://v2.quasar.dev/quasar-cli/boot-files
|
||||
export default boot(async (/* { app, router, ... } */) => {
|
||||
GraphicsExtras;
|
||||
});
|
@ -1,111 +0,0 @@
|
||||
import axios, { AxiosInstance } from 'axios';
|
||||
import { AxiosError } from 'axios';
|
||||
import { Dialog } from 'quasar';
|
||||
import { boot } from 'quasar/wrappers';
|
||||
import { getJwtToken } from 'src/examples/app/configs/TokenManage';
|
||||
import { getHttpBase } from 'src/examples/app/configs/UrlManage';
|
||||
|
||||
declare module '@vue/runtime-core' {
|
||||
interface ComponentCustomProperties {
|
||||
$axios: AxiosInstance;
|
||||
}
|
||||
}
|
||||
|
||||
interface ErrorData {
|
||||
status: number;
|
||||
title: string;
|
||||
detail: string;
|
||||
code: number;
|
||||
}
|
||||
|
||||
export class ApiError {
|
||||
origin: AxiosError;
|
||||
/**
|
||||
* 业务错误代码
|
||||
*/
|
||||
code: number;
|
||||
/**
|
||||
* 错误信息
|
||||
*/
|
||||
title: string;
|
||||
/**
|
||||
* 相关问题描述
|
||||
*/
|
||||
detail?: string;
|
||||
constructor(origin: AxiosError<unknown, unknown>) {
|
||||
this.origin = origin;
|
||||
const response = origin.response;
|
||||
if (response) {
|
||||
const err = response.data as ErrorData;
|
||||
this.code = err.code;
|
||||
this.title = err.title;
|
||||
this.detail = err.detail;
|
||||
} else {
|
||||
this.code = origin.status || -1;
|
||||
this.title = origin.message;
|
||||
}
|
||||
}
|
||||
|
||||
static from(err: AxiosError<unknown, unknown>): ApiError {
|
||||
return new ApiError(err);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否认证失败(登录过期)
|
||||
* @returns
|
||||
*/
|
||||
isAuthError(): boolean {
|
||||
return this.origin.response?.status === 401;
|
||||
}
|
||||
}
|
||||
|
||||
// Be careful when using SSR for cross-request state pollution
|
||||
// due to creating a Singleton instance here;
|
||||
// If any client changes this (global) instance, it might be a
|
||||
// good idea to move this instance creation inside of the
|
||||
// "export default () => {}" function below (which runs individually
|
||||
// for each client)
|
||||
const api = axios.create({ baseURL: getHttpBase() });
|
||||
|
||||
export default boot(({ app, router }) => {
|
||||
// for use inside Vue files (Options API) through this.$axios and this.$api
|
||||
|
||||
// 拦截请求,添加
|
||||
api.interceptors.request.use(
|
||||
(config) => {
|
||||
config.headers.Authorization = getJwtToken();
|
||||
return config;
|
||||
},
|
||||
(err: AxiosError) => {
|
||||
return Promise.reject(ApiError.from(err));
|
||||
}
|
||||
);
|
||||
|
||||
api.interceptors.response.use(
|
||||
(response) => {
|
||||
return response;
|
||||
},
|
||||
(err) => {
|
||||
if (err.response && err.response.status === 401) {
|
||||
Dialog.create({
|
||||
title: '认证失败',
|
||||
message: '认证失败或登录超时,请重新登录',
|
||||
persistent: true,
|
||||
}).onOk(() => {
|
||||
router.push({ name: 'login' });
|
||||
});
|
||||
}
|
||||
return Promise.reject(ApiError.from(err));
|
||||
}
|
||||
);
|
||||
|
||||
app.config.globalProperties.$axios = axios;
|
||||
// ^ ^ ^ this will allow you to use this.$axios (for Vue Options API form)
|
||||
// so you won't necessarily have to import axios in each vue file
|
||||
|
||||
app.config.globalProperties.$api = api;
|
||||
// ^ ^ ^ this will allow you to use this.$api (for Vue Options API form)
|
||||
// so you can easily perform requests against your app's API
|
||||
});
|
||||
|
||||
export { api };
|
@ -1,34 +0,0 @@
|
||||
<template>
|
||||
<q-item
|
||||
clickable
|
||||
tag="a"
|
||||
target="_blank"
|
||||
:href="link"
|
||||
>
|
||||
<q-item-section
|
||||
v-if="icon"
|
||||
avatar
|
||||
>
|
||||
<q-icon :name="icon" />
|
||||
</q-item-section>
|
||||
|
||||
<q-item-section>
|
||||
<q-item-label>{{ title }}</q-item-label>
|
||||
<q-item-label caption>{{ caption }}</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
export interface EssentialLinkProps {
|
||||
title: string;
|
||||
caption?: string;
|
||||
link?: string;
|
||||
icon?: string;
|
||||
}
|
||||
withDefaults(defineProps<EssentialLinkProps>(), {
|
||||
caption: '',
|
||||
link: '#',
|
||||
icon: '',
|
||||
});
|
||||
</script>
|
@ -1,37 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<p>{{ title }}</p>
|
||||
<ul>
|
||||
<li v-for="todo in todos" :key="todo.id" @click="increment">
|
||||
{{ todo.id }} - {{ todo.content }}
|
||||
</li>
|
||||
</ul>
|
||||
<p>Count: {{ todoCount }} / {{ meta.totalCount }}</p>
|
||||
<p>Active: {{ active ? 'yes' : 'no' }}</p>
|
||||
<p>Clicks on todos: {{ clickCount }}</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from 'vue';
|
||||
import { Todo, Meta } from './models';
|
||||
|
||||
interface Props {
|
||||
title: string;
|
||||
todos?: Todo[];
|
||||
meta: Meta;
|
||||
active: boolean;
|
||||
}
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
todos: () => [],
|
||||
});
|
||||
|
||||
const clickCount = ref(0);
|
||||
function increment() {
|
||||
clickCount.value += 1;
|
||||
return clickCount.value;
|
||||
}
|
||||
|
||||
const todoCount = computed(() => props.todos.length);
|
||||
|
||||
</script>
|
@ -1,92 +0,0 @@
|
||||
<template>
|
||||
<!-- 绘制图形模板属性 -->
|
||||
<div v-if="drawStore.drawMode">
|
||||
<q-card flat>
|
||||
<q-card-section>
|
||||
<div class="text-h6">{{ drawStore.drawGraphicName + ' 模板' }}</div>
|
||||
</q-card-section>
|
||||
<q-separator inset></q-separator>
|
||||
<q-card-section>
|
||||
<template v-if="drawStore.drawGraphicType === Link.Type">
|
||||
<link-template></link-template>
|
||||
</template>
|
||||
<template v-if="drawStore.drawGraphicType === Rect.Type">
|
||||
<rect-template></rect-template>
|
||||
</template>
|
||||
<template v-if="drawStore.drawGraphicType === Platform.Type">
|
||||
<platform-template></platform-template>
|
||||
</template>
|
||||
<template v-if="drawStore.drawGraphicType === Station.Type">
|
||||
<station-template></station-template>
|
||||
</template>
|
||||
<template v-if="drawStore.drawGraphicType === Train.Type">
|
||||
<TrainProperty></TrainProperty>
|
||||
</template>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</div>
|
||||
<!-- 画布或图形对象属性 -->
|
||||
<div v-else-if="drawStore.selectedGraphics !== null">
|
||||
<q-card flat>
|
||||
<q-card-section>
|
||||
<div class="text-h6">{{ drawStore.selectedObjName + ' 属性' }}</div>
|
||||
</q-card-section>
|
||||
<q-separator inset></q-separator>
|
||||
<template v-if="drawStore.selectedGraphics.length === 0">
|
||||
<q-card-section>
|
||||
<canvas-property></canvas-property>
|
||||
</q-card-section>
|
||||
</template>
|
||||
<template v-else-if="drawStore.selectedGraphics.length === 1">
|
||||
<q-card-section>
|
||||
<link-property
|
||||
v-if="drawStore.selectedGraphicType === Link.Type"
|
||||
></link-property>
|
||||
<rect-property
|
||||
v-if="drawStore.selectedGraphicType === Rect.Type"
|
||||
></rect-property>
|
||||
<platform-property
|
||||
v-if="drawStore.selectedGraphicType === Platform.Type"
|
||||
></platform-property>
|
||||
<station-property
|
||||
v-if="drawStore.selectedGraphicType === Station.Type"
|
||||
></station-property>
|
||||
<train-property
|
||||
v-if="drawStore.selectedGraphicType === Train.Type"
|
||||
></train-property>
|
||||
<iscs-fan-property
|
||||
v-else-if="drawStore.selectedGraphicType === IscsFan.Type"
|
||||
></iscs-fan-property>
|
||||
<signal-property
|
||||
v-else-if="drawStore.selectedGraphicType === Signal.Type"
|
||||
></signal-property>
|
||||
</q-card-section>
|
||||
</template>
|
||||
</q-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import LinkTemplate from './templates/LinkTemplate.vue';
|
||||
import RectTemplate from './templates/RectTemplate.vue';
|
||||
import PlatformTemplate from './templates/PlatformTemplate.vue';
|
||||
import StationTemplate from './templates/StationTemplate.vue';
|
||||
import CanvasProperty from './properties/CanvasProperty.vue';
|
||||
import LinkProperty from './properties/LinkProperty.vue';
|
||||
import RectProperty from './properties/RectProperty.vue';
|
||||
import PlatformProperty from './properties/PlatformProperty.vue';
|
||||
import StationProperty from './properties/StationProperty.vue';
|
||||
import TrainProperty from './properties/TrainProperty.vue';
|
||||
import IscsFanProperty from './properties/IscsFanProperty.vue';
|
||||
import SignalProperty from './properties/SignalProperty.vue';
|
||||
import { Link } from 'src/graphics/link/Link';
|
||||
import { Rect } from 'src/graphics/rect/Rect';
|
||||
import { Platform } from 'src/graphics/platform/Platform';
|
||||
import { Station } from 'src/graphics/station/Station';
|
||||
import { Train } from 'src/graphics/train/Train';
|
||||
import { useDrawStore } from 'src/stores/draw-store';
|
||||
import { IscsFan } from 'src/graphics/iscs-fan/IscsFan';
|
||||
import { Signal } from 'src/graphics/signal/Signal';
|
||||
|
||||
const drawStore = useDrawStore();
|
||||
</script>
|
@ -1,74 +0,0 @@
|
||||
<template>
|
||||
<q-form>
|
||||
<q-input
|
||||
outlined
|
||||
v-model.number="canvas.width"
|
||||
@blur="onUpdate"
|
||||
label="画布宽 *"
|
||||
lazy-rules
|
||||
:rules="[(val) => (val && val > 0) || '画布宽必须大于0']"
|
||||
/>
|
||||
|
||||
<q-input
|
||||
outlined
|
||||
type="number"
|
||||
v-model.number="canvas.height"
|
||||
@blur="onUpdate"
|
||||
label="画布高 *"
|
||||
lazy-rules
|
||||
:rules="[(val) => val > 0 || '画布高必须大于0']"
|
||||
/>
|
||||
|
||||
<q-input
|
||||
outlined
|
||||
v-model="canvas.backgroundColor"
|
||||
@blur="onUpdate"
|
||||
label="画布背景色 *"
|
||||
lazy-rules
|
||||
:rules="[(val) => (val && val.length > 0) || '画布背景色必须设置']"
|
||||
>
|
||||
<template v-slot:append>
|
||||
<q-icon name="colorize" class="cursor-pointer">
|
||||
<q-popup-proxy cover transition-show="scale" transition-hide="scale">
|
||||
<q-color
|
||||
:model-value="canvas.backgroundColor"
|
||||
@change="
|
||||
(val) => {
|
||||
canvas.backgroundColor = val;
|
||||
onUpdate();
|
||||
}
|
||||
"
|
||||
/>
|
||||
</q-popup-proxy>
|
||||
</q-icon>
|
||||
</template>
|
||||
</q-input>
|
||||
</q-form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useDrawStore } from 'src/stores/draw-store';
|
||||
import { onMounted, onUnmounted, reactive } from 'vue';
|
||||
const drawStore = useDrawStore();
|
||||
|
||||
const canvas = reactive({
|
||||
width: 1920,
|
||||
height: 1080,
|
||||
backgroundColor: '#ffffff',
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
const jc = drawStore.getJlCanvas();
|
||||
canvas.width = jc.properties.width;
|
||||
canvas.height = jc.properties.height;
|
||||
canvas.backgroundColor = jc.properties.backgroundColor;
|
||||
});
|
||||
|
||||
function onUpdate() {
|
||||
const app = drawStore.getDrawApp();
|
||||
app.updateCanvasAndRecord({
|
||||
...canvas,
|
||||
viewportTransform: app.canvas.properties.viewportTransform,
|
||||
});
|
||||
}
|
||||
</script>
|
@ -1,42 +0,0 @@
|
||||
<template>
|
||||
<q-form>
|
||||
<q-input outlined readonly v-model="model.id" label="id" :rules="[]" />
|
||||
</q-form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { IscsFanData } from 'src/examples/app/graphics/IscsFanInteraction';
|
||||
import { IscsFan } from 'src/graphics/iscs-fan/IscsFan';
|
||||
import { useDrawStore } from 'src/stores/draw-store';
|
||||
import { onMounted, reactive, watch } from 'vue';
|
||||
|
||||
const drawStore = useDrawStore();
|
||||
const model = reactive(new IscsFanData());
|
||||
|
||||
drawStore.$subscribe;
|
||||
watch(
|
||||
() => drawStore.selectedGraphic,
|
||||
(val) => {
|
||||
if (val && val.type == IscsFan.Type) {
|
||||
// console.log('Iscs风机变更');
|
||||
model.copyFrom(val.saveData() as IscsFanData);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
// console.log('Iscs风机 属性表单 mounted');
|
||||
const g = drawStore.selectedGraphic as IscsFan;
|
||||
if (g) {
|
||||
model.copyFrom(g.saveData());
|
||||
}
|
||||
});
|
||||
|
||||
function onUpdate() {
|
||||
console.log('Iscs风机 属性更新');
|
||||
const g = drawStore.selectedGraphic as IscsFan;
|
||||
if (g) {
|
||||
drawStore.getDrawApp().updateGraphicAndRecord(g, model);
|
||||
}
|
||||
}
|
||||
</script>
|
@ -1,96 +0,0 @@
|
||||
<template>
|
||||
<q-form>
|
||||
<q-input outlined readonly v-model="linkModel.id" label="id" hint="" />
|
||||
<q-input
|
||||
outlined
|
||||
v-model.number="linkModel.lineWidth"
|
||||
type="number"
|
||||
@blur="onUpdate"
|
||||
label="线宽"
|
||||
lazy-rules
|
||||
:rules="[(val) => (val && val > 0) || '画布宽必须大于0']"
|
||||
/>
|
||||
|
||||
<q-input
|
||||
outlined
|
||||
v-model="linkModel.lineColor"
|
||||
@blur="onUpdate"
|
||||
label="线色"
|
||||
lazy-rules
|
||||
:rules="[(val) => (val && val.length > 0) || '线色不能为空']"
|
||||
>
|
||||
<template v-slot:append>
|
||||
<q-icon name="colorize" class="cursor-pointer">
|
||||
<q-popup-proxy cover transition-show="scale" transition-hide="scale">
|
||||
<q-color
|
||||
v-model="linkModel.lineColor"
|
||||
@change="
|
||||
(val) => {
|
||||
linkModel.lineColor = val;
|
||||
onUpdate();
|
||||
}
|
||||
"
|
||||
/>
|
||||
</q-popup-proxy>
|
||||
</q-icon>
|
||||
</template>
|
||||
</q-input>
|
||||
|
||||
<!-- <q-btn-toggle
|
||||
disable
|
||||
v-model="linkModel.curve"
|
||||
:options="[
|
||||
{ label: '直线', value: false },
|
||||
{ label: '曲线', value: true },
|
||||
]"
|
||||
/> -->
|
||||
|
||||
<q-input
|
||||
v-if="linkModel.curve"
|
||||
outlined
|
||||
v-model.number="linkModel.segmentsCount"
|
||||
type="number"
|
||||
@blur="onUpdate"
|
||||
label="曲线分段数量"
|
||||
lazy-rules
|
||||
:rules="[(val) => (val && val > 0) || '曲线分段数量必须大于0']"
|
||||
/>
|
||||
</q-form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { LinkData } from 'src/examples/app/graphics/LinkInteraction';
|
||||
import { Link } from 'src/graphics/link/Link';
|
||||
import { useDrawStore } from 'src/stores/draw-store';
|
||||
import { onMounted, reactive, watch } from 'vue';
|
||||
|
||||
const drawStore = useDrawStore();
|
||||
const linkModel = reactive(new LinkData());
|
||||
|
||||
drawStore.$subscribe;
|
||||
watch(
|
||||
() => drawStore.selectedGraphic,
|
||||
(val) => {
|
||||
if (val && val.type == Link.Type) {
|
||||
// console.log('link变更');
|
||||
linkModel.copyFrom(val.saveData() as LinkData);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
// console.log('link 属性表单 mounted');
|
||||
const link = drawStore.selectedGraphic as Link;
|
||||
if (link) {
|
||||
linkModel.copyFrom(link.saveData());
|
||||
}
|
||||
});
|
||||
|
||||
function onUpdate() {
|
||||
console.log('link 属性更新');
|
||||
const link = drawStore.selectedGraphic as Link;
|
||||
if (link) {
|
||||
drawStore.getDrawApp().updateGraphicAndRecord(link, linkModel);
|
||||
}
|
||||
}
|
||||
</script>
|
@ -1,112 +0,0 @@
|
||||
<template>
|
||||
<q-form>
|
||||
<q-input outlined readonly v-model="platformModel.id" label="id" hint="" />
|
||||
<q-input
|
||||
outlined
|
||||
v-model.number="platformModel.lineWidth"
|
||||
type="number"
|
||||
@blur="onUpdate"
|
||||
label="线宽"
|
||||
lazy-rules
|
||||
:rules="[(val) => (val && val > 0) || '画布宽必须大于0']"
|
||||
/>
|
||||
<q-input
|
||||
outlined
|
||||
v-model="platformModel.lineColor"
|
||||
@blur="onUpdate"
|
||||
label="线色"
|
||||
lazy-rules
|
||||
:rules="[(val) => (val && val.length > 0) || '线色不能为空']"
|
||||
>
|
||||
<template v-slot:append>
|
||||
<q-icon name="colorize" class="cursor-pointer">
|
||||
<q-popup-proxy cover transition-show="scale" transition-hide="scale">
|
||||
<q-color
|
||||
v-model="platformModel.lineColor"
|
||||
@change="
|
||||
(val) => {
|
||||
platformModel.lineColor = val;
|
||||
onUpdate();
|
||||
}
|
||||
"
|
||||
/>
|
||||
</q-popup-proxy>
|
||||
</q-icon>
|
||||
</template>
|
||||
</q-input>
|
||||
<q-select
|
||||
outlined
|
||||
@blur="onUpdate"
|
||||
v-model="hasDoor"
|
||||
:options="optionsDoor"
|
||||
label="是否有屏蔽门"
|
||||
/>
|
||||
<q-select
|
||||
outlined
|
||||
@blur="onUpdate"
|
||||
v-model="trainDirection"
|
||||
:options="optionsDirection"
|
||||
label="行驶方向"
|
||||
/>
|
||||
</q-form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { PlatformData } from 'src/examples/app/graphics/PlatformInteraction';
|
||||
import { Platform } from 'src/graphics/platform/Platform';
|
||||
import { useDrawStore } from 'src/stores/draw-store';
|
||||
import { onMounted, reactive, ref, watch } from 'vue';
|
||||
|
||||
const drawStore = useDrawStore();
|
||||
const platformModel = reactive(new PlatformData());
|
||||
const hasDoor = ref('是');
|
||||
const optionsDoor = ['是', '否'];
|
||||
const trainDirection = ref('向左');
|
||||
const optionsDirection = ['向左', '向右'];
|
||||
enum showSelect {
|
||||
是 = 'true',
|
||||
否 = 'false',
|
||||
向左 = 'left',
|
||||
向右 = 'right',
|
||||
}
|
||||
enum showSelectData {
|
||||
true = '是',
|
||||
false = '否',
|
||||
left = '向左',
|
||||
right = '向右',
|
||||
}
|
||||
|
||||
drawStore.$subscribe;
|
||||
watch(
|
||||
() => drawStore.selectedGraphic,
|
||||
(val) => {
|
||||
if (val && val.type == Platform.Type) {
|
||||
platformModel.copyFrom(val.saveData() as PlatformData);
|
||||
hasDoor.value = (showSelectData as never)[platformModel.hasdoor + ''];
|
||||
trainDirection.value = (showSelectData as never)[
|
||||
platformModel.trainDirection
|
||||
];
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
const platform = drawStore.selectedGraphic as Platform;
|
||||
if (platform) {
|
||||
platformModel.copyFrom(platform.saveData());
|
||||
hasDoor.value = (showSelectData as never)[platformModel.hasdoor + ''];
|
||||
trainDirection.value = (showSelectData as never)[
|
||||
platformModel.trainDirection
|
||||
];
|
||||
}
|
||||
});
|
||||
|
||||
function onUpdate() {
|
||||
platformModel.hasdoor = JSON.parse((showSelect as never)[hasDoor.value]);
|
||||
platformModel.trainDirection = (showSelect as never)[trainDirection.value];
|
||||
const platform = drawStore.selectedGraphic as Platform;
|
||||
if (platform) {
|
||||
drawStore.getDrawApp().updateGraphicAndRecord(platform, platformModel);
|
||||
}
|
||||
}
|
||||
</script>
|
@ -1,74 +0,0 @@
|
||||
<template>
|
||||
<q-form>
|
||||
<q-input outlined readonly v-model="stationModel.id" label="id" hint="" />
|
||||
<q-input
|
||||
outlined
|
||||
v-model.number="stationModel.lineWidth"
|
||||
type="number"
|
||||
@blur="onUpdate"
|
||||
label="线宽"
|
||||
lazy-rules
|
||||
:rules="[(val) => (val && val > 0) || '画布宽必须大于0']"
|
||||
/>
|
||||
|
||||
<q-input
|
||||
outlined
|
||||
v-model="stationModel.lineColor"
|
||||
@blur="onUpdate"
|
||||
label="线色"
|
||||
lazy-rules
|
||||
:rules="[(val) => (val && val.length > 0) || '线色不能为空']"
|
||||
>
|
||||
<template v-slot:append>
|
||||
<q-icon name="colorize" class="cursor-pointer">
|
||||
<q-popup-proxy cover transition-show="scale" transition-hide="scale">
|
||||
<q-color
|
||||
v-model="stationModel.lineColor"
|
||||
@change="
|
||||
(val) => {
|
||||
stationModel.lineColor = val;
|
||||
onUpdate();
|
||||
}
|
||||
"
|
||||
/>
|
||||
</q-popup-proxy>
|
||||
</q-icon>
|
||||
</template>
|
||||
</q-input>
|
||||
</q-form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { RectData } from 'src/examples/app/graphics/RectInteraction';
|
||||
import { Rect } from 'src/graphics/rect/Rect';
|
||||
import { useDrawStore } from 'src/stores/draw-store';
|
||||
import { onMounted, reactive, watch } from 'vue';
|
||||
|
||||
const drawStore = useDrawStore();
|
||||
const stationModel = reactive(new RectData());
|
||||
|
||||
drawStore.$subscribe;
|
||||
watch(
|
||||
() => drawStore.selectedGraphic,
|
||||
(val) => {
|
||||
if (val && val.type == Rect.Type) {
|
||||
stationModel.copyFrom(val.saveData() as RectData);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
const station = drawStore.selectedGraphic as Rect;
|
||||
|
||||
if (station) {
|
||||
stationModel.copyFrom(station.saveData());
|
||||
}
|
||||
});
|
||||
|
||||
function onUpdate() {
|
||||
const station = drawStore.selectedGraphic as Rect;
|
||||
if (station) {
|
||||
drawStore.getDrawApp().updateGraphicAndRecord(station, stationModel);
|
||||
}
|
||||
}
|
||||
</script>
|
@ -1,57 +0,0 @@
|
||||
<template>
|
||||
<q-form>
|
||||
<q-input outlined readonly v-model="signalModel.id" label="id" hint="" />
|
||||
<q-select
|
||||
outlined
|
||||
@blur="onUpdate"
|
||||
v-model="signalDirection"
|
||||
:options="optionsDirection"
|
||||
label="方向"
|
||||
/>
|
||||
</q-form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { SignalData } from 'src/examples/app/graphics/SignalInteraction';
|
||||
import { Signal } from 'src/graphics/signal/Signal';
|
||||
import { useDrawStore } from 'src/stores/draw-store';
|
||||
import { onMounted, reactive, ref, watch } from 'vue';
|
||||
|
||||
const drawStore = useDrawStore();
|
||||
const signalModel = reactive(new SignalData());
|
||||
const signalDirection = ref('向右');
|
||||
const optionsDirection = ['向左', '向右', '向上', '向下'];
|
||||
enum directionSelect {
|
||||
向左 = 'left',
|
||||
向右 = 'right',
|
||||
向上 = 'up',
|
||||
向下 = 'down',
|
||||
}
|
||||
|
||||
drawStore.$subscribe;
|
||||
watch(
|
||||
() => drawStore.selectedGraphic,
|
||||
(val) => {
|
||||
if (val && val.type == Signal.Type) {
|
||||
signalModel.copyFrom(val.saveData() as SignalData);
|
||||
signalDirection.value = (directionSelect as never)[signalModel.direction];
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
const signal = drawStore.selectedGraphic as Signal;
|
||||
if (signal) {
|
||||
signalModel.copyFrom(signal.saveData());
|
||||
signalDirection.value = (directionSelect as never)[signalModel.direction];
|
||||
}
|
||||
});
|
||||
|
||||
function onUpdate() {
|
||||
signalModel.direction = (directionSelect as never)[signalDirection.value];
|
||||
const signal = drawStore.selectedGraphic as Signal;
|
||||
if (signal) {
|
||||
drawStore.getDrawApp().updateGraphicAndRecord(signal, signalModel);
|
||||
}
|
||||
}
|
||||
</script>
|
@ -1,200 +0,0 @@
|
||||
<template>
|
||||
<q-form>
|
||||
<q-input outlined readonly v-model="stationModel.id" label="id" hint="" />
|
||||
<q-input
|
||||
outlined
|
||||
label="车站名称"
|
||||
@blur="onUpdate"
|
||||
v-model="stationModel.code"
|
||||
lazy-rules
|
||||
/>
|
||||
<q-input
|
||||
outlined
|
||||
v-model.number="stationModel.codeFontSize"
|
||||
type="number"
|
||||
@blur="onUpdate"
|
||||
label="字体大小"
|
||||
lazy-rules
|
||||
:rules="[(val) => (val && val > 0) || '字体大小必须大于0']"
|
||||
/>
|
||||
<q-input
|
||||
outlined
|
||||
v-model="stationModel.codeColor"
|
||||
@blur="onUpdate"
|
||||
label="字体颜色"
|
||||
lazy-rules
|
||||
:rules="[(val) => (val && val.length > 0) || '线色不能为空']"
|
||||
>
|
||||
<template v-slot:append>
|
||||
<q-icon name="colorize" class="cursor-pointer">
|
||||
<q-popup-proxy cover transition-show="scale" transition-hide="scale">
|
||||
<q-color
|
||||
v-model="stationModel.codeColor"
|
||||
@change="
|
||||
(val) => {
|
||||
stationModel.codeColor = val;
|
||||
onUpdate();
|
||||
}
|
||||
"
|
||||
/>
|
||||
</q-popup-proxy>
|
||||
</q-icon>
|
||||
</template>
|
||||
</q-input>
|
||||
<q-select
|
||||
outlined
|
||||
@blur="onUpdate"
|
||||
v-model="hasCircle"
|
||||
:options="optionsCircle"
|
||||
label="是否有圆圈"
|
||||
/>
|
||||
<div v-if="stationModel.hasCircle">
|
||||
<q-item-label header>位置</q-item-label>
|
||||
<q-item>
|
||||
<q-item-section no-wrap class="q-gutter-sm column">
|
||||
<div class="row">
|
||||
<q-input
|
||||
outlined
|
||||
@blur="onUpdate"
|
||||
label="x"
|
||||
v-model.number="stationModel.circlePoint.x"
|
||||
type="number"
|
||||
step="any"
|
||||
class="col"
|
||||
/>
|
||||
<q-input
|
||||
outlined
|
||||
@blur="onUpdate"
|
||||
label="y"
|
||||
v-model.number="stationModel.circlePoint.y"
|
||||
type="number"
|
||||
step="any"
|
||||
class="col"
|
||||
/>
|
||||
</div>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-input
|
||||
outlined
|
||||
v-model.number="stationModel.radius"
|
||||
type="number"
|
||||
@blur="onUpdate"
|
||||
label="半径"
|
||||
lazy-rules
|
||||
:rules="[(val) => (val && val > 0) || '半径大小必须大于0']"
|
||||
/>
|
||||
<q-input
|
||||
outlined
|
||||
v-model="stationModel.fillColor"
|
||||
@blur="onUpdate"
|
||||
label="填充颜色"
|
||||
lazy-rules
|
||||
:rules="[(val) => (val && val.length > 0) || '线色不能为空']"
|
||||
>
|
||||
<template v-slot:append>
|
||||
<q-icon name="colorize" class="cursor-pointer">
|
||||
<q-popup-proxy
|
||||
cover
|
||||
transition-show="scale"
|
||||
transition-hide="scale"
|
||||
>
|
||||
<q-color
|
||||
v-model="stationModel.fillColor"
|
||||
@change="
|
||||
(val) => {
|
||||
stationModel.fillColor = val;
|
||||
onUpdate();
|
||||
}
|
||||
"
|
||||
/>
|
||||
</q-popup-proxy>
|
||||
</q-icon>
|
||||
</template>
|
||||
</q-input>
|
||||
<q-input
|
||||
outlined
|
||||
v-model.number="stationModel.borderWidth"
|
||||
type="number"
|
||||
@blur="onUpdate"
|
||||
label="边框宽度"
|
||||
lazy-rules
|
||||
:rules="[(val) => (val && val > 0) || '画布宽必须大于0']"
|
||||
/>
|
||||
<q-input
|
||||
outlined
|
||||
v-model="stationModel.borderColor"
|
||||
@blur="onUpdate"
|
||||
label="边框颜色"
|
||||
lazy-rules
|
||||
:rules="[(val) => (val && val.length > 0) || '线色不能为空']"
|
||||
>
|
||||
<template v-slot:append>
|
||||
<q-icon name="colorize" class="cursor-pointer">
|
||||
<q-popup-proxy
|
||||
cover
|
||||
transition-show="scale"
|
||||
transition-hide="scale"
|
||||
>
|
||||
<q-color
|
||||
v-model="stationModel.borderColor"
|
||||
@change="
|
||||
(val) => {
|
||||
stationModel.borderColor = val;
|
||||
onUpdate();
|
||||
}
|
||||
"
|
||||
/>
|
||||
</q-popup-proxy>
|
||||
</q-icon>
|
||||
</template>
|
||||
</q-input>
|
||||
</div>
|
||||
</q-form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { StationData } from 'src/examples/app/graphics/StationInteraction';
|
||||
import { Station } from 'src/graphics/station/Station';
|
||||
import { useDrawStore } from 'src/stores/draw-store';
|
||||
import { onMounted, reactive, ref, watch } from 'vue';
|
||||
|
||||
const drawStore = useDrawStore();
|
||||
const stationModel = reactive(new StationData());
|
||||
const hasCircle = ref('是');
|
||||
const optionsCircle = ['是', '否'];
|
||||
enum showSelect {
|
||||
是 = 'true',
|
||||
否 = 'false',
|
||||
}
|
||||
enum showSelectData {
|
||||
true = '是',
|
||||
false = '否',
|
||||
}
|
||||
|
||||
drawStore.$subscribe;
|
||||
watch(
|
||||
() => drawStore.selectedGraphic,
|
||||
(val) => {
|
||||
if (val && val.type == Station.Type) {
|
||||
stationModel.copyFrom(val.saveData() as StationData);
|
||||
hasCircle.value = (showSelectData as never)[stationModel.hasCircle + ''];
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
const station = drawStore.selectedGraphic as Station;
|
||||
if (station) {
|
||||
stationModel.copyFrom(station.saveData());
|
||||
hasCircle.value = (showSelectData as never)[stationModel.hasCircle + ''];
|
||||
}
|
||||
});
|
||||
|
||||
function onUpdate() {
|
||||
stationModel.hasCircle = JSON.parse((showSelect as never)[hasCircle.value]);
|
||||
const station = drawStore.selectedGraphic as Station;
|
||||
if (station) {
|
||||
drawStore.getDrawApp().updateGraphicAndRecord(station, stationModel);
|
||||
}
|
||||
}
|
||||
</script>
|
@ -1,198 +0,0 @@
|
||||
<template>
|
||||
<q-form>
|
||||
<q-input outlined readonly v-model="trainModel.id" label="id" hint="" />
|
||||
<q-input
|
||||
outlined
|
||||
v-model="trainModel.code"
|
||||
label="车号"
|
||||
hint=""
|
||||
@blur="onUpdate"
|
||||
/>
|
||||
<q-input
|
||||
outlined
|
||||
v-model="trainModel.codeColor"
|
||||
@blur="onUpdate"
|
||||
label="车号颜色"
|
||||
lazy-rules
|
||||
:rules="[(val) => (val && val.length > 0) || '车号颜色不能为空']"
|
||||
>
|
||||
<template v-slot:append>
|
||||
<q-icon name="colorize" class="cursor-pointer">
|
||||
<q-popup-proxy cover transition-show="scale" transition-hide="scale">
|
||||
<q-color
|
||||
v-model="trainModel.codeColor"
|
||||
@change="
|
||||
(val) => {
|
||||
trainModel.codeColor = val;
|
||||
onUpdate();
|
||||
}
|
||||
"
|
||||
/>
|
||||
</q-popup-proxy>
|
||||
</q-icon>
|
||||
</template>
|
||||
</q-input>
|
||||
<q-input
|
||||
outlined
|
||||
v-model="trainModel.headColor"
|
||||
@blur="onUpdate"
|
||||
label="箭头颜色"
|
||||
lazy-rules
|
||||
:rules="[(val) => (val && val.length > 0) || '车箭头颜色不能为空']"
|
||||
>
|
||||
<template v-slot:append>
|
||||
<q-icon name="colorize" class="cursor-pointer">
|
||||
<q-popup-proxy cover transition-show="scale" transition-hide="scale">
|
||||
<q-color
|
||||
v-model="trainModel.headColor"
|
||||
@change="
|
||||
(val) => {
|
||||
trainModel.headColor = val;
|
||||
onUpdate();
|
||||
}
|
||||
"
|
||||
/>
|
||||
</q-popup-proxy>
|
||||
</q-icon>
|
||||
</template>
|
||||
</q-input>
|
||||
<q-input
|
||||
outlined
|
||||
v-model.number="trainModel.codeFontSize"
|
||||
type="number"
|
||||
@blur="onUpdate"
|
||||
label="字体大小"
|
||||
lazy-rules
|
||||
:rules="[(val) => (val && val > 0) || '字体大小必须大于0']"
|
||||
/>
|
||||
<q-select
|
||||
outlined
|
||||
@blur="onUpdate"
|
||||
v-model="hasBorder"
|
||||
:options="optionsDoor"
|
||||
label="是否有边框"
|
||||
/>
|
||||
<q-input
|
||||
outlined
|
||||
v-model.number="trainModel.borderWidth"
|
||||
type="number"
|
||||
@blur="onUpdate"
|
||||
label="边框线宽"
|
||||
lazy-rules
|
||||
:rules="[(val) => (val && val > 0) || '边框线宽必须大于0']"
|
||||
/>
|
||||
<q-input
|
||||
outlined
|
||||
v-model="trainModel.borderColor"
|
||||
@blur="onUpdate"
|
||||
label="边框颜色"
|
||||
lazy-rules
|
||||
:rules="[(val) => (val && val.length > 0) || '边框颜色不能为空']"
|
||||
>
|
||||
<template v-slot:append>
|
||||
<q-icon name="colorize" class="cursor-pointer">
|
||||
<q-popup-proxy cover transition-show="scale" transition-hide="scale">
|
||||
<q-color
|
||||
v-model="trainModel.borderColor"
|
||||
@change="
|
||||
(val) => {
|
||||
trainModel.borderColor = val;
|
||||
onUpdate();
|
||||
}
|
||||
"
|
||||
/>
|
||||
</q-popup-proxy>
|
||||
</q-icon>
|
||||
</template>
|
||||
</q-input>
|
||||
<q-input
|
||||
outlined
|
||||
v-model="trainModel.bodyColor"
|
||||
@blur="onUpdate"
|
||||
label="背景颜色"
|
||||
lazy-rules
|
||||
:rules="[(val) => (val && val.length > 0) || '背景颜色不能为空']"
|
||||
>
|
||||
<template v-slot:append>
|
||||
<q-icon name="colorize" class="cursor-pointer">
|
||||
<q-popup-proxy cover transition-show="scale" transition-hide="scale">
|
||||
<q-color
|
||||
v-model="trainModel.bodyColor"
|
||||
@change="
|
||||
(val) => {
|
||||
trainModel.bodyColor = val;
|
||||
onUpdate();
|
||||
}
|
||||
"
|
||||
/>
|
||||
</q-popup-proxy>
|
||||
</q-icon>
|
||||
</template>
|
||||
</q-input>
|
||||
<q-select
|
||||
outlined
|
||||
@blur="onUpdate"
|
||||
v-model="trainDirection"
|
||||
:options="optionsDirection"
|
||||
label="行驶方向"
|
||||
/>
|
||||
</q-form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { TrainData } from 'src/examples/app/graphics/TrainInteraction';
|
||||
import { Train } from 'src/graphics/train/Train';
|
||||
import { useDrawStore } from 'src/stores/draw-store';
|
||||
import { onMounted, reactive, ref, watch } from 'vue';
|
||||
|
||||
const drawStore = useDrawStore();
|
||||
const trainModel = reactive(new TrainData());
|
||||
const hasBorder = ref('是');
|
||||
const optionsDoor = ['是', '否'];
|
||||
const trainDirection = ref('向左');
|
||||
const optionsDirection = ['向左', '向右'];
|
||||
enum showSelect {
|
||||
是 = 'true',
|
||||
否 = 'false',
|
||||
向左 = 'left',
|
||||
向右 = 'right',
|
||||
}
|
||||
enum showSelectData {
|
||||
true = '是',
|
||||
false = '否',
|
||||
left = '向左',
|
||||
right = '向右',
|
||||
}
|
||||
|
||||
drawStore.$subscribe;
|
||||
watch(
|
||||
() => drawStore.selectedGraphic,
|
||||
(val) => {
|
||||
if (val && val.type == Train.Type) {
|
||||
trainModel.copyFrom(val.saveData() as TrainData);
|
||||
hasBorder.value = (showSelectData as never)[trainModel.hasBorder + ''];
|
||||
trainDirection.value = (showSelectData as never)[
|
||||
trainModel.trainDirection
|
||||
];
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
const train = drawStore.selectedGraphic as Train;
|
||||
if (train) {
|
||||
trainModel.copyFrom(train.saveData());
|
||||
hasBorder.value = (showSelectData as never)[trainModel.hasBorder + ''];
|
||||
trainDirection.value = (showSelectData as never)[trainModel.trainDirection];
|
||||
}
|
||||
});
|
||||
|
||||
function onUpdate() {
|
||||
trainModel.hasBorder = JSON.parse((showSelect as never)[hasBorder.value]);
|
||||
trainModel.trainDirection = (showSelect as never)[trainDirection.value];
|
||||
const train = drawStore.selectedGraphic as Train;
|
||||
if (train) {
|
||||
drawStore.getDrawApp().updateGraphicAndRecord(train, trainModel);
|
||||
}
|
||||
}
|
||||
</script>
|
@ -1,96 +0,0 @@
|
||||
<template>
|
||||
<q-form>
|
||||
<q-input
|
||||
outlined
|
||||
v-model.number="template.lineWidth"
|
||||
type="number"
|
||||
@blur="onUpdate"
|
||||
label="线宽 *"
|
||||
lazy-rules
|
||||
:rules="[(val) => (val && val > 0) || '线宽必须大于0']"
|
||||
/>
|
||||
|
||||
<q-input
|
||||
outlined
|
||||
v-model="template.lineColor"
|
||||
@blur="onUpdate"
|
||||
label="线色 *"
|
||||
lazy-rules
|
||||
:rules="[(val) => (val && val.length > 0) || '线色不能为空']"
|
||||
>
|
||||
<template v-slot:append>
|
||||
<q-icon name="colorize" class="cursor-pointer">
|
||||
<q-popup-proxy cover transition-show="scale" transition-hide="scale">
|
||||
<q-color
|
||||
v-model="template.lineColor"
|
||||
@change="
|
||||
(val) => {
|
||||
template.lineColor = val;
|
||||
onUpdate();
|
||||
}
|
||||
"
|
||||
/>
|
||||
</q-popup-proxy>
|
||||
</q-icon>
|
||||
</template>
|
||||
</q-input>
|
||||
|
||||
<q-btn-toggle
|
||||
v-model="template.curve"
|
||||
@update:model-value="onUpdate"
|
||||
:options="[
|
||||
{ label: '直线', value: false },
|
||||
{ label: '曲线', value: true },
|
||||
]"
|
||||
/>
|
||||
|
||||
<q-input
|
||||
v-if="template.curve"
|
||||
outlined
|
||||
v-model.number="template.segmentsCount"
|
||||
type="number"
|
||||
@blur="onUpdate"
|
||||
label="曲线分段数量 *"
|
||||
lazy-rules
|
||||
:rules="[(val) => (val && val > 0) || '曲线分段数量必须大于0']"
|
||||
/>
|
||||
</q-form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { LinkTemplate } from 'src/graphics/link/Link';
|
||||
import { useDrawStore } from 'src/stores/draw-store';
|
||||
import { onMounted, reactive } from 'vue';
|
||||
|
||||
const drawStore = useDrawStore();
|
||||
const template = reactive({
|
||||
lineWidth: 1,
|
||||
lineColor: '#0000ff',
|
||||
curve: false,
|
||||
segmentsCount: 10,
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
const type = drawStore.drawGraphicType;
|
||||
if (type) {
|
||||
const gt = drawStore.drawGraphicTemplate;
|
||||
if (gt) {
|
||||
const lt = gt as LinkTemplate;
|
||||
template.lineWidth = lt.lineWidth;
|
||||
template.lineColor = lt.lineColor;
|
||||
template.curve = lt.curve;
|
||||
template.segmentsCount = lt.segmentsCount;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function onUpdate() {
|
||||
const gt = drawStore.drawGraphicTemplate as LinkTemplate;
|
||||
if (gt) {
|
||||
gt.lineWidth = template.lineWidth;
|
||||
gt.lineColor = template.lineColor;
|
||||
gt.curve = template.curve;
|
||||
gt.segmentsCount = template.segmentsCount;
|
||||
}
|
||||
}
|
||||
</script>
|
@ -1,76 +0,0 @@
|
||||
<template>
|
||||
<q-form>
|
||||
<q-input
|
||||
outlined
|
||||
v-model.number="template.lineWidth"
|
||||
type="number"
|
||||
@blur="onUpdate"
|
||||
label="线宽 *"
|
||||
lazy-rules
|
||||
:rules="[(val) => (val && val > 0) || '线宽必须大于0']"
|
||||
/>
|
||||
|
||||
<q-input
|
||||
outlined
|
||||
v-model="template.lineColor"
|
||||
@blur="onUpdate"
|
||||
label="线色 *"
|
||||
lazy-rules
|
||||
:rules="[(val) => (val && val.length > 0) || '线色不能为空']"
|
||||
>
|
||||
<template v-slot:append>
|
||||
<q-icon name="colorize" class="cursor-pointer">
|
||||
<q-popup-proxy cover transition-show="scale" transition-hide="scale">
|
||||
<q-color
|
||||
v-model="template.lineColor"
|
||||
@change="
|
||||
(val) => {
|
||||
template.lineColor = val;
|
||||
onUpdate();
|
||||
}
|
||||
"
|
||||
/>
|
||||
</q-popup-proxy>
|
||||
</q-icon>
|
||||
</template>
|
||||
</q-input>
|
||||
</q-form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { LinkTemplate } from 'src/graphics/link/Link';
|
||||
import { useDrawStore } from 'src/stores/draw-store';
|
||||
import { onMounted, reactive } from 'vue';
|
||||
|
||||
const drawStore = useDrawStore();
|
||||
const template = reactive({
|
||||
lineWidth: 1,
|
||||
lineColor: '#0000ff',
|
||||
curve: false,
|
||||
segmentsCount: 10,
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
const type = drawStore.drawGraphicType;
|
||||
if (type) {
|
||||
const gt = drawStore.drawGraphicTemplate;
|
||||
if (gt) {
|
||||
const lt = gt as LinkTemplate;
|
||||
template.lineWidth = lt.lineWidth;
|
||||
template.lineColor = lt.lineColor;
|
||||
template.curve = lt.curve;
|
||||
template.segmentsCount = lt.segmentsCount;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function onUpdate() {
|
||||
const gt = drawStore.drawGraphicTemplate as LinkTemplate;
|
||||
if (gt) {
|
||||
gt.lineWidth = template.lineWidth;
|
||||
gt.lineColor = template.lineColor;
|
||||
gt.curve = template.curve;
|
||||
gt.segmentsCount = template.segmentsCount;
|
||||
}
|
||||
}
|
||||
</script>
|
@ -1,76 +0,0 @@
|
||||
<template>
|
||||
<q-form>
|
||||
<q-input
|
||||
outlined
|
||||
v-model.number="template.lineWidth"
|
||||
type="number"
|
||||
@blur="onUpdate"
|
||||
label="线宽 *"
|
||||
lazy-rules
|
||||
:rules="[(val) => (val && val > 0) || '线宽必须大于0']"
|
||||
/>
|
||||
|
||||
<q-input
|
||||
outlined
|
||||
v-model="template.lineColor"
|
||||
@blur="onUpdate"
|
||||
label="线色 *"
|
||||
lazy-rules
|
||||
:rules="[(val) => (val && val.length > 0) || '线色不能为空']"
|
||||
>
|
||||
<template v-slot:append>
|
||||
<q-icon name="colorize" class="cursor-pointer">
|
||||
<q-popup-proxy cover transition-show="scale" transition-hide="scale">
|
||||
<q-color
|
||||
v-model="template.lineColor"
|
||||
@change="
|
||||
(val) => {
|
||||
template.lineColor = val;
|
||||
onUpdate();
|
||||
}
|
||||
"
|
||||
/>
|
||||
</q-popup-proxy>
|
||||
</q-icon>
|
||||
</template>
|
||||
</q-input>
|
||||
</q-form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { LinkTemplate } from 'src/graphics/link/Link';
|
||||
import { useDrawStore } from 'src/stores/draw-store';
|
||||
import { onMounted, reactive } from 'vue';
|
||||
|
||||
const drawStore = useDrawStore();
|
||||
const template = reactive({
|
||||
lineWidth: 1,
|
||||
lineColor: '#0000ff',
|
||||
curve: false,
|
||||
segmentsCount: 10,
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
const type = drawStore.drawGraphicType;
|
||||
if (type) {
|
||||
const gt = drawStore.drawGraphicTemplate;
|
||||
if (gt) {
|
||||
const lt = gt as LinkTemplate;
|
||||
template.lineWidth = lt.lineWidth;
|
||||
template.lineColor = lt.lineColor;
|
||||
template.curve = lt.curve;
|
||||
template.segmentsCount = lt.segmentsCount;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function onUpdate() {
|
||||
const gt = drawStore.drawGraphicTemplate as LinkTemplate;
|
||||
if (gt) {
|
||||
gt.lineWidth = template.lineWidth;
|
||||
gt.lineColor = template.lineColor;
|
||||
gt.curve = template.curve;
|
||||
gt.segmentsCount = template.segmentsCount;
|
||||
}
|
||||
}
|
||||
</script>
|
@ -1,70 +0,0 @@
|
||||
<template>
|
||||
<q-form>
|
||||
<q-input
|
||||
outlined
|
||||
v-model.number="template.lineWidth"
|
||||
type="number"
|
||||
@blur="onUpdate"
|
||||
label="字体大小 *"
|
||||
lazy-rules
|
||||
:rules="[(val) => (val && val > 0) || '线宽必须大于0']"
|
||||
/>
|
||||
|
||||
<q-input
|
||||
outlined
|
||||
v-model="template.lineColor"
|
||||
@blur="onUpdate"
|
||||
label="字体颜色 *"
|
||||
lazy-rules
|
||||
:rules="[(val) => (val && val.length > 0) || '线色不能为空']"
|
||||
>
|
||||
<template v-slot:append>
|
||||
<q-icon name="colorize" class="cursor-pointer">
|
||||
<q-popup-proxy cover transition-show="scale" transition-hide="scale">
|
||||
<q-color
|
||||
v-model="template.lineColor"
|
||||
@change="
|
||||
(val) => {
|
||||
template.lineColor = val;
|
||||
onUpdate();
|
||||
}
|
||||
"
|
||||
/>
|
||||
</q-popup-proxy>
|
||||
</q-icon>
|
||||
</template>
|
||||
</q-input>
|
||||
</q-form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { LinkTemplate } from 'src/graphics/link/Link';
|
||||
import { useDrawStore } from 'src/stores/draw-store';
|
||||
import { onMounted, reactive } from 'vue';
|
||||
|
||||
const drawStore = useDrawStore();
|
||||
const template = reactive({
|
||||
lineWidth: 1,
|
||||
lineColor: '#0000ff',
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
const type = drawStore.drawGraphicType;
|
||||
if (type) {
|
||||
const gt = drawStore.drawGraphicTemplate;
|
||||
if (gt) {
|
||||
const lt = gt as LinkTemplate;
|
||||
template.lineWidth = lt.lineWidth;
|
||||
template.lineColor = lt.lineColor;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function onUpdate() {
|
||||
const gt = drawStore.drawGraphicTemplate as LinkTemplate;
|
||||
if (gt) {
|
||||
gt.lineWidth = template.lineWidth;
|
||||
gt.lineColor = template.lineColor;
|
||||
}
|
||||
}
|
||||
</script>
|
@ -1,69 +0,0 @@
|
||||
<template>
|
||||
<q-form>
|
||||
<q-input
|
||||
outlined
|
||||
v-model.number="template.codeFontSize"
|
||||
type="number"
|
||||
@blur="onUpdate"
|
||||
label="字体大小 *"
|
||||
lazy-rules
|
||||
:rules="[(val) => (val && val > 0) || '字体大小必须大于0']"
|
||||
/>
|
||||
<q-input
|
||||
outlined
|
||||
v-model="template.headColor"
|
||||
@blur="onUpdate"
|
||||
label="箭头颜色 *"
|
||||
lazy-rules
|
||||
:rules="[(val) => (val && val.length > 0) || '箭头颜色不能为空']"
|
||||
>
|
||||
<template v-slot:append>
|
||||
<q-icon name="colorize" class="cursor-pointer">
|
||||
<q-popup-proxy cover transition-show="scale" transition-hide="scale">
|
||||
<q-color
|
||||
v-model="template.headColor"
|
||||
@change="
|
||||
(val) => {
|
||||
template.headColor = val;
|
||||
onUpdate();
|
||||
}
|
||||
"
|
||||
/>
|
||||
</q-popup-proxy>
|
||||
</q-icon>
|
||||
</template>
|
||||
</q-input>
|
||||
</q-form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { TrainTemplate } from 'src/graphics/train/Train';
|
||||
import { useDrawStore } from 'src/stores/draw-store';
|
||||
import { onMounted, reactive } from 'vue';
|
||||
|
||||
const drawStore = useDrawStore();
|
||||
const template = reactive({
|
||||
codeFontSize: 22,
|
||||
headColor: '#00FF00',
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
const type = drawStore.drawGraphicType;
|
||||
if (type) {
|
||||
const gt = drawStore.drawGraphicTemplate;
|
||||
if (gt) {
|
||||
const lt = gt as TrainTemplate;
|
||||
template.codeFontSize = lt.codeFontSize;
|
||||
template.headColor = lt.headColor;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function onUpdate() {
|
||||
const gt = drawStore.drawGraphicTemplate as TrainTemplate;
|
||||
if (gt) {
|
||||
gt.codeFontSize = template.codeFontSize;
|
||||
gt.headColor = template.headColor;
|
||||
}
|
||||
}
|
||||
</script>
|
@ -1,8 +0,0 @@
|
||||
export interface Todo {
|
||||
id: number;
|
||||
content: string;
|
||||
}
|
||||
|
||||
export interface Meta {
|
||||
totalCount: number;
|
||||
}
|
@ -1,5 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import { GraphicApp } from '../app/JlGraphicApp';
|
||||
import { JlGraphic } from './JlGraphic';
|
||||
|
||||
/**
|
||||
@ -101,11 +100,7 @@ export class GraphicRelation {
|
||||
* 图形关系管理
|
||||
*/
|
||||
export class RelationManage {
|
||||
app: GraphicApp;
|
||||
relations: GraphicRelation[] = [];
|
||||
constructor(app: GraphicApp) {
|
||||
this.app = app;
|
||||
}
|
||||
|
||||
isContainsRelation(
|
||||
rp1: GraphicRelationParam,
|
||||
@ -182,4 +177,11 @@ export class RelationManage {
|
||||
const relations = this.getRelationsOfGraphicAndOtherType(g, type);
|
||||
relations.forEach((rl) => this.deleteRelation(rl));
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空
|
||||
*/
|
||||
clear() {
|
||||
this.relations.splice(0, this.relations.length);
|
||||
}
|
||||
}
|
@ -1,4 +1,3 @@
|
||||
import { GraphicApp } from '../app/JlGraphicApp';
|
||||
import { RelationManage } from './GraphicRelation';
|
||||
import { JlGraphic } from './JlGraphic';
|
||||
|
||||
@ -10,12 +9,12 @@ export interface GraphicQueryStore {
|
||||
/**
|
||||
* 根据id获取图形
|
||||
*/
|
||||
queryById<T extends JlGraphic>(id: string): T;
|
||||
queryById<T extends JlGraphic>(id: number | string): T;
|
||||
/**
|
||||
* 根据id模糊查询图形
|
||||
* @param id
|
||||
*/
|
||||
queryByIdAmbiguous(id: string): JlGraphic[];
|
||||
queryByIdAmbiguous(id: number | string): JlGraphic[];
|
||||
|
||||
/**
|
||||
* 根据类型获取图形列表
|
||||
@ -36,13 +35,13 @@ export interface GraphicQueryStore {
|
||||
* 根据id或code查询图形
|
||||
* @param v
|
||||
*/
|
||||
queryByIdOrCode(v: string): JlGraphic[];
|
||||
queryByIdOrCode(v: string | number): JlGraphic[];
|
||||
/**
|
||||
* 根据id或code及类型查询图形
|
||||
* @param v
|
||||
* @param type
|
||||
*/
|
||||
queryByIdOrCodeAndType(v: string, type: string): JlGraphic[];
|
||||
queryByIdOrCodeAndType(v: string | number, type: string): JlGraphic[];
|
||||
/**
|
||||
* 根据code和类型获取图形
|
||||
* @param code
|
||||
@ -61,19 +60,19 @@ export interface GraphicQueryStore {
|
||||
code: string,
|
||||
type: string
|
||||
): T[];
|
||||
|
||||
checkIdExist(v: number): boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* 图形存储
|
||||
*/
|
||||
export class GraphicStore implements GraphicQueryStore {
|
||||
app: GraphicApp;
|
||||
store: Map<string, JlGraphic>;
|
||||
store: Map<number, JlGraphic>;
|
||||
relationManage: RelationManage;
|
||||
constructor(app: GraphicApp) {
|
||||
this.app = app;
|
||||
this.store = new Map<string, JlGraphic>();
|
||||
this.relationManage = new RelationManage(app);
|
||||
constructor() {
|
||||
this.store = new Map<number, JlGraphic>();
|
||||
this.relationManage = new RelationManage();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -82,15 +81,20 @@ export class GraphicStore implements GraphicQueryStore {
|
||||
getAllGraphics(): JlGraphic[] {
|
||||
return [...this.store.values()];
|
||||
}
|
||||
queryById<T extends JlGraphic>(id: string): T {
|
||||
const graphic = this.store.get(id) as T;
|
||||
if (!graphic) throw Error(`未找到id为 [${id}] 的图形.`);
|
||||
return this.store.get(id) as T;
|
||||
queryById<T extends JlGraphic>(id: number | string): T {
|
||||
let nid = id;
|
||||
if (typeof id === 'string') {
|
||||
nid = parseInt(id);
|
||||
}
|
||||
queryByIdAmbiguous(id: string): JlGraphic[] {
|
||||
const graphic = this.store.get(nid as number) as T;
|
||||
if (!graphic) throw Error(`未找到id为 [${nid}] 的图形.`);
|
||||
return this.store.get(nid as number) as T;
|
||||
}
|
||||
queryByIdAmbiguous(id: number | string): JlGraphic[] {
|
||||
const nid = id + '';
|
||||
const list: JlGraphic[] = [];
|
||||
this.store.forEach((g) => {
|
||||
if (g.id.search(id) >= 0) {
|
||||
if ((g.id + '').search(nid) >= 0) {
|
||||
list.push(g);
|
||||
}
|
||||
});
|
||||
@ -123,7 +127,7 @@ export class GraphicStore implements GraphicQueryStore {
|
||||
});
|
||||
return list;
|
||||
}
|
||||
queryByIdOrCode(s: string): JlGraphic[] {
|
||||
queryByIdOrCode(s: string | number): JlGraphic[] {
|
||||
const list: JlGraphic[] = [];
|
||||
this.store.forEach((g) => {
|
||||
if (g.isIdOrCode(s)) {
|
||||
@ -132,7 +136,7 @@ export class GraphicStore implements GraphicQueryStore {
|
||||
});
|
||||
return list;
|
||||
}
|
||||
queryByIdOrCodeAndType(s: string, type: string): JlGraphic[] {
|
||||
queryByIdOrCodeAndType(s: string | number, type: string): JlGraphic[] {
|
||||
const list: JlGraphic[] = [];
|
||||
this.store.forEach((g) => {
|
||||
if (g.isIdOrCode(s) && g.type === type) {
|
||||
@ -169,7 +173,7 @@ export class GraphicStore implements GraphicQueryStore {
|
||||
* @param graphics 要存储的图形
|
||||
*/
|
||||
storeGraphics(graphic: JlGraphic): boolean {
|
||||
if (!graphic.id || graphic.id.trim() === '') {
|
||||
if (!graphic.id || graphic.id === 0) {
|
||||
throw new Error(`存储图形对象异常: id为空, ${graphic}`);
|
||||
}
|
||||
if (this.store.has(graphic.id)) {
|
||||
@ -198,4 +202,16 @@ export class GraphicStore implements GraphicQueryStore {
|
||||
}
|
||||
return remove;
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空
|
||||
*/
|
||||
clear() {
|
||||
this.relationManage.clear();
|
||||
this.store.clear();
|
||||
}
|
||||
|
||||
checkIdExist(id: number) {
|
||||
return this.store.has(id)
|
||||
}
|
||||
}
|
@ -9,10 +9,10 @@ export class IdGenerator {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
next(): string {
|
||||
next(): number {
|
||||
++this.serial;
|
||||
// console.log(this.getType() + this.serial)
|
||||
return this.getType() + this.serial;
|
||||
return this.serial;
|
||||
}
|
||||
|
||||
getType(): string {
|
||||
@ -20,7 +20,6 @@ export class IdGenerator {
|
||||
}
|
||||
|
||||
initSerial(serial: number): void {
|
||||
// console.log(serial)
|
||||
this.serial = serial;
|
||||
}
|
||||
}
|
@ -10,7 +10,7 @@ import {
|
||||
Point,
|
||||
Rectangle,
|
||||
} from 'pixi.js';
|
||||
import { AppConsts, JlCanvas } from '../app';
|
||||
import { AppConsts, IJlCanvas } from '../app';
|
||||
import {
|
||||
convertRectangleToPolygonPoints,
|
||||
recursiveChildren,
|
||||
@ -259,8 +259,12 @@ DisplayObject.prototype.isGraphicChild = function isGraphicChild() {
|
||||
const g = this.getGraphic();
|
||||
return g != null && !this.isAssistantAppend() && g.isChild(this);
|
||||
};
|
||||
DisplayObject.prototype.onAddToCanvas = function onAddToCanvas() {};
|
||||
DisplayObject.prototype.onRemoveFromCanvas = function onRemoveFromCanvas() {};
|
||||
DisplayObject.prototype.onAddToCanvas = function onAddToCanvas(
|
||||
_canvas: IJlCanvas
|
||||
) {};
|
||||
DisplayObject.prototype.onRemoveFromCanvas = function onRemoveFromCanvas(
|
||||
_canvas: IJlCanvas
|
||||
) {};
|
||||
DisplayObject.prototype.isInCanvas = function isInCanvas(): boolean {
|
||||
let graphic = this as DisplayObject;
|
||||
while (graphic && !Object.hasOwn(graphic, '__JlCanvas')) {
|
||||
@ -277,7 +281,7 @@ DisplayObject.prototype.getCanvas = function getCanvas() {
|
||||
graphic = graphic.parent;
|
||||
}
|
||||
if (graphic) {
|
||||
return graphic as JlCanvas;
|
||||
return graphic as IJlCanvas;
|
||||
}
|
||||
throw new Error(`图形${this.name}不在画布中`);
|
||||
};
|
||||
@ -290,7 +294,7 @@ DisplayObject.prototype.getViewport = function getViewport() {
|
||||
};
|
||||
DisplayObject.prototype.getGraphicApp = function getGraphicApp() {
|
||||
const canvas = this.getCanvas();
|
||||
return canvas.app;
|
||||
return canvas.scene.app;
|
||||
};
|
||||
DisplayObject.prototype.localToCanvasPoint = function localToCanvasPoint(
|
||||
p: IPointData
|
||||
@ -471,8 +475,8 @@ export class ChildTransform {
|
||||
* 图形数据
|
||||
*/
|
||||
export interface GraphicData {
|
||||
get id(): string; // 图形id
|
||||
set id(v: string);
|
||||
get id(): number; // 图形id
|
||||
set id(v: number);
|
||||
get graphicType(): string; // 图形类型
|
||||
set graphicType(v: string);
|
||||
get transform(): GraphicTransform; //
|
||||
@ -502,6 +506,7 @@ export interface GraphicData {
|
||||
export interface GraphicState {
|
||||
get code(): string; // 业务标识
|
||||
get graphicType(): string; // 图形类型
|
||||
remove?: boolean; // 是否移除图形
|
||||
/**
|
||||
* 克隆消息
|
||||
*/
|
||||
@ -580,7 +585,7 @@ export class GraphicAnimation {
|
||||
export abstract class JlGraphic extends Container {
|
||||
readonly __JlGraphic = true as const;
|
||||
readonly type: string; // 图形类型
|
||||
private _id = ''; // 图形的唯一标识,不具有业务意义,唯一,不可重复,可用做图形数据关联。
|
||||
private _id = 0; // 图形的唯一标识,不具有业务意义,唯一,不可重复,可用做图形数据关联。
|
||||
private _code = ''; // 业务编号/名称,用于标识图形对象,具有业务意义
|
||||
_datas?: GraphicData; // 图形数据
|
||||
_states?: GraphicState; // 图形状态数据
|
||||
@ -642,6 +647,10 @@ export abstract class JlGraphic extends Container {
|
||||
this.removeAllChildSelected();
|
||||
this.emit('unselected', this);
|
||||
}
|
||||
const app = this.getGraphicApp();
|
||||
if (app) {
|
||||
app.emit('graphicselectedchange', this, this.selected);
|
||||
}
|
||||
}
|
||||
|
||||
hasSelectedChilds(): boolean {
|
||||
@ -678,11 +687,16 @@ export abstract class JlGraphic extends Container {
|
||||
});
|
||||
}
|
||||
fireChildSelected(child: DisplayObject) {
|
||||
if (child.selected) {
|
||||
const selected = child.selected;
|
||||
if (selected) {
|
||||
this.emit('childselected', child);
|
||||
} else {
|
||||
this.emit('childunselected', child);
|
||||
}
|
||||
const app = this.getGraphicApp();
|
||||
if (app) {
|
||||
app.emit('graphicchildselectedchange', child, selected);
|
||||
}
|
||||
}
|
||||
exitChildEdit() {
|
||||
this.childEdit = false;
|
||||
@ -692,14 +706,14 @@ export abstract class JlGraphic extends Container {
|
||||
/**
|
||||
* 是否此对象id/code
|
||||
*/
|
||||
isIdOrCode(s: string): boolean {
|
||||
isIdOrCode(s: string | number): boolean {
|
||||
return this.id === s || this.code === s;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取图形id,如果图形数据对象存在,则返回图形数据对象id
|
||||
*/
|
||||
public get id(): string {
|
||||
public get id(): number {
|
||||
if (this._datas) {
|
||||
return this._datas.id;
|
||||
}
|
||||
@ -708,7 +722,7 @@ export abstract class JlGraphic extends Container {
|
||||
/**
|
||||
* 设置图形id,如果图形数据存在,则同时设置图形数据id
|
||||
*/
|
||||
public set id(v: string) {
|
||||
public set id(v: number) {
|
||||
this._id = v;
|
||||
if (this._datas) {
|
||||
this._datas.id = v;
|
||||
@ -902,7 +916,7 @@ export abstract class JlGraphic extends Container {
|
||||
this.onStateChange(state, old);
|
||||
stateChange = true;
|
||||
this.emit('stateupdate', this.getStates(), old);
|
||||
this.repaint();
|
||||
// this.repaint();
|
||||
}
|
||||
return stateChange;
|
||||
}
|
||||
@ -912,8 +926,12 @@ export abstract class JlGraphic extends Container {
|
||||
onStateChange(newVal: GraphicState, old?: GraphicState): void {}
|
||||
|
||||
repaint(): void {
|
||||
try {
|
||||
this.doRepaint();
|
||||
this.emit('repaint', this);
|
||||
} catch (e) {
|
||||
console.error(`设备id=${this.id},type=${this.type}重绘逻辑异常`, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
4
src/core/index.ts
Normal file
4
src/core/index.ts
Normal file
@ -0,0 +1,4 @@
|
||||
export * from './JlGraphic';
|
||||
export * from './IdGenerator';
|
||||
export * from './GraphicRelation';
|
||||
export * from './GraphicStore';
|
@ -1 +0,0 @@
|
||||
// app global css in SCSS form
|
@ -1,25 +0,0 @@
|
||||
// Quasar SCSS (& Sass) Variables
|
||||
// --------------------------------------------------
|
||||
// To customize the look and feel of this app, you can override
|
||||
// the Sass/SCSS variables found in Quasar's source Sass/SCSS files.
|
||||
|
||||
// Check documentation for full list of Quasar variables
|
||||
|
||||
// Your own variables (that are declared here) and Quasar's own
|
||||
// ones will be available out of the box in your .vue/.scss/.sass files
|
||||
|
||||
// It's highly recommended to change the default colors
|
||||
// to match your app's branding.
|
||||
// Tip: Use the "Theme Builder" on Quasar's documentation website.
|
||||
|
||||
$primary : #1976D2;
|
||||
$secondary : #26A69A;
|
||||
$accent : #9C27B0;
|
||||
|
||||
$dark : #1D1D1D;
|
||||
$dark-page : #121212;
|
||||
|
||||
$positive : #21BA45;
|
||||
$negative : #C10015;
|
||||
$info : #31CCEC;
|
||||
$warning : #F2C037;
|
9
src/env.d.ts
vendored
9
src/env.d.ts
vendored
@ -1,9 +0,0 @@
|
||||
/* eslint-disable */
|
||||
|
||||
declare namespace NodeJS {
|
||||
interface ProcessEnv {
|
||||
NODE_ENV: string;
|
||||
VUE_ROUTER_MODE: 'hash' | 'history' | 'abstract' | undefined;
|
||||
VUE_ROUTER_BASE: string | undefined;
|
||||
}
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
export class PageQueryDto {
|
||||
current: number;
|
||||
size: number;
|
||||
orders?: OrderItemDto[];
|
||||
constructor(current: number, size: number, orders?: OrderItemDto[]) {
|
||||
this.current = current;
|
||||
this.size = size;
|
||||
this.orders = orders;
|
||||
}
|
||||
}
|
||||
|
||||
export class OrderItemDto {
|
||||
column: string;
|
||||
asc: boolean;
|
||||
constructor(column: string, asc: boolean) {
|
||||
this.column = column;
|
||||
this.asc = asc;
|
||||
}
|
||||
|
||||
static asc(column: string): OrderItemDto {
|
||||
return new OrderItemDto(column, true);
|
||||
}
|
||||
static desc(column: string): OrderItemDto {
|
||||
return new OrderItemDto(column, false);
|
||||
}
|
||||
}
|
||||
|
||||
export interface PageDto<T = unknown> {
|
||||
records: T[];
|
||||
/**
|
||||
* 记录总数
|
||||
*/
|
||||
total: number;
|
||||
/**
|
||||
* 第几页
|
||||
*/
|
||||
current: number;
|
||||
/**
|
||||
* 每页数量
|
||||
*/
|
||||
size: number;
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
import { api } from 'src/boot/axios';
|
||||
import { PageDto, PageQueryDto } from './ApiCommon';
|
||||
import { Md5 } from 'ts-md5';
|
||||
|
||||
const UserUriBase = '/api/user';
|
||||
|
||||
interface RegisterInfo {
|
||||
name: string;
|
||||
mobile: string;
|
||||
password: string;
|
||||
}
|
||||
|
||||
interface User {
|
||||
id: string;
|
||||
name: string;
|
||||
mobile: string;
|
||||
password: string;
|
||||
registerTime: string;
|
||||
}
|
||||
|
||||
const PasswordSult = '4a6d74126bfd06d69406fcccb7e7d5d9'; // 密码加盐
|
||||
function encryptPassword(password: string): string {
|
||||
const md5 = new Md5();
|
||||
return md5.appendStr(`${password}${PasswordSult}`).end() as string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户注册
|
||||
* @param info
|
||||
* @returns
|
||||
*/
|
||||
export async function register(info: RegisterInfo): Promise<User> {
|
||||
const response = await api.post(`${UserUriBase}/register`, {
|
||||
...info,
|
||||
password: encryptPassword(info.password),
|
||||
});
|
||||
return response.data as User;
|
||||
}
|
||||
|
||||
interface LoginInfo {
|
||||
account: string;
|
||||
password: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户登录
|
||||
* @param loginInfo
|
||||
* @returns
|
||||
*/
|
||||
export async function login(loginInfo: LoginInfo): Promise<string> {
|
||||
const info = { ...loginInfo, password: encryptPassword(loginInfo.password) };
|
||||
const response = await api.post(`${UserUriBase}/login`, info);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
export class PagingQueryParams extends PageQueryDto {
|
||||
name?: string;
|
||||
roleId?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询用户信息
|
||||
* @param params
|
||||
* @returns
|
||||
*/
|
||||
export async function pageQuery(
|
||||
params: PagingQueryParams
|
||||
): Promise<PageDto<User>> {
|
||||
const response = await api.get(`${UserUriBase}/paging`, {
|
||||
params: params,
|
||||
});
|
||||
return response.data;
|
||||
}
|
||||
|
||||
export function distributeRole(query: { userId: number; roleIds: number[] }) {
|
||||
return api.post('/api/role/distribute', query);
|
||||
}
|
Binary file not shown.
Binary file not shown.
@ -1,161 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package google.protobuf;
|
||||
|
||||
option go_package = "google.golang.org/protobuf/types/known/anypb";
|
||||
option java_package = "com.google.protobuf";
|
||||
option java_outer_classname = "AnyProto";
|
||||
option java_multiple_files = true;
|
||||
option objc_class_prefix = "GPB";
|
||||
option csharp_namespace = "Google.Protobuf.WellKnownTypes";
|
||||
|
||||
// `Any` contains an arbitrary serialized protocol buffer message along with a
|
||||
// URL that describes the type of the serialized message.
|
||||
//
|
||||
// Protobuf library provides support to pack/unpack Any values in the form
|
||||
// of utility functions or additional generated methods of the Any type.
|
||||
//
|
||||
// Example 1: Pack and unpack a message in C++.
|
||||
//
|
||||
// Foo foo = ...;
|
||||
// Any any;
|
||||
// any.PackFrom(foo);
|
||||
// ...
|
||||
// if (any.UnpackTo(&foo)) {
|
||||
// ...
|
||||
// }
|
||||
//
|
||||
// Example 2: Pack and unpack a message in Java.
|
||||
//
|
||||
// Foo foo = ...;
|
||||
// Any any = Any.pack(foo);
|
||||
// ...
|
||||
// if (any.is(Foo.class)) {
|
||||
// foo = any.unpack(Foo.class);
|
||||
// }
|
||||
// // or ...
|
||||
// if (any.isSameTypeAs(Foo.getDefaultInstance())) {
|
||||
// foo = any.unpack(Foo.getDefaultInstance());
|
||||
// }
|
||||
//
|
||||
// Example 3: Pack and unpack a message in Python.
|
||||
//
|
||||
// foo = Foo(...)
|
||||
// any = Any()
|
||||
// any.Pack(foo)
|
||||
// ...
|
||||
// if any.Is(Foo.DESCRIPTOR):
|
||||
// any.Unpack(foo)
|
||||
// ...
|
||||
//
|
||||
// Example 4: Pack and unpack a message in Go
|
||||
//
|
||||
// foo := &pb.Foo{...}
|
||||
// any, err := anypb.New(foo)
|
||||
// if err != nil {
|
||||
// ...
|
||||
// }
|
||||
// ...
|
||||
// foo := &pb.Foo{}
|
||||
// if err := any.UnmarshalTo(foo); err != nil {
|
||||
// ...
|
||||
// }
|
||||
//
|
||||
// The pack methods provided by protobuf library will by default use
|
||||
// 'type.googleapis.com/full.type.name' as the type URL and the unpack
|
||||
// methods only use the fully qualified type name after the last '/'
|
||||
// in the type URL, for example "foo.bar.com/x/y.z" will yield type
|
||||
// name "y.z".
|
||||
//
|
||||
// JSON
|
||||
//
|
||||
// The JSON representation of an `Any` value uses the regular
|
||||
// representation of the deserialized, embedded message, with an
|
||||
// additional field `@type` which contains the type URL. Example:
|
||||
//
|
||||
// package google.profile;
|
||||
// message Person {
|
||||
// string first_name = 1;
|
||||
// string last_name = 2;
|
||||
// }
|
||||
//
|
||||
// {
|
||||
// "@type": "type.googleapis.com/google.profile.Person",
|
||||
// "firstName": <string>,
|
||||
// "lastName": <string>
|
||||
// }
|
||||
//
|
||||
// If the embedded message type is well-known and has a custom JSON
|
||||
// representation, that representation will be embedded adding a field
|
||||
// `value` which holds the custom JSON in addition to the `@type`
|
||||
// field. Example (for message [google.protobuf.Duration][]):
|
||||
//
|
||||
// {
|
||||
// "@type": "type.googleapis.com/google.protobuf.Duration",
|
||||
// "value": "1.212s"
|
||||
// }
|
||||
//
|
||||
message Any {
|
||||
// A URL/resource name that uniquely identifies the type of the serialized
|
||||
// protocol buffer message. This string must contain at least
|
||||
// one "/" character. The last segment of the URL's path must represent
|
||||
// the fully qualified name of the type (as in
|
||||
// `path/google.protobuf.Duration`). The name should be in a canonical form
|
||||
// (e.g., leading "." is not accepted).
|
||||
//
|
||||
// In practice, teams usually precompile into the binary all types that they
|
||||
// expect it to use in the context of Any. However, for URLs which use the
|
||||
// scheme `http`, `https`, or no scheme, one can optionally set up a type
|
||||
// server that maps type URLs to message definitions as follows:
|
||||
//
|
||||
// * If no scheme is provided, `https` is assumed.
|
||||
// * An HTTP GET on the URL must yield a [google.protobuf.Type][]
|
||||
// value in binary format, or produce an error.
|
||||
// * Applications are allowed to cache lookup results based on the
|
||||
// URL, or have them precompiled into a binary to avoid any
|
||||
// lookup. Therefore, binary compatibility needs to be preserved
|
||||
// on changes to types. (Use versioned type names to manage
|
||||
// breaking changes.)
|
||||
//
|
||||
// Note: this functionality is not currently available in the official
|
||||
// protobuf release, and it is not used for type URLs beginning with
|
||||
// type.googleapis.com.
|
||||
//
|
||||
// Schemes other than `http`, `https` (or the empty scheme) might be
|
||||
// used with implementation specific semantics.
|
||||
//
|
||||
string type_url = 1;
|
||||
|
||||
// Must be a valid serialized protocol buffer of the above specified type.
|
||||
bytes value = 2;
|
||||
}
|
@ -1,207 +0,0 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package google.protobuf;
|
||||
|
||||
import "google/protobuf/source_context.proto";
|
||||
import "google/protobuf/type.proto";
|
||||
|
||||
option java_package = "com.google.protobuf";
|
||||
option java_outer_classname = "ApiProto";
|
||||
option java_multiple_files = true;
|
||||
option objc_class_prefix = "GPB";
|
||||
option csharp_namespace = "Google.Protobuf.WellKnownTypes";
|
||||
option go_package = "google.golang.org/protobuf/types/known/apipb";
|
||||
|
||||
// Api is a light-weight descriptor for an API Interface.
|
||||
//
|
||||
// Interfaces are also described as "protocol buffer services" in some contexts,
|
||||
// such as by the "service" keyword in a .proto file, but they are different
|
||||
// from API Services, which represent a concrete implementation of an interface
|
||||
// as opposed to simply a description of methods and bindings. They are also
|
||||
// sometimes simply referred to as "APIs" in other contexts, such as the name of
|
||||
// this message itself. See https://cloud.google.com/apis/design/glossary for
|
||||
// detailed terminology.
|
||||
message Api {
|
||||
// The fully qualified name of this interface, including package name
|
||||
// followed by the interface's simple name.
|
||||
string name = 1;
|
||||
|
||||
// The methods of this interface, in unspecified order.
|
||||
repeated Method methods = 2;
|
||||
|
||||
// Any metadata attached to the interface.
|
||||
repeated Option options = 3;
|
||||
|
||||
// A version string for this interface. If specified, must have the form
|
||||
// `major-version.minor-version`, as in `1.10`. If the minor version is
|
||||
// omitted, it defaults to zero. If the entire version field is empty, the
|
||||
// major version is derived from the package name, as outlined below. If the
|
||||
// field is not empty, the version in the package name will be verified to be
|
||||
// consistent with what is provided here.
|
||||
//
|
||||
// The versioning schema uses [semantic
|
||||
// versioning](http://semver.org) where the major version number
|
||||
// indicates a breaking change and the minor version an additive,
|
||||
// non-breaking change. Both version numbers are signals to users
|
||||
// what to expect from different versions, and should be carefully
|
||||
// chosen based on the product plan.
|
||||
//
|
||||
// The major version is also reflected in the package name of the
|
||||
// interface, which must end in `v<major-version>`, as in
|
||||
// `google.feature.v1`. For major versions 0 and 1, the suffix can
|
||||
// be omitted. Zero major versions must only be used for
|
||||
// experimental, non-GA interfaces.
|
||||
//
|
||||
string version = 4;
|
||||
|
||||
// Source context for the protocol buffer service represented by this
|
||||
// message.
|
||||
SourceContext source_context = 5;
|
||||
|
||||
// Included interfaces. See [Mixin][].
|
||||
repeated Mixin mixins = 6;
|
||||
|
||||
// The source syntax of the service.
|
||||
Syntax syntax = 7;
|
||||
}
|
||||
|
||||
// Method represents a method of an API interface.
|
||||
message Method {
|
||||
// The simple name of this method.
|
||||
string name = 1;
|
||||
|
||||
// A URL of the input message type.
|
||||
string request_type_url = 2;
|
||||
|
||||
// If true, the request is streamed.
|
||||
bool request_streaming = 3;
|
||||
|
||||
// The URL of the output message type.
|
||||
string response_type_url = 4;
|
||||
|
||||
// If true, the response is streamed.
|
||||
bool response_streaming = 5;
|
||||
|
||||
// Any metadata attached to the method.
|
||||
repeated Option options = 6;
|
||||
|
||||
// The source syntax of this method.
|
||||
Syntax syntax = 7;
|
||||
}
|
||||
|
||||
// Declares an API Interface to be included in this interface. The including
|
||||
// interface must redeclare all the methods from the included interface, but
|
||||
// documentation and options are inherited as follows:
|
||||
//
|
||||
// - If after comment and whitespace stripping, the documentation
|
||||
// string of the redeclared method is empty, it will be inherited
|
||||
// from the original method.
|
||||
//
|
||||
// - Each annotation belonging to the service config (http,
|
||||
// visibility) which is not set in the redeclared method will be
|
||||
// inherited.
|
||||
//
|
||||
// - If an http annotation is inherited, the path pattern will be
|
||||
// modified as follows. Any version prefix will be replaced by the
|
||||
// version of the including interface plus the [root][] path if
|
||||
// specified.
|
||||
//
|
||||
// Example of a simple mixin:
|
||||
//
|
||||
// package google.acl.v1;
|
||||
// service AccessControl {
|
||||
// // Get the underlying ACL object.
|
||||
// rpc GetAcl(GetAclRequest) returns (Acl) {
|
||||
// option (google.api.http).get = "/v1/{resource=**}:getAcl";
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// package google.storage.v2;
|
||||
// service Storage {
|
||||
// rpc GetAcl(GetAclRequest) returns (Acl);
|
||||
//
|
||||
// // Get a data record.
|
||||
// rpc GetData(GetDataRequest) returns (Data) {
|
||||
// option (google.api.http).get = "/v2/{resource=**}";
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Example of a mixin configuration:
|
||||
//
|
||||
// apis:
|
||||
// - name: google.storage.v2.Storage
|
||||
// mixins:
|
||||
// - name: google.acl.v1.AccessControl
|
||||
//
|
||||
// The mixin construct implies that all methods in `AccessControl` are
|
||||
// also declared with same name and request/response types in
|
||||
// `Storage`. A documentation generator or annotation processor will
|
||||
// see the effective `Storage.GetAcl` method after inheriting
|
||||
// documentation and annotations as follows:
|
||||
//
|
||||
// service Storage {
|
||||
// // Get the underlying ACL object.
|
||||
// rpc GetAcl(GetAclRequest) returns (Acl) {
|
||||
// option (google.api.http).get = "/v2/{resource=**}:getAcl";
|
||||
// }
|
||||
// ...
|
||||
// }
|
||||
//
|
||||
// Note how the version in the path pattern changed from `v1` to `v2`.
|
||||
//
|
||||
// If the `root` field in the mixin is specified, it should be a
|
||||
// relative path under which inherited HTTP paths are placed. Example:
|
||||
//
|
||||
// apis:
|
||||
// - name: google.storage.v2.Storage
|
||||
// mixins:
|
||||
// - name: google.acl.v1.AccessControl
|
||||
// root: acls
|
||||
//
|
||||
// This implies the following inherited HTTP annotation:
|
||||
//
|
||||
// service Storage {
|
||||
// // Get the underlying ACL object.
|
||||
// rpc GetAcl(GetAclRequest) returns (Acl) {
|
||||
// option (google.api.http).get = "/v2/acls/{resource=**}:getAcl";
|
||||
// }
|
||||
// ...
|
||||
// }
|
||||
message Mixin {
|
||||
// The fully qualified name of the interface which is included.
|
||||
string name = 1;
|
||||
|
||||
// If non-empty specifies a path under which inherited HTTP paths
|
||||
// are rooted.
|
||||
string root = 2;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user