目录结构及编译调整
This commit is contained in:
parent
218b1b5922
commit
f44ecb69b8
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(): string;
|
||||||
|
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;
|
||||||
|
}
|
601
lib/app/JlGraphicApp.d.ts
vendored
Normal file
601
lib/app/JlGraphicApp.d.ts
vendored
Normal file
@ -0,0 +1,601 @@
|
|||||||
|
/// <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;
|
||||||
|
}
|
||||||
|
export declare class CanvasData implements ICanvasProperties {
|
||||||
|
width: number;
|
||||||
|
height: number;
|
||||||
|
backgroundColor: string;
|
||||||
|
viewportTransform: GraphicTransform;
|
||||||
|
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;
|
||||||
|
nonInteractiveContainer: Container;
|
||||||
|
assistantAppendContainer: Container;
|
||||||
|
constructor(scene: IGraphicScene, properties?: CanvasData);
|
||||||
|
/**
|
||||||
|
* 图形重绘(数据/状态变化时触发)
|
||||||
|
*/
|
||||||
|
repaint(): void;
|
||||||
|
get width(): number;
|
||||||
|
get height(): number;
|
||||||
|
get backgroundColor(): string;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
/**
|
||||||
|
* 处理图形状态
|
||||||
|
* @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 } 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, };
|
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;
|
||||||
|
}
|
90
lib/core/GraphicStore.d.ts
vendored
Normal file
90
lib/core/GraphicStore.d.ts
vendored
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
import { RelationManage } from './GraphicRelation';
|
||||||
|
import { JlGraphic } from './JlGraphic';
|
||||||
|
export interface GraphicQueryStore {
|
||||||
|
/**
|
||||||
|
* 获取所有图形对象
|
||||||
|
*/
|
||||||
|
getAllGraphics(): JlGraphic[];
|
||||||
|
/**
|
||||||
|
* 根据id获取图形
|
||||||
|
*/
|
||||||
|
queryById<T extends JlGraphic>(id: string): T;
|
||||||
|
/**
|
||||||
|
* 根据id模糊查询图形
|
||||||
|
* @param id
|
||||||
|
*/
|
||||||
|
queryByIdAmbiguous(id: 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): JlGraphic[];
|
||||||
|
/**
|
||||||
|
* 根据id或code及类型查询图形
|
||||||
|
* @param v
|
||||||
|
* @param type
|
||||||
|
*/
|
||||||
|
queryByIdOrCodeAndType(v: string, 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[];
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 图形存储
|
||||||
|
*/
|
||||||
|
export declare class GraphicStore implements GraphicQueryStore {
|
||||||
|
store: Map<string, JlGraphic>;
|
||||||
|
relationManage: RelationManage;
|
||||||
|
constructor();
|
||||||
|
/**
|
||||||
|
* 获取所有图形对象
|
||||||
|
*/
|
||||||
|
getAllGraphics(): JlGraphic[];
|
||||||
|
queryById<T extends JlGraphic>(id: string): T;
|
||||||
|
queryByIdAmbiguous(id: string): JlGraphic[];
|
||||||
|
queryByType<T extends JlGraphic>(type: string): T[];
|
||||||
|
queryByCode(code: string): JlGraphic[] | undefined;
|
||||||
|
queryByCodeAmbiguous(code: string): JlGraphic[];
|
||||||
|
queryByIdOrCode(s: string): JlGraphic[];
|
||||||
|
queryByIdOrCodeAndType(s: string, 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;
|
||||||
|
}
|
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(): string;
|
||||||
|
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(): string;
|
||||||
|
set id(v: string);
|
||||||
|
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): boolean;
|
||||||
|
/**
|
||||||
|
* 获取图形id,如果图形数据对象存在,则返回图形数据对象id
|
||||||
|
*/
|
||||||
|
get id(): string;
|
||||||
|
/**
|
||||||
|
* 设置图形id,如果图形数据存在,则同时设置图形数据id
|
||||||
|
*/
|
||||||
|
set id(v: string);
|
||||||
|
/**
|
||||||
|
* 获取图形业务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 default 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;
|
||||||
|
}
|
0
src/jlgraphic/index.ts → lib/index.d.ts
vendored
0
src/jlgraphic/index.ts → lib/index.d.ts
vendored
6575
lib/index.js
6575
lib/index.js
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 default 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';
|
52
lib/message/BasicMessageClient.d.ts
vendored
Normal file
52
lib/message/BasicMessageClient.d.ts
vendored
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
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;
|
||||||
|
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;
|
||||||
|
handleMessage(data: any): void;
|
||||||
|
onDisconnect(): void;
|
||||||
|
}
|
146
lib/message/MessageBroker.d.ts
vendored
Normal file
146
lib/message/MessageBroker.d.ts
vendored
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
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;
|
||||||
|
/**
|
||||||
|
* 是否已经连接
|
||||||
|
*/
|
||||||
|
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 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;
|
||||||
|
/**
|
||||||
|
* 取消所有订阅,从通用Stomp客户端移除此消息代理
|
||||||
|
*/
|
||||||
|
close(): void;
|
||||||
|
}
|
||||||
|
export {};
|
13
lib/message/MqttBroker.d.ts
vendored
Normal file
13
lib/message/MqttBroker.d.ts
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
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;
|
||||||
|
}
|
11
lib/message/WsMsgBroker.d.ts
vendored
Normal file
11
lib/message/WsMsgBroker.d.ts
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
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;
|
||||||
|
close(): void;
|
||||||
|
}
|
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<string, 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 {};
|
23
lib/plugins/CopyPlugin.d.ts
vendored
Normal file
23
lib/plugins/CopyPlugin.d.ts
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import { Container, FederatedPointerEvent, Point } from 'pixi.js';
|
||||||
|
import { IGraphicScene } from '../app';
|
||||||
|
import { JlGraphic } from '../core';
|
||||||
|
import { KeyListener } from './KeyboardPlugin';
|
||||||
|
/**
|
||||||
|
* 图形复制插件
|
||||||
|
*/
|
||||||
|
export declare class GraphicCopyPlugin {
|
||||||
|
container: Container;
|
||||||
|
scene: IGraphicScene;
|
||||||
|
keyListeners: KeyListener[];
|
||||||
|
copys: JlGraphic[];
|
||||||
|
start?: Point;
|
||||||
|
running: boolean;
|
||||||
|
moveLimit?: 'x' | 'y';
|
||||||
|
constructor(scene: IGraphicScene);
|
||||||
|
updateMoveLimit(limit?: 'x' | 'y'): void;
|
||||||
|
init(): void;
|
||||||
|
clear(): void;
|
||||||
|
onPointerMove(e: FederatedPointerEvent): void;
|
||||||
|
onFinish(): void;
|
||||||
|
cancle(): void;
|
||||||
|
}
|
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 {};
|
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;
|
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;
|
||||||
|
}
|
@ -6,7 +6,7 @@
|
|||||||
"author": "walker <shengxuqiang@joylink.club>",
|
"author": "walker <shengxuqiang@joylink.club>",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/jlgraphic",
|
"main": "lib",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "rollup -c rollup.config.ts --configPlugin typescript"
|
"build": "rollup -c rollup.config.ts --configPlugin typescript"
|
||||||
},
|
},
|
||||||
|
@ -3,14 +3,21 @@ import typescript from '@rollup/plugin-typescript'
|
|||||||
|
|
||||||
|
|
||||||
const config: RollupOptions = {
|
const config: RollupOptions = {
|
||||||
input: 'src/jlgraphic/index.ts',
|
input: 'src/index.ts',
|
||||||
output: {
|
output: {
|
||||||
file: 'lib/index.js',
|
dir: 'lib',
|
||||||
format: 'cjs',
|
format: 'esm',
|
||||||
},
|
},
|
||||||
|
external: [
|
||||||
|
'pixi.js', 'pixi-viewport', '@stomp/stompjs', 'mqtt', 'eventemitter3'
|
||||||
|
],
|
||||||
|
logLevel: 'debug',
|
||||||
plugins: [
|
plugins: [
|
||||||
typescript({
|
typescript({
|
||||||
|
declaration: true,
|
||||||
|
declarationDir: 'lib',
|
||||||
|
include: ['src/**/*'],
|
||||||
|
tsconfig: './tsconfig.json',
|
||||||
})
|
})
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
@ -719,7 +719,6 @@ abstract class GraphicSceneBase
|
|||||||
* @param options
|
* @param options
|
||||||
*/
|
*/
|
||||||
setOptions(options: GraphicAppOptions) {
|
setOptions(options: GraphicAppOptions) {
|
||||||
// console.log('更新选项', options);
|
|
||||||
if (this._options) {
|
if (this._options) {
|
||||||
this._options = Object.assign(this._options, options);
|
this._options = Object.assign(this._options, options);
|
||||||
} else {
|
} else {
|
||||||
@ -807,13 +806,6 @@ abstract class GraphicSceneBase
|
|||||||
this.pixi.resizeTo = dom;
|
this.pixi.resizeTo = dom;
|
||||||
dom.appendChild(this.pixi.view as unknown as Node);
|
dom.appendChild(this.pixi.view as unknown as Node);
|
||||||
this._viewportResizer = setInterval(() => {
|
this._viewportResizer = setInterval(() => {
|
||||||
// console.log(
|
|
||||||
// 'dom resize ',
|
|
||||||
// dom.style.width,
|
|
||||||
// dom.style.height,
|
|
||||||
// dom.clientWidth,
|
|
||||||
// dom.clientHeight
|
|
||||||
// );
|
|
||||||
this.updateViewport(dom.clientWidth, dom.clientHeight);
|
this.updateViewport(dom.clientWidth, dom.clientHeight);
|
||||||
}, 1000);
|
}, 1000);
|
||||||
// 恢复
|
// 恢复
|
||||||
@ -838,7 +830,6 @@ abstract class GraphicSceneBase
|
|||||||
for (const item of this.graphicTemplateMap) {
|
for (const item of this.graphicTemplateMap) {
|
||||||
await item[1].loadAssets();
|
await item[1].loadAssets();
|
||||||
}
|
}
|
||||||
// console.log('开始加载proto数据', protos);
|
|
||||||
// 加载数据到图形存储
|
// 加载数据到图形存储
|
||||||
protos.forEach((proto) => {
|
protos.forEach((proto) => {
|
||||||
const template = this.getGraphicTemplatesByType(proto.graphicType);
|
const template = this.getGraphicTemplatesByType(proto.graphicType);
|
||||||
@ -855,7 +846,6 @@ abstract class GraphicSceneBase
|
|||||||
.map((g) => g.id)
|
.map((g) => g.id)
|
||||||
.sort((a, b) => a - b)
|
.sort((a, b) => a - b)
|
||||||
.pop() ?? 0;
|
.pop() ?? 0;
|
||||||
// console.log('最大值', max)
|
|
||||||
GraphicIdGenerator.initSerial(max);
|
GraphicIdGenerator.initSerial(max);
|
||||||
// 数据加载完成后
|
// 数据加载完成后
|
||||||
this.emit('postdataloaded');
|
this.emit('postdataloaded');
|
||||||
@ -900,11 +890,9 @@ abstract class GraphicSceneBase
|
|||||||
}
|
}
|
||||||
if (graphic.eventMode == 'static' || graphic.eventMode == 'dynamic') {
|
if (graphic.eventMode == 'static' || graphic.eventMode == 'dynamic') {
|
||||||
// 添加为可交互
|
// 添加为可交互
|
||||||
// console.log(`type=${graphic.type}的图形添加到交互容器`);
|
|
||||||
this.canvas.addChild(graphic);
|
this.canvas.addChild(graphic);
|
||||||
} else {
|
} else {
|
||||||
// 添加到不可交互容器
|
// 添加到不可交互容器
|
||||||
// console.log(`type=${graphic.type}的图形添加到无交互容器`);
|
|
||||||
this.canvas.addNonInteractiveChild(graphic);
|
this.canvas.addNonInteractiveChild(graphic);
|
||||||
}
|
}
|
||||||
graphic.repaint();
|
graphic.repaint();
|
||||||
@ -1253,7 +1241,6 @@ export class GraphicApp extends GraphicSceneBase implements IGraphicApp {
|
|||||||
|
|
||||||
constructor(options: GraphicAppOptions) {
|
constructor(options: GraphicAppOptions) {
|
||||||
super(options);
|
super(options);
|
||||||
// console.log('创建图形App')
|
|
||||||
this.opRecord = new OperationRecord();
|
this.opRecord = new OperationRecord();
|
||||||
// 绑定键盘监听
|
// 绑定键盘监听
|
||||||
this.keyboardPlugin = new JlGraphicAppKeyboardPlugin(this);
|
this.keyboardPlugin = new JlGraphicAppKeyboardPlugin(this);
|
||||||
@ -1264,7 +1251,6 @@ export class GraphicApp extends GraphicSceneBase implements IGraphicApp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setOptions(options: GraphicAppOptions) {
|
setOptions(options: GraphicAppOptions) {
|
||||||
// console.log('更新选项', options);
|
|
||||||
if (options.maxOperationRecords && options.maxOperationRecords > 0) {
|
if (options.maxOperationRecords && options.maxOperationRecords > 0) {
|
||||||
this.opRecord.setMaxLen(options.maxOperationRecords);
|
this.opRecord.setMaxLen(options.maxOperationRecords);
|
||||||
}
|
}
|
@ -20,7 +20,6 @@ export class IdGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
initSerial(serial: number): void {
|
initSerial(serial: number): void {
|
||||||
// console.log(serial)
|
|
||||||
this.serial = serial;
|
this.serial = serial;
|
||||||
}
|
}
|
||||||
}
|
}
|
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';
|
5
src/graphic/index.ts
Normal file
5
src/graphic/index.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
export * from './VectorGraphic';
|
||||||
|
export * from './VectorText';
|
||||||
|
export * from './DraggablePoint';
|
||||||
|
export * from './AbsorbablePosition';
|
||||||
|
export * from './DashedLine';
|
@ -1,51 +0,0 @@
|
|||||||
import { Graphics } from 'pixi.js';
|
|
||||||
export function drawArrow(
|
|
||||||
polygon: Graphics,
|
|
||||||
x: number,
|
|
||||||
y: number,
|
|
||||||
length: number,
|
|
||||||
radius: number,
|
|
||||||
lineWidth: number
|
|
||||||
) {
|
|
||||||
const trianglAcme = { x, y };
|
|
||||||
const triangleP1 = {
|
|
||||||
x: x - radius - Math.sin(Math.PI / 6),
|
|
||||||
y: y + Math.cos(Math.PI / 6) * radius,
|
|
||||||
};
|
|
||||||
const triangleP2 = {
|
|
||||||
x: x - radius - Math.sin(Math.PI / 6),
|
|
||||||
y: y - Math.cos(Math.PI / 6) * radius,
|
|
||||||
};
|
|
||||||
const lineP1 = {
|
|
||||||
x: x - radius - Math.sin(Math.PI / 6),
|
|
||||||
y: y + lineWidth / 2,
|
|
||||||
};
|
|
||||||
const lineP2 = {
|
|
||||||
x: x - length,
|
|
||||||
y: y + lineWidth / 2,
|
|
||||||
};
|
|
||||||
const lineP3 = {
|
|
||||||
x: x - length,
|
|
||||||
y: y - lineWidth / 2,
|
|
||||||
};
|
|
||||||
const lineP4 = {
|
|
||||||
x: x - radius - Math.sin(Math.PI / 6),
|
|
||||||
y: y - lineWidth / 2,
|
|
||||||
};
|
|
||||||
polygon.drawPolygon(
|
|
||||||
trianglAcme.x,
|
|
||||||
trianglAcme.y,
|
|
||||||
triangleP1.x,
|
|
||||||
triangleP1.y,
|
|
||||||
lineP1.x,
|
|
||||||
lineP1.y,
|
|
||||||
lineP2.x,
|
|
||||||
lineP2.y,
|
|
||||||
lineP3.x,
|
|
||||||
lineP3.y,
|
|
||||||
lineP4.x,
|
|
||||||
lineP4.y,
|
|
||||||
triangleP2.x,
|
|
||||||
triangleP2.y
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,139 +0,0 @@
|
|||||||
import {
|
|
||||||
GraphicAnimation,
|
|
||||||
GraphicData,
|
|
||||||
GraphicState,
|
|
||||||
JlGraphic,
|
|
||||||
JlGraphicTemplate,
|
|
||||||
} from 'src/jlgraphic';
|
|
||||||
import ISCS_FAN_Assets from './iscs-fan-spritesheet.png';
|
|
||||||
import ISCS_FAN_JSON from './iscs-fan-data.json';
|
|
||||||
|
|
||||||
import { Assets, Sprite, Spritesheet, Texture } from 'pixi.js';
|
|
||||||
|
|
||||||
interface FanTextures {
|
|
||||||
border: Texture;
|
|
||||||
blue: Texture;
|
|
||||||
gray: Texture;
|
|
||||||
green: Texture;
|
|
||||||
red: Texture;
|
|
||||||
yellow: Texture;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IIscsFanData extends GraphicData {
|
|
||||||
get code(): string;
|
|
||||||
set code(v: string);
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IIscsFanState extends GraphicState {
|
|
||||||
get state(): number;
|
|
||||||
set state(v: number);
|
|
||||||
}
|
|
||||||
|
|
||||||
export class IscsFan extends JlGraphic {
|
|
||||||
static Type = 'IscsFan';
|
|
||||||
_border: Sprite;
|
|
||||||
_fan: Sprite;
|
|
||||||
fanTextures: FanTextures;
|
|
||||||
|
|
||||||
constructor(fanTextures: FanTextures) {
|
|
||||||
super(IscsFan.Type);
|
|
||||||
this.fanTextures = fanTextures;
|
|
||||||
this._border = new Sprite();
|
|
||||||
this._border.texture = this.fanTextures.border;
|
|
||||||
this._border.anchor.set(0.5);
|
|
||||||
this._fan = new Sprite();
|
|
||||||
this._fan.texture = this.fanTextures.gray;
|
|
||||||
this._fan.anchor.set(0.5);
|
|
||||||
this.addChild(this._border);
|
|
||||||
this.addChild(this._fan);
|
|
||||||
}
|
|
||||||
get states(): IIscsFanState {
|
|
||||||
return this.getStates<IIscsFanState>();
|
|
||||||
}
|
|
||||||
doRepaint(): void {
|
|
||||||
if (this.states.state === 0) {
|
|
||||||
// 停止
|
|
||||||
this.stopFanRun();
|
|
||||||
this._fan.rotation = 0;
|
|
||||||
this._fan.texture = this.fanTextures.gray;
|
|
||||||
} else if (this.states.state === 1) {
|
|
||||||
// 正常运行
|
|
||||||
this._fan.texture = this.fanTextures.green;
|
|
||||||
// 动画
|
|
||||||
this.initFanRun();
|
|
||||||
} else if (this.states.state === 2) {
|
|
||||||
// 报警运行
|
|
||||||
this._fan.texture = this.fanTextures.yellow;
|
|
||||||
// 动画
|
|
||||||
this.initFanRun();
|
|
||||||
} else if (this.states.state === 3) {
|
|
||||||
// 故障
|
|
||||||
this.stopFanRun();
|
|
||||||
this._fan.rotation = 0;
|
|
||||||
this._fan.texture = this.fanTextures.red;
|
|
||||||
} else if (this.states.state === 4) {
|
|
||||||
// 通信故障
|
|
||||||
// 停止
|
|
||||||
this.stopFanRun();
|
|
||||||
this._fan.rotation = 0;
|
|
||||||
this._fan.texture = this.fanTextures.blue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
initFanRun() {
|
|
||||||
// 动画
|
|
||||||
const name = 'fan_run';
|
|
||||||
let fanRun = this.animation(name);
|
|
||||||
if (!fanRun) {
|
|
||||||
fanRun = GraphicAnimation.init({
|
|
||||||
name: 'fan_run',
|
|
||||||
run: (dt: number) => {
|
|
||||||
this._fan.angle = (this._fan.angle + dt) % 360;
|
|
||||||
},
|
|
||||||
});
|
|
||||||
this.addAnimation(fanRun);
|
|
||||||
}
|
|
||||||
const speed = Math.round(Math.random() * 10) + 1;
|
|
||||||
fanRun.xSpeed = speed;
|
|
||||||
fanRun.resume();
|
|
||||||
}
|
|
||||||
stopFanRun() {
|
|
||||||
const name = 'fan_run';
|
|
||||||
const fanRun = this.animation(name);
|
|
||||||
if (fanRun) {
|
|
||||||
fanRun.pause();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class IscsFanTemplate extends JlGraphicTemplate<IscsFan> {
|
|
||||||
fanTextures?: FanTextures;
|
|
||||||
constructor(dataTemplate: IIscsFanData, stateTemplate: IIscsFanState) {
|
|
||||||
super(IscsFan.Type, {
|
|
||||||
dataTemplate,
|
|
||||||
stateTemplate,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
new(): IscsFan {
|
|
||||||
if (this.fanTextures) {
|
|
||||||
const g = new IscsFan(this.fanTextures);
|
|
||||||
g.loadData(this.datas);
|
|
||||||
g.loadState(this.states);
|
|
||||||
return g;
|
|
||||||
}
|
|
||||||
throw new Error('资源未加载/加载失败');
|
|
||||||
}
|
|
||||||
async loadAssets(): Promise<FanTextures> {
|
|
||||||
const texture = await Assets.load(ISCS_FAN_Assets);
|
|
||||||
const iscsFanSheet = new Spritesheet(texture, ISCS_FAN_JSON);
|
|
||||||
const result = await iscsFanSheet.parse();
|
|
||||||
this.fanTextures = {
|
|
||||||
border: result['fan-border.png'],
|
|
||||||
blue: result['fan-blue.png'],
|
|
||||||
gray: result['fan-gray.png'],
|
|
||||||
green: result['fan-green.png'],
|
|
||||||
red: result['fan-red.png'],
|
|
||||||
yellow: result['fan-yellow.png'],
|
|
||||||
};
|
|
||||||
return this.fanTextures as FanTextures;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,109 +0,0 @@
|
|||||||
import { FederatedMouseEvent, Point } from 'pixi.js';
|
|
||||||
import {
|
|
||||||
AbsorbableLine,
|
|
||||||
AbsorbablePosition,
|
|
||||||
GraphicDrawAssistant,
|
|
||||||
GraphicInteractionPlugin,
|
|
||||||
GraphicTransformEvent,
|
|
||||||
JlDrawApp,
|
|
||||||
JlGraphic,
|
|
||||||
} from 'src/jlgraphic';
|
|
||||||
import { IIscsFanData, IscsFan, IscsFanTemplate } from './IscsFan';
|
|
||||||
|
|
||||||
export class IscsFanDraw extends GraphicDrawAssistant<
|
|
||||||
IscsFanTemplate,
|
|
||||||
IIscsFanData
|
|
||||||
> {
|
|
||||||
_iscsFan: IscsFan | null = null;
|
|
||||||
|
|
||||||
constructor(app: JlDrawApp, template: IscsFanTemplate) {
|
|
||||||
super(app, template, IscsFan.Type, '风机');
|
|
||||||
IscsFanInteraction.init(app);
|
|
||||||
}
|
|
||||||
|
|
||||||
bind(): void {
|
|
||||||
super.bind();
|
|
||||||
if (!this._iscsFan) {
|
|
||||||
this._iscsFan = this.graphicTemplate.new();
|
|
||||||
this.container.addChild(this._iscsFan);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public get iscsFan(): IscsFan {
|
|
||||||
if (!this._iscsFan) {
|
|
||||||
throw new Error('风机绘制逻辑异常');
|
|
||||||
}
|
|
||||||
return this._iscsFan;
|
|
||||||
}
|
|
||||||
|
|
||||||
redraw(cp: Point): void {
|
|
||||||
this.iscsFan.position.copyFrom(cp);
|
|
||||||
}
|
|
||||||
onLeftUp(e: FederatedMouseEvent): void {
|
|
||||||
this.iscsFan.position.copyFrom(this.toCanvasCoordinates(e.global));
|
|
||||||
this.createAndStore(false);
|
|
||||||
}
|
|
||||||
prepareData(data: IIscsFanData): boolean {
|
|
||||||
data.transform = this.iscsFan.saveTransform();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
onEsc(): void {
|
|
||||||
this.finish();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class IscsFanInteraction extends GraphicInteractionPlugin<IscsFan> {
|
|
||||||
static Name = 'iscs_fan_transform';
|
|
||||||
constructor(app: JlDrawApp) {
|
|
||||||
super(IscsFanInteraction.Name, app);
|
|
||||||
}
|
|
||||||
static init(app: JlDrawApp) {
|
|
||||||
return new IscsFanInteraction(app);
|
|
||||||
}
|
|
||||||
filter(...grahpics: JlGraphic[]): IscsFan[] | undefined {
|
|
||||||
return grahpics
|
|
||||||
.filter((g) => g.type === IscsFan.Type)
|
|
||||||
.map((g) => g as IscsFan);
|
|
||||||
}
|
|
||||||
bind(g: IscsFan): void {
|
|
||||||
g.eventMode = 'static';
|
|
||||||
g.cursor = 'pointer';
|
|
||||||
// g.scalable = true;
|
|
||||||
g.rotatable = true;
|
|
||||||
g.on('drag-start', () => {
|
|
||||||
console.log('风机拖拽');
|
|
||||||
});
|
|
||||||
g.on('transformstart', (e: GraphicTransformEvent) => {
|
|
||||||
if (e.isShift()) {
|
|
||||||
g.getGraphicApp().setOptions({
|
|
||||||
absorbablePositions: buildAbsorbablePositions(g),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
unbind(g: IscsFan): void {
|
|
||||||
g.eventMode = 'none';
|
|
||||||
// g.scalable = false;
|
|
||||||
g.rotatable = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildAbsorbablePositions(
|
|
||||||
g: IscsFan
|
|
||||||
): AbsorbablePosition[] | undefined {
|
|
||||||
const app = g.getGraphicApp();
|
|
||||||
const canvas = app.canvas;
|
|
||||||
const store = app.queryStore;
|
|
||||||
const aps: AbsorbablePosition[] = [];
|
|
||||||
store.queryByType(IscsFan.Type).forEach((fan) => {
|
|
||||||
if (fan.id === g.id) return;
|
|
||||||
const p = fan.position;
|
|
||||||
aps.push(
|
|
||||||
new AbsorbableLine(new Point(0, p.y), new Point(canvas.width, p.y))
|
|
||||||
);
|
|
||||||
aps.push(
|
|
||||||
new AbsorbableLine(new Point(p.x, 0), new Point(p.x, canvas.height))
|
|
||||||
);
|
|
||||||
});
|
|
||||||
return aps;
|
|
||||||
}
|
|
@ -1,66 +0,0 @@
|
|||||||
{"frames": {
|
|
||||||
|
|
||||||
"fan-blue.png":
|
|
||||||
{
|
|
||||||
"frame": {"x":0,"y":0,"w":41,"h":41},
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": false,
|
|
||||||
"spriteSourceSize": {"x":0,"y":0,"w":41,"h":41},
|
|
||||||
"sourceSize": {"w":41,"h":41},
|
|
||||||
"anchor": {"x":0.5,"y":0.5}
|
|
||||||
},
|
|
||||||
"fan-border.png":
|
|
||||||
{
|
|
||||||
"frame": {"x":41,"y":0,"w":41,"h":41},
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": false,
|
|
||||||
"spriteSourceSize": {"x":0,"y":0,"w":41,"h":41},
|
|
||||||
"sourceSize": {"w":41,"h":41},
|
|
||||||
"anchor": {"x":0.5,"y":0.5}
|
|
||||||
},
|
|
||||||
"fan-gray.png":
|
|
||||||
{
|
|
||||||
"frame": {"x":82,"y":0,"w":41,"h":41},
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": false,
|
|
||||||
"spriteSourceSize": {"x":0,"y":0,"w":41,"h":41},
|
|
||||||
"sourceSize": {"w":41,"h":41},
|
|
||||||
"anchor": {"x":0.5,"y":0.5}
|
|
||||||
},
|
|
||||||
"fan-green.png":
|
|
||||||
{
|
|
||||||
"frame": {"x":123,"y":0,"w":41,"h":41},
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": false,
|
|
||||||
"spriteSourceSize": {"x":0,"y":0,"w":41,"h":41},
|
|
||||||
"sourceSize": {"w":41,"h":41},
|
|
||||||
"anchor": {"x":0.5,"y":0.5}
|
|
||||||
},
|
|
||||||
"fan-red.png":
|
|
||||||
{
|
|
||||||
"frame": {"x":164,"y":0,"w":41,"h":41},
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": false,
|
|
||||||
"spriteSourceSize": {"x":0,"y":0,"w":41,"h":41},
|
|
||||||
"sourceSize": {"w":41,"h":41},
|
|
||||||
"anchor": {"x":0.5,"y":0.5}
|
|
||||||
},
|
|
||||||
"fan-yellow.png":
|
|
||||||
{
|
|
||||||
"frame": {"x":205,"y":0,"w":41,"h":41},
|
|
||||||
"rotated": false,
|
|
||||||
"trimmed": false,
|
|
||||||
"spriteSourceSize": {"x":0,"y":0,"w":41,"h":41},
|
|
||||||
"sourceSize": {"w":41,"h":41},
|
|
||||||
"anchor": {"x":0.5,"y":0.5}
|
|
||||||
}},
|
|
||||||
"meta": {
|
|
||||||
"app": "https://www.codeandweb.com/texturepacker",
|
|
||||||
"version": "1.1",
|
|
||||||
"image": "test-iscs-fan.png",
|
|
||||||
"format": "RGBA8888",
|
|
||||||
"size": {"w":246,"h":41},
|
|
||||||
"scale": "1",
|
|
||||||
"smartupdate": "$TexturePacker:SmartUpdate:e7620bd2d73cc0b3e2deea9704e7eefc:f129a1d9e4b9ba57720b3861c22b155b:eb2d421f7759984b7713aa4aa5354134$"
|
|
||||||
}
|
|
||||||
}
|
|
Binary file not shown.
Before Width: | Height: | Size: 16 KiB |
@ -1,104 +0,0 @@
|
|||||||
import { Color, Graphics, IPointData } from 'pixi.js';
|
|
||||||
import {
|
|
||||||
GraphicData,
|
|
||||||
JlGraphic,
|
|
||||||
JlGraphicTemplate,
|
|
||||||
convertToBezierParams,
|
|
||||||
} from 'src/jlgraphic';
|
|
||||||
import { ILineGraphic } from 'src/jlgraphic/plugins/GraphicEditPlugin';
|
|
||||||
|
|
||||||
export interface ILinkData extends GraphicData {
|
|
||||||
get code(): string; // 编号
|
|
||||||
set code(v: string);
|
|
||||||
get curve(): boolean; // 是否曲线
|
|
||||||
set curve(v: boolean);
|
|
||||||
get segmentsCount(): number; // 曲线分段数
|
|
||||||
set segmentsCount(v: number);
|
|
||||||
get points(): IPointData[]; // 线坐标点
|
|
||||||
set points(points: IPointData[]);
|
|
||||||
get lineWidth(): number; // 线宽
|
|
||||||
set lineWidth(v: number);
|
|
||||||
get lineColor(): string; // 线色
|
|
||||||
set lineColor(v: string);
|
|
||||||
clone(): ILinkData;
|
|
||||||
copyFrom(data: ILinkData): void;
|
|
||||||
eq(other: ILinkData): boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Link extends JlGraphic implements ILineGraphic {
|
|
||||||
static Type = 'Link';
|
|
||||||
lineGraphic: Graphics;
|
|
||||||
constructor() {
|
|
||||||
super(Link.Type);
|
|
||||||
this.lineGraphic = new Graphics();
|
|
||||||
this.addChild(this.lineGraphic);
|
|
||||||
}
|
|
||||||
|
|
||||||
get datas(): ILinkData {
|
|
||||||
return this.getDatas<ILinkData>();
|
|
||||||
}
|
|
||||||
doRepaint(): void {
|
|
||||||
if (this.datas.points.length < 2) {
|
|
||||||
throw new Error('Link坐标数据异常');
|
|
||||||
}
|
|
||||||
this.lineGraphic.clear();
|
|
||||||
this.lineGraphic.lineStyle(
|
|
||||||
this.datas.lineWidth,
|
|
||||||
new Color(this.datas.lineColor)
|
|
||||||
);
|
|
||||||
if (this.datas.curve) {
|
|
||||||
// 曲线
|
|
||||||
const bps = convertToBezierParams(this.datas.points);
|
|
||||||
bps.forEach((bp) => {
|
|
||||||
this.lineGraphic.drawBezierCurve(
|
|
||||||
bp.p1,
|
|
||||||
bp.p2,
|
|
||||||
bp.cp1,
|
|
||||||
bp.cp2,
|
|
||||||
this.datas.segmentsCount
|
|
||||||
);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// 直线
|
|
||||||
const start = this.getStartPoint();
|
|
||||||
this.lineGraphic.moveTo(start.x, start.y);
|
|
||||||
for (let i = 0; i < this.datas.points.length; i++) {
|
|
||||||
const p = this.datas.points[i];
|
|
||||||
this.lineGraphic.lineTo(p.x, p.y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
get linePoints(): IPointData[] {
|
|
||||||
return this.datas.points;
|
|
||||||
}
|
|
||||||
set linePoints(points: IPointData[]) {
|
|
||||||
const old = this.datas.clone();
|
|
||||||
old.points = points;
|
|
||||||
this.updateData(old);
|
|
||||||
}
|
|
||||||
getStartPoint(): IPointData {
|
|
||||||
return this.datas.points[0];
|
|
||||||
}
|
|
||||||
getEndPoint(): IPointData {
|
|
||||||
return this.datas.points[this.datas.points.length - 1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class LinkTemplate extends JlGraphicTemplate<Link> {
|
|
||||||
curve: boolean;
|
|
||||||
lineWidth: number;
|
|
||||||
lineColor: string;
|
|
||||||
segmentsCount: number;
|
|
||||||
constructor(dataTemplate: ILinkData) {
|
|
||||||
super(Link.Type, {
|
|
||||||
dataTemplate,
|
|
||||||
});
|
|
||||||
this.lineWidth = 2;
|
|
||||||
this.lineColor = '#000000';
|
|
||||||
this.curve = false;
|
|
||||||
this.segmentsCount = 10;
|
|
||||||
}
|
|
||||||
new(): Link {
|
|
||||||
return new Link();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,451 +0,0 @@
|
|||||||
import {
|
|
||||||
Color,
|
|
||||||
DisplayObject,
|
|
||||||
FederatedMouseEvent,
|
|
||||||
FederatedPointerEvent,
|
|
||||||
Graphics,
|
|
||||||
IHitArea,
|
|
||||||
Point,
|
|
||||||
} from 'pixi.js';
|
|
||||||
import {
|
|
||||||
AbsorbablePosition,
|
|
||||||
DraggablePoint,
|
|
||||||
IGraphicApp,
|
|
||||||
GraphicDrawAssistant,
|
|
||||||
GraphicInteractionPlugin,
|
|
||||||
GraphicTransformEvent,
|
|
||||||
IDrawApp,
|
|
||||||
JlGraphic,
|
|
||||||
KeyListener,
|
|
||||||
calculateMirrorPoint,
|
|
||||||
convertToBezierParams,
|
|
||||||
linePoint,
|
|
||||||
pointPolygon,
|
|
||||||
} from 'src/jlgraphic';
|
|
||||||
import AbsorbablePoint, {
|
|
||||||
AbsorbableCircle,
|
|
||||||
} from 'src/jlgraphic/graphic/AbsorbablePosition';
|
|
||||||
import {
|
|
||||||
BezierCurveEditPlugin,
|
|
||||||
ILineGraphic,
|
|
||||||
PolylineEditPlugin,
|
|
||||||
addWayPoint,
|
|
||||||
clearWayPoint,
|
|
||||||
getWaypointRangeIndex,
|
|
||||||
removeBezierWayPoint,
|
|
||||||
removeLineWayPoint,
|
|
||||||
} from 'src/jlgraphic/plugins/GraphicEditPlugin';
|
|
||||||
import { ContextMenu } from 'src/jlgraphic/ui/ContextMenu';
|
|
||||||
import { MenuItemOptions, MenuOptions } from 'src/jlgraphic/ui/Menu';
|
|
||||||
import { ILinkData, Link, LinkTemplate } from './Link';
|
|
||||||
|
|
||||||
export interface ILinkDrawOptions {
|
|
||||||
newData: () => ILinkData;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class LinkDraw extends GraphicDrawAssistant<LinkTemplate, ILinkData> {
|
|
||||||
points: Point[] = [];
|
|
||||||
graphic: Graphics = new Graphics();
|
|
||||||
|
|
||||||
// 快捷切曲线绘制
|
|
||||||
keyqListener: KeyListener = new KeyListener({
|
|
||||||
value: 'KeyQ',
|
|
||||||
global: true,
|
|
||||||
onPress: () => {
|
|
||||||
if (this.points.length == 0) {
|
|
||||||
this.graphicTemplate.curve = true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
// 快捷切直线绘制
|
|
||||||
keyzListener: KeyListener = new KeyListener({
|
|
||||||
value: 'KeyZ',
|
|
||||||
global: true,
|
|
||||||
onPress: () => {
|
|
||||||
if (this.points.length == 0) {
|
|
||||||
this.graphicTemplate.curve = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
constructor(app: IDrawApp, template: LinkTemplate) {
|
|
||||||
super(app, template, Link.Type, '轨道Link');
|
|
||||||
this.container.addChild(this.graphic);
|
|
||||||
this.graphicTemplate.curve = true;
|
|
||||||
|
|
||||||
LinkPointsEditPlugin.init(app);
|
|
||||||
}
|
|
||||||
|
|
||||||
bind(): void {
|
|
||||||
super.bind();
|
|
||||||
this.app.addKeyboardListener(this.keyqListener, this.keyzListener);
|
|
||||||
}
|
|
||||||
unbind(): void {
|
|
||||||
super.unbind();
|
|
||||||
this.app.removeKeyboardListener(this.keyqListener, this.keyzListener);
|
|
||||||
}
|
|
||||||
|
|
||||||
clearCache(): void {
|
|
||||||
this.points = [];
|
|
||||||
this.graphic.clear();
|
|
||||||
}
|
|
||||||
onRightClick(): void {
|
|
||||||
this.createAndStore(true);
|
|
||||||
}
|
|
||||||
onLeftDown(e: FederatedPointerEvent): void {
|
|
||||||
const { x, y } = this.toCanvasCoordinates(e.global);
|
|
||||||
const p = new Point(x, y);
|
|
||||||
if (this.graphicTemplate.curve) {
|
|
||||||
if (this.points.length == 0) {
|
|
||||||
this.points.push(p);
|
|
||||||
} else {
|
|
||||||
this.points.push(p, p.clone());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.points.push(p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onLeftUp(e: FederatedMouseEvent): void {
|
|
||||||
const template = this.graphicTemplate;
|
|
||||||
if (template.curve) {
|
|
||||||
const mp = this.toCanvasCoordinates(e.global);
|
|
||||||
if (this.points.length == 1) {
|
|
||||||
this.points.push(new Point(mp.x, mp.y));
|
|
||||||
} else if (this.points.length > 1) {
|
|
||||||
const cp2 = this.points[this.points.length - 2];
|
|
||||||
const p = this.points[this.points.length - 1];
|
|
||||||
cp2.copyFrom(calculateMirrorPoint(p, mp));
|
|
||||||
this.points.push(mp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
redraw(p: Point): void {
|
|
||||||
if (this.points.length < 1) return;
|
|
||||||
this.graphic.clear();
|
|
||||||
const template = this.graphicTemplate;
|
|
||||||
this.graphic.lineStyle(template.lineWidth, new Color(template.lineColor));
|
|
||||||
const ps = [...this.points];
|
|
||||||
if (template.curve) {
|
|
||||||
// 曲线
|
|
||||||
if (ps.length == 1) {
|
|
||||||
this.graphic.moveTo(ps[0].x, ps[0].y);
|
|
||||||
this.graphic.lineTo(p.x, p.y);
|
|
||||||
} else {
|
|
||||||
if ((ps.length + 1) % 3 == 0) {
|
|
||||||
ps.push(p.clone(), p.clone());
|
|
||||||
} else {
|
|
||||||
const cp = ps[ps.length - 2];
|
|
||||||
const p1 = ps[ps.length - 1];
|
|
||||||
const mp = calculateMirrorPoint(p1, p);
|
|
||||||
cp.copyFrom(mp);
|
|
||||||
}
|
|
||||||
|
|
||||||
const bps = convertToBezierParams(ps);
|
|
||||||
bps.forEach((bp) =>
|
|
||||||
this.graphic.drawBezierCurve(
|
|
||||||
bp.p1,
|
|
||||||
bp.p2,
|
|
||||||
bp.cp1,
|
|
||||||
bp.cp2,
|
|
||||||
template.segmentsCount
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ps.push(p);
|
|
||||||
// 直线
|
|
||||||
this.graphic.moveTo(ps[0].x, ps[0].y);
|
|
||||||
for (let i = 1; i < ps.length; i++) {
|
|
||||||
const p = ps[i];
|
|
||||||
this.graphic.lineTo(p.x, p.y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
prepareData(data: ILinkData): boolean {
|
|
||||||
const template = this.graphicTemplate;
|
|
||||||
if (
|
|
||||||
(!template.curve && this.points.length < 2) ||
|
|
||||||
(template.curve && this.points.length < 4)
|
|
||||||
) {
|
|
||||||
console.log('Link绘制因点不够取消绘制');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (template.curve) {
|
|
||||||
this.points.pop();
|
|
||||||
}
|
|
||||||
data.curve = template.curve;
|
|
||||||
data.segmentsCount = template.segmentsCount;
|
|
||||||
data.points = this.points;
|
|
||||||
data.lineWidth = template.lineWidth;
|
|
||||||
data.lineColor = template.lineColor;
|
|
||||||
data.segmentsCount = template.segmentsCount;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class LinkGraphicHitArea implements IHitArea {
|
|
||||||
link: Link;
|
|
||||||
constructor(link: Link) {
|
|
||||||
this.link = link;
|
|
||||||
}
|
|
||||||
contains(x: number, y: number): boolean {
|
|
||||||
const p = new Point(x, y);
|
|
||||||
if (this.link.datas.curve) {
|
|
||||||
// 曲线
|
|
||||||
const bps = convertToBezierParams(this.link.datas.points);
|
|
||||||
for (let i = 0; i < bps.length; i++) {
|
|
||||||
const bp = bps[i];
|
|
||||||
if (
|
|
||||||
pointPolygon(
|
|
||||||
p,
|
|
||||||
[bp.p1, bp.cp1, bp.cp2, bp.p2],
|
|
||||||
this.link.datas.lineWidth
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 直线
|
|
||||||
for (let i = 1; i < this.link.datas.points.length; i++) {
|
|
||||||
const p1 = this.link.datas.points[i - 1];
|
|
||||||
const p2 = this.link.datas.points[i];
|
|
||||||
if (linePoint(p1, p2, p, this.link.datas.lineWidth)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 构建吸附位置
|
|
||||||
* @param link
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
function buildAbsorbablePositions(link: Link): AbsorbablePosition[] {
|
|
||||||
const aps: AbsorbablePosition[] = [];
|
|
||||||
const links = link.queryStore.queryByType<Link>(Link.Type);
|
|
||||||
links.forEach((other) => {
|
|
||||||
if (other.id == link.id) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const apa = new AbsorbablePoint(
|
|
||||||
other.localToCanvasPoint(other.getStartPoint())
|
|
||||||
);
|
|
||||||
const apb = new AbsorbablePoint(
|
|
||||||
other.localToCanvasPoint(other.getEndPoint())
|
|
||||||
);
|
|
||||||
aps.push(apa, apb);
|
|
||||||
});
|
|
||||||
|
|
||||||
aps.push(new AbsorbableCircle(new Point(450, 410), 30));
|
|
||||||
|
|
||||||
return aps;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 端点拖拽添加吸附位置
|
|
||||||
* @param g
|
|
||||||
* @param dp
|
|
||||||
* @param index
|
|
||||||
*/
|
|
||||||
function onPolylineEditPointCreate(
|
|
||||||
g: ILineGraphic,
|
|
||||||
dp: DraggablePoint,
|
|
||||||
index: number
|
|
||||||
): void {
|
|
||||||
const link = g as Link;
|
|
||||||
if (index === 0 || index == link.datas.points.length - 1) {
|
|
||||||
// 端点
|
|
||||||
dp.on('transformstart', (e: GraphicTransformEvent) => {
|
|
||||||
if (e.isShift()) {
|
|
||||||
link.getGraphicApp().setOptions({
|
|
||||||
absorbablePositions: buildAbsorbablePositions(link),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
dp.on('rightclick', (e: FederatedMouseEvent) => {
|
|
||||||
// dp.getGraphicApp().openContextMenu(EditPointContextMenu.DefaultMenu);
|
|
||||||
// 路径中的点
|
|
||||||
const app = dp.getGraphicApp();
|
|
||||||
app.registerMenu(EditPointContextMenu);
|
|
||||||
removeWaypointConfig.handler = () => {
|
|
||||||
removeLineWayPoint(link, index);
|
|
||||||
};
|
|
||||||
clearWaypointsConfig.handler = () => {
|
|
||||||
clearWayPoint(link, false);
|
|
||||||
};
|
|
||||||
EditPointContextMenu.open(e.global);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function onCurveEditPointCreate(
|
|
||||||
g: ILineGraphic,
|
|
||||||
dp: DraggablePoint,
|
|
||||||
index: number
|
|
||||||
): void {
|
|
||||||
const link = g as Link;
|
|
||||||
if (index === 0 || index == link.datas.points.length - 1) {
|
|
||||||
// 端点
|
|
||||||
dp.on('transformstart', (e: GraphicTransformEvent) => {
|
|
||||||
if (e.isShift()) {
|
|
||||||
link.getGraphicApp().setOptions({
|
|
||||||
absorbablePositions: buildAbsorbablePositions(link),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
const c = index % 3;
|
|
||||||
dp.on('rightclick', (e: FederatedMouseEvent) => {
|
|
||||||
// dp.getGraphicApp().openContextMenu(EditPointContextMenu.DefaultMenu);
|
|
||||||
if (c === 0) {
|
|
||||||
// 路径中的点
|
|
||||||
const app = dp.getGraphicApp();
|
|
||||||
app.registerMenu(EditPointContextMenu);
|
|
||||||
removeWaypointConfig.handler = () => {
|
|
||||||
removeBezierWayPoint(link, index);
|
|
||||||
};
|
|
||||||
clearWaypointsConfig.handler = () => {
|
|
||||||
clearWayPoint(link, true);
|
|
||||||
};
|
|
||||||
EditPointContextMenu.open(e.global);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export const addWaypointConfig: MenuItemOptions = {
|
|
||||||
name: '添加路径点',
|
|
||||||
};
|
|
||||||
export const addWaySegmentingConfig: MenuItemOptions = {
|
|
||||||
name: '细分',
|
|
||||||
};
|
|
||||||
export const removeWaypointConfig: MenuItemOptions = {
|
|
||||||
name: '移除路径点',
|
|
||||||
};
|
|
||||||
export const clearWaypointsConfig: MenuItemOptions = {
|
|
||||||
name: '清除所有路径点',
|
|
||||||
};
|
|
||||||
const menuOptions: MenuOptions = {
|
|
||||||
name: '图形编辑点菜单',
|
|
||||||
groups: [
|
|
||||||
{
|
|
||||||
items: [removeWaypointConfig, clearWaypointsConfig],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
const EditPointContextMenu = ContextMenu.init(menuOptions);
|
|
||||||
|
|
||||||
const LinkEditMenu: ContextMenu = ContextMenu.init({
|
|
||||||
name: '轨道编辑菜单',
|
|
||||||
groups: [
|
|
||||||
{
|
|
||||||
items: [addWaypointConfig, clearWaypointsConfig],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* link路径编辑
|
|
||||||
*/
|
|
||||||
export class LinkPointsEditPlugin extends GraphicInteractionPlugin<Link> {
|
|
||||||
static Name = 'LinkPointsDrag';
|
|
||||||
constructor(app: IGraphicApp) {
|
|
||||||
super(LinkPointsEditPlugin.Name, app);
|
|
||||||
app.registerMenu(LinkEditMenu);
|
|
||||||
}
|
|
||||||
static init(app: IGraphicApp): LinkPointsEditPlugin {
|
|
||||||
return new LinkPointsEditPlugin(app);
|
|
||||||
}
|
|
||||||
filter(...grahpics: JlGraphic[]): Link[] | undefined {
|
|
||||||
return grahpics.filter((g) => g.type == Link.Type) as Link[];
|
|
||||||
}
|
|
||||||
bind(g: Link): void {
|
|
||||||
g.lineGraphic.eventMode = 'static';
|
|
||||||
g.lineGraphic.cursor = 'pointer';
|
|
||||||
g.lineGraphic.hitArea = new LinkGraphicHitArea(g);
|
|
||||||
g.on('_rightclick', this.onContextMenu, this);
|
|
||||||
g.on('selected', this.onSelected, this);
|
|
||||||
g.on('unselected', this.onUnselected, this);
|
|
||||||
}
|
|
||||||
unbind(g: Link): void {
|
|
||||||
g.off('_rightclick', this.onContextMenu, this);
|
|
||||||
g.off('selected', this.onSelected, this);
|
|
||||||
g.off('unselected', this.onUnselected, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
onContextMenu(e: FederatedMouseEvent) {
|
|
||||||
const target = e.target as DisplayObject;
|
|
||||||
const link = target.getGraphic() as Link;
|
|
||||||
this.app.updateSelected(link);
|
|
||||||
const p = link.getGraphicApp().toCanvasCoordinates(e.global);
|
|
||||||
console.log('右键坐标', p);
|
|
||||||
|
|
||||||
addWaypointConfig.handler = () => {
|
|
||||||
const linePoints = link.linePoints;
|
|
||||||
console.log('添加路径点', linePoints, p);
|
|
||||||
const { start, end } = getWaypointRangeIndex(
|
|
||||||
linePoints,
|
|
||||||
link.datas.curve,
|
|
||||||
p,
|
|
||||||
link.datas.lineWidth
|
|
||||||
);
|
|
||||||
addWayPoint(link, link.datas.curve, start, end, p);
|
|
||||||
};
|
|
||||||
clearWaypointsConfig.handler = () => {
|
|
||||||
clearWayPoint(link, link.datas.curve);
|
|
||||||
};
|
|
||||||
LinkEditMenu.open(e.global);
|
|
||||||
}
|
|
||||||
|
|
||||||
onSelected(g: DisplayObject): void {
|
|
||||||
const link = g as Link;
|
|
||||||
let lep;
|
|
||||||
if (link.datas.curve) {
|
|
||||||
// 曲线
|
|
||||||
lep = link.getAssistantAppend<BezierCurveEditPlugin>(
|
|
||||||
BezierCurveEditPlugin.Name
|
|
||||||
);
|
|
||||||
if (!lep) {
|
|
||||||
lep = new BezierCurveEditPlugin(link, {
|
|
||||||
onEditPointCreate: onCurveEditPointCreate,
|
|
||||||
});
|
|
||||||
link.addAssistantAppend(lep);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 直线
|
|
||||||
lep = link.getAssistantAppend<PolylineEditPlugin>(
|
|
||||||
PolylineEditPlugin.Name
|
|
||||||
);
|
|
||||||
if (!lep) {
|
|
||||||
lep = new PolylineEditPlugin(link, {
|
|
||||||
onEditPointCreate: onPolylineEditPointCreate,
|
|
||||||
});
|
|
||||||
link.addAssistantAppend(lep);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lep.showAll();
|
|
||||||
}
|
|
||||||
onUnselected(g: DisplayObject): void {
|
|
||||||
const link = g as Link;
|
|
||||||
let lep;
|
|
||||||
if (link.datas.curve) {
|
|
||||||
// 曲线
|
|
||||||
lep = link.getAssistantAppend<BezierCurveEditPlugin>(
|
|
||||||
BezierCurveEditPlugin.Name
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
// 直线
|
|
||||||
lep = link.getAssistantAppend<PolylineEditPlugin>(
|
|
||||||
PolylineEditPlugin.Name
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (lep) {
|
|
||||||
lep.hideAll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,203 +0,0 @@
|
|||||||
import { Color, Graphics, IPointData, Rectangle } from 'pixi.js';
|
|
||||||
import {
|
|
||||||
GraphicData,
|
|
||||||
JlGraphic,
|
|
||||||
JlGraphicTemplate,
|
|
||||||
VectorText,
|
|
||||||
getRectangleCenter,
|
|
||||||
} from 'src/jlgraphic';
|
|
||||||
|
|
||||||
export interface IPlatformData extends GraphicData {
|
|
||||||
get code(): string; // 编号
|
|
||||||
set code(v: string);
|
|
||||||
get hasdoor(): boolean; // 是否有屏蔽门
|
|
||||||
set hasdoor(v: boolean);
|
|
||||||
get trainDirection(): string; // 行驶方向--屏蔽门上下
|
|
||||||
set trainDirection(v: string);
|
|
||||||
get lineWidth(): number; // 线宽
|
|
||||||
set lineWidth(v: number);
|
|
||||||
get lineColor(): string; // 站台线色
|
|
||||||
set lineColor(v: string);
|
|
||||||
get lineColorDoor(): string; // 屏蔽门线色
|
|
||||||
set lineColorDoor(v: string);
|
|
||||||
get point(): IPointData; // 位置坐标
|
|
||||||
set point(point: IPointData);
|
|
||||||
get width(): number; // 宽度
|
|
||||||
set width(v: number);
|
|
||||||
get height(): number; // 高度
|
|
||||||
set height(v: number);
|
|
||||||
clone(): IPlatformData;
|
|
||||||
copyFrom(data: IPlatformData): void;
|
|
||||||
eq(other: IPlatformData): boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
//站台颜色
|
|
||||||
export enum PlatformColorEnum {
|
|
||||||
blue = '0x0fe81f', //站台的颜色
|
|
||||||
lightBlue = '0x55d15d',
|
|
||||||
yellow = '0xfbff00',
|
|
||||||
white = '0xffffff',
|
|
||||||
lozengeRed = '0xff0000', //站台旁的菱形图标
|
|
||||||
whiteNumbers = '0xffffff', //站台旁白色数字
|
|
||||||
HCharYellow = '0xfbff00', //站台旁的H字符
|
|
||||||
HCharWhite = '0xffffff',
|
|
||||||
HCharRed = '0xff0000',
|
|
||||||
doorBlue = '0x008000', //屏蔽门的颜色
|
|
||||||
doorRed = '0xff0000',
|
|
||||||
}
|
|
||||||
|
|
||||||
const platformConsts = {
|
|
||||||
width: 60,
|
|
||||||
height: 20,
|
|
||||||
lineWidth: 3,
|
|
||||||
besideFontSize: 12,
|
|
||||||
doorOpenSpacing: 5,
|
|
||||||
doorPlatformSpacing: 10,
|
|
||||||
besideSpacing: 10,
|
|
||||||
};
|
|
||||||
|
|
||||||
export class Platform extends JlGraphic {
|
|
||||||
static Type = 'Platform';
|
|
||||||
|
|
||||||
platformGraphic: Graphics;
|
|
||||||
doorGraphic: Graphics;
|
|
||||||
doorCloseGraphic: Graphics;
|
|
||||||
besideGraphic: Graphics;
|
|
||||||
codeGraph: VectorText = new VectorText(''); //站台旁数字、字符
|
|
||||||
constructor() {
|
|
||||||
super(Platform.Type);
|
|
||||||
this.platformGraphic = new Graphics();
|
|
||||||
this.doorGraphic = new Graphics();
|
|
||||||
this.doorCloseGraphic = new Graphics();
|
|
||||||
this.besideGraphic = new Graphics();
|
|
||||||
this.addChild(this.platformGraphic);
|
|
||||||
this.addChild(this.doorGraphic);
|
|
||||||
this.addChild(this.doorCloseGraphic);
|
|
||||||
this.addChild(this.besideGraphic);
|
|
||||||
this.addChild(this.codeGraph);
|
|
||||||
this.codeGraph.setVectorFontSize(platformConsts.besideFontSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
get datas(): IPlatformData {
|
|
||||||
return this.getDatas<IPlatformData>();
|
|
||||||
}
|
|
||||||
doRepaint(): void {
|
|
||||||
const width = this.datas.width;
|
|
||||||
const height = this.datas.height;
|
|
||||||
//屏蔽门
|
|
||||||
const doorGraphic = this.doorGraphic;
|
|
||||||
const doorCloseGraphic = this.doorCloseGraphic;
|
|
||||||
doorGraphic.clear();
|
|
||||||
doorCloseGraphic.clear();
|
|
||||||
if (this.datas.hasdoor) {
|
|
||||||
doorGraphic.lineStyle(
|
|
||||||
this.datas.lineWidth,
|
|
||||||
new Color(this.datas.lineColorDoor)
|
|
||||||
);
|
|
||||||
doorGraphic.moveTo(-width / 2 - this.datas.lineWidth / 2, 0);
|
|
||||||
doorGraphic.lineTo(-platformConsts.doorOpenSpacing, 0);
|
|
||||||
doorGraphic.moveTo(platformConsts.doorOpenSpacing, 0);
|
|
||||||
doorGraphic.lineTo(width / 2 + this.datas.lineWidth / 2, 0);
|
|
||||||
//屏蔽门闭合
|
|
||||||
doorCloseGraphic.lineStyle(
|
|
||||||
this.datas.lineWidth,
|
|
||||||
new Color(this.datas.lineColorDoor)
|
|
||||||
);
|
|
||||||
doorCloseGraphic.moveTo(-platformConsts.doorOpenSpacing, 0);
|
|
||||||
doorCloseGraphic.lineTo(platformConsts.doorOpenSpacing, 0);
|
|
||||||
doorGraphic.position.set(
|
|
||||||
0,
|
|
||||||
-height / 2 - platformConsts.doorPlatformSpacing
|
|
||||||
);
|
|
||||||
doorCloseGraphic.position.set(
|
|
||||||
0,
|
|
||||||
-height / 2 - platformConsts.doorPlatformSpacing
|
|
||||||
);
|
|
||||||
}
|
|
||||||
//站台
|
|
||||||
const platformGraphic = this.platformGraphic;
|
|
||||||
platformGraphic.clear();
|
|
||||||
platformGraphic.lineStyle(
|
|
||||||
this.datas.lineWidth,
|
|
||||||
new Color(this.datas.lineColor)
|
|
||||||
);
|
|
||||||
platformGraphic.beginFill(this.datas.lineColor, 1);
|
|
||||||
platformGraphic.drawRect(0, 0, this.datas.width, this.datas.height);
|
|
||||||
platformGraphic.endFill;
|
|
||||||
const rectP = new Rectangle(0, 0, this.datas.width, this.datas.height);
|
|
||||||
platformGraphic.pivot = getRectangleCenter(rectP);
|
|
||||||
this.position.set(this.datas.point.x, this.datas.point.y);
|
|
||||||
//站台旁菱形图标
|
|
||||||
const besideGraphic = this.besideGraphic;
|
|
||||||
besideGraphic.clear();
|
|
||||||
besideGraphic.lineStyle(1, new Color(PlatformColorEnum.lozengeRed));
|
|
||||||
besideGraphic.drawRect(0, 0, this.datas.height / 4, this.datas.height / 4);
|
|
||||||
const rect = new Rectangle(
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
this.datas.height / 4,
|
|
||||||
this.datas.height / 4
|
|
||||||
);
|
|
||||||
besideGraphic.pivot = getRectangleCenter(rect);
|
|
||||||
besideGraphic.rotation = Math.PI / 4;
|
|
||||||
besideGraphic.position.set(
|
|
||||||
-width / 2 - this.datas.lineWidth / 2 - platformConsts.besideSpacing,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
//站台旁的数字、字符
|
|
||||||
const codeGraph = this.codeGraph;
|
|
||||||
codeGraph.text = 'H';
|
|
||||||
codeGraph.anchor.set(0.5);
|
|
||||||
codeGraph.position.set(
|
|
||||||
-width / 2 - this.datas.lineWidth / 2 - platformConsts.besideSpacing,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
codeGraph.style.fill = PlatformColorEnum.HCharYellow;
|
|
||||||
//站台方向
|
|
||||||
if (this.datas.trainDirection == 'right') {
|
|
||||||
doorGraphic.position.set(
|
|
||||||
0,
|
|
||||||
height / 2 + platformConsts.doorPlatformSpacing
|
|
||||||
);
|
|
||||||
doorCloseGraphic.position.set(
|
|
||||||
0,
|
|
||||||
height / 2 + platformConsts.doorPlatformSpacing
|
|
||||||
);
|
|
||||||
besideGraphic.position.set(
|
|
||||||
width / 2 + this.datas.lineWidth / 2 + platformConsts.besideSpacing,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
codeGraph.position.set(
|
|
||||||
width / 2 + this.datas.lineWidth / 2 + platformConsts.besideSpacing,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
}
|
|
||||||
//子元素显隐
|
|
||||||
doorCloseGraphic.visible = false;
|
|
||||||
/* besideGraphic.visible = false;
|
|
||||||
codeGraph.visible = false; */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class PlatformTemplate extends JlGraphicTemplate<Platform> {
|
|
||||||
hasdoor: boolean;
|
|
||||||
trainDirection: string;
|
|
||||||
lineWidth: number;
|
|
||||||
lineColor: string;
|
|
||||||
lineColorDoor: string;
|
|
||||||
width: number;
|
|
||||||
height: number;
|
|
||||||
constructor() {
|
|
||||||
super(Platform.Type, {});
|
|
||||||
this.hasdoor = true;
|
|
||||||
this.trainDirection = 'left';
|
|
||||||
this.lineWidth = platformConsts.lineWidth;
|
|
||||||
this.lineColor = PlatformColorEnum.yellow;
|
|
||||||
this.lineColorDoor = PlatformColorEnum.doorBlue;
|
|
||||||
this.width = platformConsts.width;
|
|
||||||
this.height = platformConsts.height;
|
|
||||||
}
|
|
||||||
new(): Platform {
|
|
||||||
return new Platform();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,123 +0,0 @@
|
|||||||
import {
|
|
||||||
Color,
|
|
||||||
FederatedPointerEvent,
|
|
||||||
Graphics,
|
|
||||||
Point,
|
|
||||||
Rectangle,
|
|
||||||
} from 'pixi.js';
|
|
||||||
import {
|
|
||||||
GraphicDrawAssistant,
|
|
||||||
GraphicInteractionPlugin,
|
|
||||||
IDrawApp,
|
|
||||||
JlGraphic,
|
|
||||||
getRectangleCenter,
|
|
||||||
} from 'src/jlgraphic';
|
|
||||||
|
|
||||||
import { IPlatformData, Platform, PlatformTemplate } from './Platform';
|
|
||||||
|
|
||||||
export interface IPlatformDrawOptions {
|
|
||||||
newData: () => IPlatformData;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class PlatformDraw extends GraphicDrawAssistant<
|
|
||||||
PlatformTemplate,
|
|
||||||
IPlatformData
|
|
||||||
> {
|
|
||||||
point: Point = new Point(0, 0);
|
|
||||||
platformGraphic: Graphics = new Graphics();
|
|
||||||
doorGraphic: Graphics = new Graphics();
|
|
||||||
|
|
||||||
constructor(app: IDrawApp, createData: () => IPlatformData) {
|
|
||||||
super(app, new PlatformTemplate(), '', '站台Platform');
|
|
||||||
this.container.addChild(this.platformGraphic);
|
|
||||||
this.container.addChild(this.doorGraphic);
|
|
||||||
this.graphicTemplate.hasdoor = true;
|
|
||||||
platformInteraction.init(app);
|
|
||||||
}
|
|
||||||
|
|
||||||
bind(): void {
|
|
||||||
super.bind();
|
|
||||||
}
|
|
||||||
unbind(): void {
|
|
||||||
super.unbind();
|
|
||||||
}
|
|
||||||
|
|
||||||
clearCache(): void {
|
|
||||||
this.platformGraphic.clear();
|
|
||||||
this.doorGraphic.clear();
|
|
||||||
}
|
|
||||||
onLeftDown(e: FederatedPointerEvent): void {
|
|
||||||
const { x, y } = this.toCanvasCoordinates(e.global);
|
|
||||||
const p = new Point(x, y);
|
|
||||||
this.point = p;
|
|
||||||
this.createAndStore(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
redraw(p: Point): void {
|
|
||||||
const template = this.graphicTemplate;
|
|
||||||
//屏蔽门
|
|
||||||
if (template.hasdoor) {
|
|
||||||
const doorGraphic = this.doorGraphic;
|
|
||||||
doorGraphic.clear();
|
|
||||||
doorGraphic.lineStyle(
|
|
||||||
template.lineWidth,
|
|
||||||
new Color(template.lineColorDoor)
|
|
||||||
);
|
|
||||||
const width = template.width;
|
|
||||||
const height = template.height;
|
|
||||||
doorGraphic.moveTo(-width / 2 - template.lineWidth / 2, -height / 2 - 10);
|
|
||||||
doorGraphic.lineTo(width / 2 + template.lineWidth / 2, -height / 2 - 10);
|
|
||||||
doorGraphic.position.set(p.x, p.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
//站台
|
|
||||||
const platformGraphic = this.platformGraphic;
|
|
||||||
platformGraphic.clear();
|
|
||||||
this.point.set(p.x, p.y);
|
|
||||||
const rect = new Rectangle(0, 0, template.width, template.height);
|
|
||||||
platformGraphic.pivot = getRectangleCenter(rect);
|
|
||||||
platformGraphic.lineStyle(template.lineWidth, template.lineColor);
|
|
||||||
platformGraphic.beginFill(template.lineColor, 1);
|
|
||||||
platformGraphic.drawRect(0, 0, template.width, template.height);
|
|
||||||
platformGraphic.endFill;
|
|
||||||
platformGraphic.position.set(this.point.x, this.point.y);
|
|
||||||
}
|
|
||||||
prepareData(data: IPlatformData): boolean {
|
|
||||||
const template = this.graphicTemplate;
|
|
||||||
data.hasdoor = template.hasdoor;
|
|
||||||
data.trainDirection = template.trainDirection;
|
|
||||||
data.point = this.point;
|
|
||||||
data.lineWidth = template.lineWidth;
|
|
||||||
data.lineColor = template.lineColor;
|
|
||||||
data.lineColorDoor = template.lineColorDoor;
|
|
||||||
data.width = template.width;
|
|
||||||
data.height = template.height;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class platformInteraction extends GraphicInteractionPlugin<Platform> {
|
|
||||||
static Name = 'platform_transform';
|
|
||||||
constructor(app: IDrawApp) {
|
|
||||||
super(platformInteraction.Name, app);
|
|
||||||
}
|
|
||||||
static init(app: IDrawApp) {
|
|
||||||
return new platformInteraction(app);
|
|
||||||
}
|
|
||||||
filter(...grahpics: JlGraphic[]): Platform[] | undefined {
|
|
||||||
return grahpics
|
|
||||||
.filter((g) => g.type === Platform.Type)
|
|
||||||
.map((g) => g as Platform);
|
|
||||||
}
|
|
||||||
bind(g: Platform): void {
|
|
||||||
g.eventMode = 'static';
|
|
||||||
g.cursor = 'pointer';
|
|
||||||
g.scalable = true;
|
|
||||||
g.rotatable = true;
|
|
||||||
}
|
|
||||||
unbind(g: Platform): void {
|
|
||||||
g.eventMode = 'none';
|
|
||||||
g.scalable = false;
|
|
||||||
g.rotatable = false;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,86 +0,0 @@
|
|||||||
import { Color, Graphics, IPointData, Point } from 'pixi.js';
|
|
||||||
import { GraphicData, JlGraphic, JlGraphicTemplate } from 'src/jlgraphic';
|
|
||||||
|
|
||||||
export interface IRectData extends GraphicData {
|
|
||||||
get code(): string; // 编号
|
|
||||||
set code(v: string);
|
|
||||||
get lineWidth(): number; // 线宽
|
|
||||||
set lineWidth(v: number);
|
|
||||||
get lineColor(): string; // 线色
|
|
||||||
set lineColor(v: string);
|
|
||||||
get point(): IPointData; // 位置坐标
|
|
||||||
set point(point: IPointData);
|
|
||||||
get width(): number; // 宽度
|
|
||||||
set width(v: number);
|
|
||||||
get height(): number; // 高度
|
|
||||||
set height(v: number);
|
|
||||||
get points(): IPointData[]; // 线坐标点
|
|
||||||
set points(points: IPointData[]);
|
|
||||||
clone(): IRectData;
|
|
||||||
copyFrom(data: IRectData): void;
|
|
||||||
eq(other: IRectData): boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
const rectConsts = {
|
|
||||||
lineWidth: 2,
|
|
||||||
lineColor: '0xff0000',
|
|
||||||
width: 60,
|
|
||||||
height: 20,
|
|
||||||
};
|
|
||||||
|
|
||||||
export class Rect extends JlGraphic {
|
|
||||||
static Type = 'Rect';
|
|
||||||
rectGraphic: Graphics;
|
|
||||||
constructor() {
|
|
||||||
super(Rect.Type);
|
|
||||||
this.rectGraphic = new Graphics();
|
|
||||||
this.addChild(this.rectGraphic);
|
|
||||||
}
|
|
||||||
|
|
||||||
get datas(): IRectData {
|
|
||||||
return this.getDatas<IRectData>();
|
|
||||||
}
|
|
||||||
doRepaint(): void {
|
|
||||||
const width = this.datas.width;
|
|
||||||
const height = this.datas.height;
|
|
||||||
if (this.linePoints.length == 0) {
|
|
||||||
const r1 = new Point(this.datas.point.x, this.datas.point.y);
|
|
||||||
const r2 = new Point(r1.x + width, r1.y);
|
|
||||||
const r3 = new Point(r1.x + width, r1.y + height);
|
|
||||||
const r4 = new Point(r1.x, r1.y + height);
|
|
||||||
this.datas.points = [r1, r2, r3, r4, r1];
|
|
||||||
}
|
|
||||||
const rectGraphic = this.rectGraphic;
|
|
||||||
rectGraphic.clear();
|
|
||||||
rectGraphic.lineStyle(
|
|
||||||
this.datas.lineWidth,
|
|
||||||
new Color(this.datas.lineColor)
|
|
||||||
);
|
|
||||||
rectGraphic.drawPolygon(this.datas.points);
|
|
||||||
}
|
|
||||||
get linePoints(): IPointData[] {
|
|
||||||
return this.datas.points;
|
|
||||||
}
|
|
||||||
set linePoints(points: IPointData[]) {
|
|
||||||
const old = this.datas.clone();
|
|
||||||
old.points = points;
|
|
||||||
this.updateData(old);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class RectTemplate extends JlGraphicTemplate<Rect> {
|
|
||||||
lineWidth: number;
|
|
||||||
lineColor: string;
|
|
||||||
width: number;
|
|
||||||
height: number;
|
|
||||||
constructor() {
|
|
||||||
super(Rect.Type);
|
|
||||||
this.lineWidth = rectConsts.lineWidth;
|
|
||||||
this.lineColor = rectConsts.lineColor;
|
|
||||||
this.width = rectConsts.width;
|
|
||||||
this.height = rectConsts.height;
|
|
||||||
}
|
|
||||||
new(): Rect {
|
|
||||||
return new Rect();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,261 +0,0 @@
|
|||||||
import {
|
|
||||||
FederatedPointerEvent,
|
|
||||||
Graphics,
|
|
||||||
Point,
|
|
||||||
IHitArea,
|
|
||||||
DisplayObject,
|
|
||||||
FederatedMouseEvent,
|
|
||||||
} from 'pixi.js';
|
|
||||||
import {
|
|
||||||
DraggablePoint,
|
|
||||||
GraphicApp,
|
|
||||||
GraphicDrawAssistant,
|
|
||||||
GraphicInteractionPlugin,
|
|
||||||
GraphicTransformEvent,
|
|
||||||
JlDrawApp,
|
|
||||||
JlGraphic,
|
|
||||||
linePoint,
|
|
||||||
} from 'src/jlgraphic';
|
|
||||||
|
|
||||||
import AbsorbablePoint, {
|
|
||||||
AbsorbablePosition,
|
|
||||||
} from 'src/jlgraphic/graphic/AbsorbablePosition';
|
|
||||||
import {
|
|
||||||
ILineGraphic,
|
|
||||||
PolylineEditPlugin,
|
|
||||||
addWaySegmentingConfig,
|
|
||||||
addPolygonSegmentingPoint,
|
|
||||||
clearWayPoint,
|
|
||||||
clearWaypointsConfig,
|
|
||||||
getWayLineIndex,
|
|
||||||
} from 'src/jlgraphic/plugins/GraphicEditPlugin';
|
|
||||||
import { ContextMenu } from 'src/jlgraphic/ui/ContextMenu';
|
|
||||||
|
|
||||||
import { IRectData, Rect, RectTemplate } from './Rect';
|
|
||||||
import { Link } from '../link/Link';
|
|
||||||
|
|
||||||
export interface IRectDrawOptions {
|
|
||||||
newData: () => IRectData;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class RectDraw extends GraphicDrawAssistant<RectTemplate, IRectData> {
|
|
||||||
point1: Point | null = null;
|
|
||||||
point2: Point | null = null;
|
|
||||||
rectGraphic: Graphics = new Graphics();
|
|
||||||
|
|
||||||
constructor(app: JlDrawApp, createData: () => IRectData) {
|
|
||||||
super(app, new RectTemplate(), createData, Rect.Type, '站台Rect');
|
|
||||||
this.container.addChild(this.rectGraphic);
|
|
||||||
RectPointsEditPlugin.init(app);
|
|
||||||
}
|
|
||||||
|
|
||||||
bind(): void {
|
|
||||||
super.bind();
|
|
||||||
}
|
|
||||||
unbind(): void {
|
|
||||||
super.unbind();
|
|
||||||
}
|
|
||||||
|
|
||||||
clearCache(): void {
|
|
||||||
this.rectGraphic.clear();
|
|
||||||
}
|
|
||||||
onLeftDown(e: FederatedPointerEvent): void {
|
|
||||||
const { x, y } = this.toCanvasCoordinates(e.global);
|
|
||||||
const p = new Point(x, y);
|
|
||||||
if (this.point1 === null) {
|
|
||||||
this.point1 = p;
|
|
||||||
} else {
|
|
||||||
this.point2 = p;
|
|
||||||
this.createAndStore(true);
|
|
||||||
this.point1 = null;
|
|
||||||
this.point2 = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
redraw(p: Point): void {
|
|
||||||
const template = this.graphicTemplate;
|
|
||||||
if (this.point1 === null) return;
|
|
||||||
const rectGraphic = this.rectGraphic;
|
|
||||||
rectGraphic.clear();
|
|
||||||
rectGraphic.lineStyle(template.lineWidth, template.lineColor);
|
|
||||||
rectGraphic.drawRect(...this.normalize(this.point1, p));
|
|
||||||
}
|
|
||||||
//根据画的两个点确定左上角的点的坐标和矩形宽高
|
|
||||||
private normalize(p1: Point, p2: Point): [number, number, number, number] {
|
|
||||||
const { abs } = Math;
|
|
||||||
const x = p1.x < p2.x ? p1.x : p2.x;
|
|
||||||
const y = p1.y < p2.y ? p1.y : p2.y;
|
|
||||||
const w = abs(p1.x - p2.x);
|
|
||||||
const h = abs(p1.y - p2.y);
|
|
||||||
return [x, y, w, h];
|
|
||||||
}
|
|
||||||
prepareData(data: IRectData): boolean {
|
|
||||||
if (this.point1 == null) {
|
|
||||||
console.log('Rect绘制因点不够取消绘制');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const p1 = this.point1 as Point;
|
|
||||||
const p2 = this.point2 as Point;
|
|
||||||
const [x, y, width, height] = this.normalize(p1, p2);
|
|
||||||
const template = this.graphicTemplate;
|
|
||||||
data.point = new Point(x, y);
|
|
||||||
data.lineWidth = template.lineWidth;
|
|
||||||
data.lineColor = template.lineColor;
|
|
||||||
data.width = width;
|
|
||||||
data.height = height;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//碰撞检测
|
|
||||||
export class RectGraphicHitArea implements IHitArea {
|
|
||||||
rect: Rect;
|
|
||||||
constructor(rect: Rect) {
|
|
||||||
this.rect = rect;
|
|
||||||
}
|
|
||||||
contains(x: number, y: number): boolean {
|
|
||||||
let contains = false;
|
|
||||||
const p = new Point(x, y);
|
|
||||||
const rectData = this.rect.datas;
|
|
||||||
//contains = pointPolygon(p, rectData.points, rectData.lineWidth);是否包含多边形内部
|
|
||||||
const tolerance = rectData.lineWidth;
|
|
||||||
for (let i = 0; i < rectData.points.length - 1; i++) {
|
|
||||||
const p1 = rectData.points[i];
|
|
||||||
const p2 = rectData.points[i + 1];
|
|
||||||
contains = contains || linePoint(p1, p2, p, tolerance);
|
|
||||||
if (contains) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return contains;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 构建吸附位置
|
|
||||||
* @param rect
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
function buildAbsorbablePositions(rect: Rect): AbsorbablePosition[] {
|
|
||||||
const aps: AbsorbablePosition[] = [];
|
|
||||||
const rects = rect.queryStore.queryByType<Rect>(Rect.Type);
|
|
||||||
const links = rect.queryStore.queryByType<Link>(Link.Type);
|
|
||||||
|
|
||||||
links.forEach((other) => {
|
|
||||||
const apa = new AbsorbablePoint(
|
|
||||||
other.localToCanvasPoint(other.getStartPoint())
|
|
||||||
);
|
|
||||||
const apb = new AbsorbablePoint(
|
|
||||||
other.localToCanvasPoint(other.getEndPoint())
|
|
||||||
);
|
|
||||||
aps.push(apa, apb);
|
|
||||||
});
|
|
||||||
|
|
||||||
rects.forEach((other) => {
|
|
||||||
if (other.id == rect.id) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
other.linePoints.forEach((point) => {
|
|
||||||
const absorbablePoint = new AbsorbablePoint(
|
|
||||||
other.localToCanvasPoint(point)
|
|
||||||
);
|
|
||||||
aps.push(absorbablePoint);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return aps;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 端点拖拽添加吸附位置
|
|
||||||
* @param g
|
|
||||||
* @param dp
|
|
||||||
* @param index
|
|
||||||
*/
|
|
||||||
function onEditPointCreate(g: ILineGraphic, dp: DraggablePoint): void {
|
|
||||||
const rect = g as Rect;
|
|
||||||
// 端点
|
|
||||||
dp.on('transformstart', (e: GraphicTransformEvent) => {
|
|
||||||
if (e.isShift()) {
|
|
||||||
rect.getGraphicApp().setOptions({
|
|
||||||
absorbablePositions: buildAbsorbablePositions(rect),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const RectEditMenu: ContextMenu = ContextMenu.init({
|
|
||||||
name: '矩形编辑菜单',
|
|
||||||
groups: [
|
|
||||||
{
|
|
||||||
items: [addWaySegmentingConfig, clearWaypointsConfig],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* rect路径编辑
|
|
||||||
*/
|
|
||||||
export class RectPointsEditPlugin extends GraphicInteractionPlugin<Rect> {
|
|
||||||
static Name = 'RectPointsDrag';
|
|
||||||
constructor(app: GraphicApp) {
|
|
||||||
super(RectPointsEditPlugin.Name, app);
|
|
||||||
app.registerMenu(RectEditMenu);
|
|
||||||
}
|
|
||||||
static init(app: GraphicApp): RectPointsEditPlugin {
|
|
||||||
return new RectPointsEditPlugin(app);
|
|
||||||
}
|
|
||||||
filter(...grahpics: JlGraphic[]): Rect[] | undefined {
|
|
||||||
return grahpics.filter((g) => g.type == Rect.Type) as Rect[];
|
|
||||||
}
|
|
||||||
bind(g: Rect): void {
|
|
||||||
g.rectGraphic.eventMode = 'static';
|
|
||||||
g.rectGraphic.cursor = 'pointer';
|
|
||||||
g.rectGraphic.hitArea = new RectGraphicHitArea(g);
|
|
||||||
g.on('_rightclick', this.onContextMenu, this);
|
|
||||||
g.on('selected', this.onSelected, this);
|
|
||||||
g.on('unselected', this.onUnselected, this);
|
|
||||||
}
|
|
||||||
unbind(g: Rect): void {
|
|
||||||
g.off('_rightclick', this.onContextMenu, this);
|
|
||||||
g.off('selected', this.onSelected, this);
|
|
||||||
g.off('unselected', this.onUnselected, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
onContextMenu(e: FederatedMouseEvent) {
|
|
||||||
const target = e.target as DisplayObject;
|
|
||||||
const rect = target.getGraphic() as Rect;
|
|
||||||
this.app.updateSelected(rect);
|
|
||||||
addWaySegmentingConfig.handler = () => {
|
|
||||||
const linePoints = rect.linePoints;
|
|
||||||
const p = rect.screenToLocalPoint(e.global);
|
|
||||||
const { start, end } = getWayLineIndex(linePoints, p);
|
|
||||||
addPolygonSegmentingPoint(rect, start, end);
|
|
||||||
};
|
|
||||||
clearWaypointsConfig.handler = () => {
|
|
||||||
clearWayPoint(rect, false);
|
|
||||||
};
|
|
||||||
RectEditMenu.open(e.global);
|
|
||||||
}
|
|
||||||
|
|
||||||
onSelected(g: DisplayObject): void {
|
|
||||||
const rect = g as Rect;
|
|
||||||
let lep = rect.getAssistantAppend<PolylineEditPlugin>(
|
|
||||||
PolylineEditPlugin.Name
|
|
||||||
);
|
|
||||||
if (!lep) {
|
|
||||||
lep = new PolylineEditPlugin(rect, { onEditPointCreate });
|
|
||||||
rect.addAssistantAppend(lep);
|
|
||||||
}
|
|
||||||
lep.showAll();
|
|
||||||
}
|
|
||||||
onUnselected(g: DisplayObject): void {
|
|
||||||
const rect = g as Rect;
|
|
||||||
const lep = rect.getAssistantAppend<PolylineEditPlugin>(
|
|
||||||
PolylineEditPlugin.Name
|
|
||||||
);
|
|
||||||
if (lep) {
|
|
||||||
lep.hideAll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,52 +0,0 @@
|
|||||||
import { Container } from '@pixi/display';
|
|
||||||
import { Graphics } from 'pixi.js';
|
|
||||||
|
|
||||||
export enum LampEnum {
|
|
||||||
lampPostColor = '0xc0c0c0',
|
|
||||||
lampDefaultColor = '0xff0000',
|
|
||||||
logicModeColor = '0x000000',
|
|
||||||
}
|
|
||||||
|
|
||||||
const lampConsts = {
|
|
||||||
lampRadius: 10,
|
|
||||||
logicModeLineWidth: 2,
|
|
||||||
logicModeDistance: 7,
|
|
||||||
};
|
|
||||||
|
|
||||||
export class Lamp extends Container {
|
|
||||||
circleLamp: Graphics = new Graphics();
|
|
||||||
logicMode: Graphics = new Graphics();
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
this.addChild(this.circleLamp);
|
|
||||||
this.addChild(this.logicMode);
|
|
||||||
}
|
|
||||||
paint(radiusX: number, radiusY: number) {
|
|
||||||
this.circleLamp.clear();
|
|
||||||
this.circleLamp
|
|
||||||
.beginFill(LampEnum.lampDefaultColor, 1)
|
|
||||||
.drawCircle(radiusX, radiusY, lampConsts.lampRadius)
|
|
||||||
.endFill();
|
|
||||||
|
|
||||||
this.logicMode
|
|
||||||
.clear()
|
|
||||||
.lineStyle(lampConsts.logicModeLineWidth, LampEnum.logicModeColor)
|
|
||||||
.moveTo(
|
|
||||||
radiusX - lampConsts.logicModeDistance,
|
|
||||||
radiusY + lampConsts.logicModeDistance
|
|
||||||
)
|
|
||||||
.lineTo(
|
|
||||||
radiusX + lampConsts.logicModeDistance,
|
|
||||||
radiusY - lampConsts.logicModeDistance
|
|
||||||
)
|
|
||||||
.moveTo(
|
|
||||||
radiusX - lampConsts.logicModeDistance,
|
|
||||||
radiusY - lampConsts.logicModeDistance
|
|
||||||
)
|
|
||||||
.lineTo(
|
|
||||||
radiusX + lampConsts.logicModeDistance,
|
|
||||||
radiusY + lampConsts.logicModeDistance
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,51 +0,0 @@
|
|||||||
import { Container } from '@pixi/display';
|
|
||||||
import { Graphics } from 'pixi.js';
|
|
||||||
import { Lamp } from './Lamp';
|
|
||||||
|
|
||||||
export enum LampEnum {
|
|
||||||
lampPostColor = '0xc0c0c0',
|
|
||||||
}
|
|
||||||
|
|
||||||
const lampConsts = {
|
|
||||||
verticalLampPostLength: 20,
|
|
||||||
levelLampPostLength: 5,
|
|
||||||
postLineWidth: 3,
|
|
||||||
lampRadius: 10,
|
|
||||||
};
|
|
||||||
|
|
||||||
export class LampMainBody extends Container {
|
|
||||||
lampNum = 1;
|
|
||||||
lampPost: Graphics = new Graphics();
|
|
||||||
lamps: Lamp[] = [];
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
paint(lampNum: number) {
|
|
||||||
if (lampNum < 1) {
|
|
||||||
throw new Error('信号机灯数量异常');
|
|
||||||
}
|
|
||||||
this.lampNum = lampNum;
|
|
||||||
this.removeChildren(0);
|
|
||||||
this.lampPost = new Graphics();
|
|
||||||
this.lampPost
|
|
||||||
.lineStyle(lampConsts.postLineWidth, LampEnum.lampPostColor)
|
|
||||||
.moveTo(0, -lampConsts.verticalLampPostLength / 2)
|
|
||||||
.lineTo(0, lampConsts.verticalLampPostLength / 2)
|
|
||||||
.moveTo(0, 0)
|
|
||||||
.lineTo(lampConsts.levelLampPostLength, 0);
|
|
||||||
this.addChild(this.lampPost);
|
|
||||||
|
|
||||||
this.lamps = [];
|
|
||||||
for (let i = 0; i < this.lampNum; i++) {
|
|
||||||
const lamp = new Lamp();
|
|
||||||
const radiusX =
|
|
||||||
(1 + i * 2) * lampConsts.lampRadius + lampConsts.levelLampPostLength;
|
|
||||||
lamp.paint(radiusX, 0);
|
|
||||||
this.addChild(lamp);
|
|
||||||
this.lamps.push(lamp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// setState() {}
|
|
||||||
}
|
|
@ -1,102 +0,0 @@
|
|||||||
import { Graphics } from 'pixi.js';
|
|
||||||
import {
|
|
||||||
GraphicData,
|
|
||||||
JlGraphic,
|
|
||||||
JlGraphicTemplate,
|
|
||||||
VectorText,
|
|
||||||
} from 'src/jlgraphic';
|
|
||||||
import { LampMainBody } from './LampMainBody';
|
|
||||||
import { drawArrow } from '../CommonGraphics';
|
|
||||||
|
|
||||||
export interface ISignalData extends GraphicData {
|
|
||||||
get code(): string; // 编号
|
|
||||||
set code(v: string);
|
|
||||||
clone(): ISignalData;
|
|
||||||
copyFrom(data: ISignalData): void;
|
|
||||||
eq(other: ISignalData): boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum SignalColorEnum {
|
|
||||||
humanControlColor = '0xffff00',
|
|
||||||
fleetModeColor = '0x00ff00',
|
|
||||||
codeColor = '0X000000',
|
|
||||||
}
|
|
||||||
|
|
||||||
const signalConsts = {
|
|
||||||
lampNum: 1,
|
|
||||||
codeFontSize: 11,
|
|
||||||
nameOffsetY: 20,
|
|
||||||
fleetModeLength: 33,
|
|
||||||
fleetModeRadius: 10,
|
|
||||||
fleetModeLineWidth: 6,
|
|
||||||
};
|
|
||||||
export class Signal extends JlGraphic {
|
|
||||||
static Type = 'signal';
|
|
||||||
codeGraph: VectorText = new VectorText('');
|
|
||||||
humanControl: Graphics = new Graphics();
|
|
||||||
fleetMode: Graphics = new Graphics();
|
|
||||||
lampMainBody: LampMainBody = new LampMainBody();
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
super(Signal.Type);
|
|
||||||
this.codeGraph.name = 'signalCode';
|
|
||||||
this.addChild(this.codeGraph);
|
|
||||||
this.addChild(this.humanControl);
|
|
||||||
this.addChild(this.fleetMode);
|
|
||||||
this.addChild(this.lampMainBody);
|
|
||||||
}
|
|
||||||
|
|
||||||
get datas(): ISignalData {
|
|
||||||
return this.getDatas<ISignalData>();
|
|
||||||
}
|
|
||||||
|
|
||||||
paint(): void {
|
|
||||||
this.lampMainBody.paint(signalConsts.lampNum);
|
|
||||||
this.humanControl.beginFill(SignalColorEnum.humanControlColor, 1);
|
|
||||||
if (this.humanControl.drawRegularPolygon) {
|
|
||||||
this.humanControl.drawRegularPolygon(-10, 0, 10, 3, Math.PI / 2);
|
|
||||||
}
|
|
||||||
this.humanControl.endFill();
|
|
||||||
this.fleetMode.beginFill(SignalColorEnum.fleetModeColor, 1);
|
|
||||||
drawArrow(
|
|
||||||
this.fleetMode,
|
|
||||||
this.lampMainBody.width + signalConsts.fleetModeLength,
|
|
||||||
0,
|
|
||||||
signalConsts.fleetModeLength,
|
|
||||||
signalConsts.fleetModeRadius,
|
|
||||||
signalConsts.fleetModeLineWidth
|
|
||||||
);
|
|
||||||
this.fleetMode.endFill();
|
|
||||||
this.codeGraph.text = this.datas?.code || '信号机编号';
|
|
||||||
this.codeGraph.style.fill = SignalColorEnum.codeColor;
|
|
||||||
this.codeGraph.setVectorFontSize(signalConsts.codeFontSize);
|
|
||||||
this.codeGraph.anchor.set(0.5);
|
|
||||||
this.codeGraph.style.fill = SignalColorEnum.codeColor;
|
|
||||||
const codeTransform = this.datas?.childTransforms?.find(
|
|
||||||
(item) => item.name === 'signalCode'
|
|
||||||
);
|
|
||||||
if (codeTransform) {
|
|
||||||
const position = codeTransform?.transform.position;
|
|
||||||
const rotation = codeTransform?.transform?.rotation;
|
|
||||||
this.codeGraph.position.set(position?.x, position?.y);
|
|
||||||
this.codeGraph.rotation = rotation || 0;
|
|
||||||
} else {
|
|
||||||
this.codeGraph.position.set(0, signalConsts.nameOffsetY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
doRepaint(): void {
|
|
||||||
this.paint();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class SignalTemplate extends JlGraphicTemplate<Signal> {
|
|
||||||
constructor(dataTemplate: ISignalData) {
|
|
||||||
super(Signal.Type, {
|
|
||||||
dataTemplate,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
new(): Signal {
|
|
||||||
return new Signal();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,133 +0,0 @@
|
|||||||
import { FederatedPointerEvent, Point } from 'pixi.js';
|
|
||||||
import {
|
|
||||||
AbsorbableLine,
|
|
||||||
AbsorbablePosition,
|
|
||||||
GraphicApp,
|
|
||||||
GraphicDrawAssistant,
|
|
||||||
GraphicInteractionPlugin,
|
|
||||||
GraphicTransformEvent,
|
|
||||||
JlDrawApp,
|
|
||||||
JlGraphic,
|
|
||||||
} from 'src/jlgraphic';
|
|
||||||
import { ISignalData, Signal, SignalTemplate } from './Signal';
|
|
||||||
import { IscsFan } from '../iscs-fan/IscsFan';
|
|
||||||
|
|
||||||
export interface ISignalDrawOptions {
|
|
||||||
newData: () => ISignalData;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class SignalDraw extends GraphicDrawAssistant<
|
|
||||||
SignalTemplate,
|
|
||||||
ISignalData
|
|
||||||
> {
|
|
||||||
_signal: Signal | null = null;
|
|
||||||
|
|
||||||
constructor(app: JlDrawApp, template: SignalTemplate) {
|
|
||||||
super(
|
|
||||||
app,
|
|
||||||
template,
|
|
||||||
'svguse: ../../drawIcon.svg#icon-signal',
|
|
||||||
'信号机Signal'
|
|
||||||
);
|
|
||||||
|
|
||||||
signalInteraction.init(app);
|
|
||||||
}
|
|
||||||
|
|
||||||
public get signal(): Signal {
|
|
||||||
if (!this._signal) {
|
|
||||||
this._signal = this.graphicTemplate.new();
|
|
||||||
this.signal.loadData(this.graphicTemplate.datas);
|
|
||||||
this.container.addChild(this.signal);
|
|
||||||
}
|
|
||||||
return this._signal;
|
|
||||||
}
|
|
||||||
|
|
||||||
clearCache(): void {
|
|
||||||
//this.codeGraph.clear();
|
|
||||||
}
|
|
||||||
onRightClick(): void {
|
|
||||||
this.createAndStore(true);
|
|
||||||
}
|
|
||||||
onLeftUp(e: FederatedPointerEvent): void {
|
|
||||||
this.container.position.copyFrom(this.toCanvasCoordinates(e.global));
|
|
||||||
this.createAndStore(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
redraw(p: Point): void {
|
|
||||||
this.signal.paint();
|
|
||||||
this.container.position.set(p.x, p.y);
|
|
||||||
}
|
|
||||||
prepareData(data: ISignalData): boolean {
|
|
||||||
data.transform = this.container.saveTransform();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class signalInteraction extends GraphicInteractionPlugin<Signal> {
|
|
||||||
static Name = 'signal_transform';
|
|
||||||
constructor(app: JlDrawApp) {
|
|
||||||
super(signalInteraction.Name, app);
|
|
||||||
}
|
|
||||||
static init(app: JlDrawApp) {
|
|
||||||
return new signalInteraction(app);
|
|
||||||
}
|
|
||||||
filter(...grahpics: JlGraphic[]): Signal[] | undefined {
|
|
||||||
return grahpics
|
|
||||||
.filter((g) => g.type === Signal.Type)
|
|
||||||
.map((g) => g as Signal);
|
|
||||||
}
|
|
||||||
bind(g: Signal): void {
|
|
||||||
g.eventMode = 'static';
|
|
||||||
g.cursor = 'pointer';
|
|
||||||
g.scalable = true;
|
|
||||||
g.rotatable = true;
|
|
||||||
g.codeGraph.draggable = true;
|
|
||||||
g.codeGraph.selectable = true;
|
|
||||||
g.codeGraph.rotatable = true;
|
|
||||||
g.codeGraph.scalable = true;
|
|
||||||
g.codeGraph.transformSave = true;
|
|
||||||
g.codeGraph.eventMode = 'static';
|
|
||||||
g.codeGraph.on('transformstart', (e: GraphicTransformEvent) => {
|
|
||||||
if (e.isShift()) {
|
|
||||||
console.log(
|
|
||||||
'信号机画布坐标',
|
|
||||||
e.target.position,
|
|
||||||
e.target.getPositionOnCanvas()
|
|
||||||
);
|
|
||||||
const app = g.getGraphicApp();
|
|
||||||
app.setOptions({
|
|
||||||
absorbablePositions: buildAbsorbablePositions(app),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
// onScaleDragEnd() {
|
|
||||||
// console.log('-----------------');
|
|
||||||
// }
|
|
||||||
unbind(g: Signal): void {
|
|
||||||
g.eventMode = 'none';
|
|
||||||
g.scalable = false;
|
|
||||||
g.rotatable = false;
|
|
||||||
g.codeGraph.draggable = false;
|
|
||||||
g.codeGraph.selectable = false;
|
|
||||||
g.codeGraph.rotatable = false;
|
|
||||||
g.codeGraph.scalable = false;
|
|
||||||
g.codeGraph.transformSave = false;
|
|
||||||
g.codeGraph.eventMode = 'none';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function buildAbsorbablePositions(app: GraphicApp): AbsorbablePosition[] {
|
|
||||||
const canvas = app.canvas;
|
|
||||||
const store = app.queryStore;
|
|
||||||
const aps: AbsorbablePosition[] = [];
|
|
||||||
store.queryByType(IscsFan.Type).forEach((fan) => {
|
|
||||||
const p = fan.position;
|
|
||||||
aps.push(
|
|
||||||
new AbsorbableLine(new Point(0, p.y), new Point(canvas.width, p.y))
|
|
||||||
);
|
|
||||||
aps.push(
|
|
||||||
new AbsorbableLine(new Point(p.x, 0), new Point(p.x, canvas.height))
|
|
||||||
);
|
|
||||||
});
|
|
||||||
return aps;
|
|
||||||
}
|
|
@ -1,101 +0,0 @@
|
|||||||
import { Color, Graphics, IPointData, Point } from 'pixi.js';
|
|
||||||
import {
|
|
||||||
GraphicData,
|
|
||||||
JlGraphic,
|
|
||||||
JlGraphicTemplate,
|
|
||||||
VectorText,
|
|
||||||
} from 'src/jlgraphic';
|
|
||||||
|
|
||||||
export interface IStationData extends GraphicData {
|
|
||||||
get code(): string; // 编号
|
|
||||||
set code(v: string);
|
|
||||||
get hasCircle(): boolean; // 是否有圆圈--线网图
|
|
||||||
set hasCircle(v: boolean);
|
|
||||||
get radius(): number; // 半径
|
|
||||||
set radius(v: number);
|
|
||||||
get borderWidth(): number; // 线宽
|
|
||||||
set borderWidth(v: number);
|
|
||||||
get borderColor(): string; // 圆边框线色
|
|
||||||
set borderColor(v: string);
|
|
||||||
get fillColor(): string; // 圆填充颜色
|
|
||||||
set fillColor(v: string);
|
|
||||||
get codeColor(): string; // 车站字体颜色
|
|
||||||
set codeColor(v: string);
|
|
||||||
get codeFontSize(): number; // 车站字体大小
|
|
||||||
set codeFontSize(v: number);
|
|
||||||
get point(): IPointData; // 位置坐标
|
|
||||||
set point(point: IPointData);
|
|
||||||
get circlePoint(): IPointData; // 位置坐标
|
|
||||||
set circlePoint(point: IPointData);
|
|
||||||
clone(): IStationData;
|
|
||||||
copyFrom(data: IStationData): void;
|
|
||||||
eq(other: IStationData): boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Station extends JlGraphic {
|
|
||||||
static Type = 'station';
|
|
||||||
codeGraph: VectorText = new VectorText(''); //站台旁数字、字符
|
|
||||||
circleGraphic: Graphics;
|
|
||||||
constructor() {
|
|
||||||
super(Station.Type);
|
|
||||||
this.circleGraphic = new Graphics();
|
|
||||||
this.addChild(this.codeGraph);
|
|
||||||
this.addChild(this.circleGraphic);
|
|
||||||
}
|
|
||||||
|
|
||||||
get datas(): IStationData {
|
|
||||||
return this.getDatas<IStationData>();
|
|
||||||
}
|
|
||||||
doRepaint(): void {
|
|
||||||
this.circleGraphic.clear();
|
|
||||||
this.position.set(this.datas.point.x, this.datas.point.y);
|
|
||||||
const codeGraph = this.codeGraph;
|
|
||||||
if (this.datas.code == '') {
|
|
||||||
codeGraph.text = '车站Station';
|
|
||||||
} else {
|
|
||||||
codeGraph.text = this.datas.code;
|
|
||||||
}
|
|
||||||
codeGraph.style.fill = this.datas.codeColor;
|
|
||||||
codeGraph.setVectorFontSize(this.datas.codeFontSize);
|
|
||||||
codeGraph.anchor.set(0.5);
|
|
||||||
if (this.datas.hasCircle) {
|
|
||||||
const circleGraphic = this.circleGraphic;
|
|
||||||
circleGraphic.lineStyle(
|
|
||||||
this.datas.borderWidth,
|
|
||||||
new Color(this.datas.borderColor)
|
|
||||||
);
|
|
||||||
circleGraphic.beginFill(this.datas.fillColor, 1);
|
|
||||||
circleGraphic.drawCircle(0, 0, this.datas.radius);
|
|
||||||
circleGraphic.endFill;
|
|
||||||
circleGraphic.position.set(
|
|
||||||
this.datas.circlePoint.x,
|
|
||||||
this.datas.circlePoint.y
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class StationTemplate extends JlGraphicTemplate<Station> {
|
|
||||||
hasCircle: boolean;
|
|
||||||
radius: number;
|
|
||||||
borderWidth: number;
|
|
||||||
borderColor: string;
|
|
||||||
fillColor: string;
|
|
||||||
codeColor: string;
|
|
||||||
codeFontSize: number;
|
|
||||||
circlePoint: IPointData;
|
|
||||||
constructor() {
|
|
||||||
super(Station.Type);
|
|
||||||
this.hasCircle = false;
|
|
||||||
this.radius = 5;
|
|
||||||
this.borderWidth = 1;
|
|
||||||
this.borderColor = '0xff0000';
|
|
||||||
this.fillColor = '0xff0000';
|
|
||||||
this.codeColor = '0xF48815';
|
|
||||||
this.codeFontSize = 22;
|
|
||||||
this.circlePoint = new Point(0, -20);
|
|
||||||
}
|
|
||||||
new(): Station {
|
|
||||||
return new Station();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,93 +0,0 @@
|
|||||||
import { FederatedPointerEvent, Point } from 'pixi.js';
|
|
||||||
import {
|
|
||||||
GraphicDrawAssistant,
|
|
||||||
GraphicInteractionPlugin,
|
|
||||||
JlDrawApp,
|
|
||||||
JlGraphic,
|
|
||||||
VectorText,
|
|
||||||
} from 'src/jlgraphic';
|
|
||||||
|
|
||||||
import { IStationData, Station, StationTemplate } from './Station';
|
|
||||||
|
|
||||||
export interface IStationDrawOptions {
|
|
||||||
newData: () => IStationData;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class StationDraw extends GraphicDrawAssistant<
|
|
||||||
StationTemplate,
|
|
||||||
IStationData
|
|
||||||
> {
|
|
||||||
point: Point = new Point(0, 0);
|
|
||||||
codeGraph: VectorText = new VectorText('');
|
|
||||||
|
|
||||||
constructor(app: JlDrawApp, createData: () => IStationData) {
|
|
||||||
super(app, new StationTemplate(), createData, Station.Type, '车站Station');
|
|
||||||
this.container.addChild(this.codeGraph);
|
|
||||||
stationInteraction.init(app);
|
|
||||||
}
|
|
||||||
|
|
||||||
bind(): void {
|
|
||||||
super.bind();
|
|
||||||
}
|
|
||||||
unbind(): void {
|
|
||||||
super.unbind();
|
|
||||||
}
|
|
||||||
|
|
||||||
clearCache(): void {
|
|
||||||
//this.codeGraph.clear();
|
|
||||||
}
|
|
||||||
onLeftDown(e: FederatedPointerEvent): void {
|
|
||||||
const { x, y } = this.toCanvasCoordinates(e.global);
|
|
||||||
const p = new Point(x, y);
|
|
||||||
this.point = p;
|
|
||||||
this.createAndStore(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
redraw(p: Point): void {
|
|
||||||
const codeGraph = this.codeGraph;
|
|
||||||
codeGraph.text = '车站Station';
|
|
||||||
codeGraph.anchor.set(0.5);
|
|
||||||
codeGraph.style.fill = '0xf48815';
|
|
||||||
codeGraph.position.set(p.x, p.y);
|
|
||||||
codeGraph.setVectorFontSize(22);
|
|
||||||
}
|
|
||||||
prepareData(data: IStationData): boolean {
|
|
||||||
const template = this.graphicTemplate;
|
|
||||||
data.point = this.point;
|
|
||||||
data.hasCircle = template.hasCircle;
|
|
||||||
data.radius = template.radius;
|
|
||||||
data.borderWidth = template.borderWidth;
|
|
||||||
data.borderColor = template.borderColor;
|
|
||||||
data.fillColor = template.fillColor;
|
|
||||||
data.codeColor = template.codeColor;
|
|
||||||
data.codeFontSize = template.codeFontSize;
|
|
||||||
data.circlePoint = template.circlePoint;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class stationInteraction extends GraphicInteractionPlugin<Station> {
|
|
||||||
static Name = 'station_transform';
|
|
||||||
constructor(app: JlDrawApp) {
|
|
||||||
super(stationInteraction.Name, app);
|
|
||||||
}
|
|
||||||
static init(app: JlDrawApp) {
|
|
||||||
return new stationInteraction(app);
|
|
||||||
}
|
|
||||||
filter(...grahpics: JlGraphic[]): Station[] | undefined {
|
|
||||||
return grahpics
|
|
||||||
.filter((g) => g.type === Station.Type)
|
|
||||||
.map((g) => g as Station);
|
|
||||||
}
|
|
||||||
bind(g: Station): void {
|
|
||||||
g.eventMode = 'static';
|
|
||||||
g.cursor = 'pointer';
|
|
||||||
g.scalable = true;
|
|
||||||
g.rotatable = true;
|
|
||||||
}
|
|
||||||
unbind(g: Station): void {
|
|
||||||
g.eventMode = 'none';
|
|
||||||
g.scalable = false;
|
|
||||||
g.rotatable = false;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,185 +0,0 @@
|
|||||||
import { Color, Graphics, IPointData } from 'pixi.js';
|
|
||||||
import {
|
|
||||||
GraphicData,
|
|
||||||
JlGraphic,
|
|
||||||
JlGraphicTemplate,
|
|
||||||
VectorText,
|
|
||||||
} from 'src/jlgraphic';
|
|
||||||
|
|
||||||
export interface ITrainData extends GraphicData {
|
|
||||||
get code(): string; // 车号
|
|
||||||
set code(v: string);
|
|
||||||
get codeColor(): string; // 车号颜色
|
|
||||||
set codeColor(v: string);
|
|
||||||
get codeFontSize(): number; // 车号字体大小
|
|
||||||
set codeFontSize(v: number);
|
|
||||||
get trainDirection(): string; // 行驶方向
|
|
||||||
set trainDirection(v: string);
|
|
||||||
get hasBorder(): boolean; // 是否有边框
|
|
||||||
set hasBorder(v: boolean);
|
|
||||||
get borderWidth(): number; // 边框线宽
|
|
||||||
set borderWidth(v: number);
|
|
||||||
get borderColor(): string; // 边框颜色
|
|
||||||
set borderColor(v: string);
|
|
||||||
get headColor(): string; // 箭头颜色
|
|
||||||
set headColor(v: string);
|
|
||||||
get bodyColor(): string; // 背景色
|
|
||||||
set bodyColor(v: string);
|
|
||||||
get point(): IPointData; // 位置坐标
|
|
||||||
set point(point: IPointData);
|
|
||||||
clone(): ITrainData;
|
|
||||||
copyFrom(data: ITrainData): void;
|
|
||||||
eq(other: ITrainData): boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 列车颜色
|
|
||||||
export enum TrainColorEnum {
|
|
||||||
headColor = '0x00FF00', // 箭头颜色
|
|
||||||
bodyColor = '0xA388B1', // 背景色
|
|
||||||
codeColor = '0xffffff', // 车号颜色
|
|
||||||
borderColor = '0xA3E198', // 边框的颜色
|
|
||||||
}
|
|
||||||
|
|
||||||
export const trainConsts = {
|
|
||||||
borderWidth: 1,
|
|
||||||
codeFontSize: 22,
|
|
||||||
marginX: 2, // 图形x轴边距
|
|
||||||
pauseW: 2, // 停止框宽度
|
|
||||||
};
|
|
||||||
|
|
||||||
export class Train extends JlGraphic {
|
|
||||||
static Type = 'Train';
|
|
||||||
|
|
||||||
arrowLeft: Graphics;
|
|
||||||
pauseLeft: Graphics;
|
|
||||||
arrowRight: Graphics;
|
|
||||||
pauseRight: Graphics;
|
|
||||||
codeRact: Graphics;
|
|
||||||
codeGraph: VectorText = new VectorText(''); //车号
|
|
||||||
constructor() {
|
|
||||||
super(Train.Type);
|
|
||||||
this.arrowLeft = new Graphics();
|
|
||||||
this.pauseLeft = new Graphics();
|
|
||||||
this.arrowRight = new Graphics();
|
|
||||||
this.pauseRight = new Graphics();
|
|
||||||
this.codeRact = new Graphics();
|
|
||||||
this.addChild(this.arrowLeft);
|
|
||||||
this.addChild(this.pauseLeft);
|
|
||||||
this.addChild(this.arrowRight);
|
|
||||||
this.addChild(this.pauseRight);
|
|
||||||
this.addChild(this.codeRact);
|
|
||||||
this.addChild(this.codeGraph);
|
|
||||||
this.codeGraph.setVectorFontSize(trainConsts.codeFontSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
get datas(): ITrainData {
|
|
||||||
return this.getDatas<ITrainData>();
|
|
||||||
}
|
|
||||||
doRepaint(): void {
|
|
||||||
this.position.set(this.datas.point.x, this.datas.point.y);
|
|
||||||
const codeGraph = this.codeGraph;
|
|
||||||
const codeRact = this.codeRact;
|
|
||||||
if (this.datas.code == '') {
|
|
||||||
codeGraph.text = '01110111';
|
|
||||||
} else {
|
|
||||||
codeGraph.text = this.datas.code;
|
|
||||||
}
|
|
||||||
codeGraph.setVectorFontSize(this.datas.codeFontSize);
|
|
||||||
codeGraph.anchor.set(0.5);
|
|
||||||
const style = {
|
|
||||||
fill: this.datas.codeColor,
|
|
||||||
padding: 5,
|
|
||||||
};
|
|
||||||
codeGraph.style = style;
|
|
||||||
const {
|
|
||||||
x: codeX,
|
|
||||||
y: codeY,
|
|
||||||
width: codeWidth,
|
|
||||||
height: codeHeight,
|
|
||||||
} = codeGraph.getLocalBounds();
|
|
||||||
const marginX = trainConsts.marginX;
|
|
||||||
const pauseW = trainConsts.pauseW;
|
|
||||||
const arrowLeft = this.arrowLeft;
|
|
||||||
arrowLeft.beginFill(this.datas.headColor, 1);
|
|
||||||
arrowLeft.drawPolygon([
|
|
||||||
-codeHeight * 0.4 - marginX - pauseW - marginX - codeWidth / 2,
|
|
||||||
0,
|
|
||||||
-marginX - pauseW - marginX - codeWidth / 2,
|
|
||||||
codeHeight / 2,
|
|
||||||
-marginX - pauseW - marginX - codeWidth / 2,
|
|
||||||
-codeHeight / 2,
|
|
||||||
]);
|
|
||||||
arrowLeft.endFill();
|
|
||||||
this.pauseLeft.beginFill(this.datas.headColor, 1);
|
|
||||||
this.pauseLeft.drawRect(0, 0, pauseW, codeHeight);
|
|
||||||
this.pauseLeft.endFill();
|
|
||||||
this.pauseLeft.position.set(
|
|
||||||
-marginX - pauseW - codeWidth / 2,
|
|
||||||
-codeHeight / 2
|
|
||||||
);
|
|
||||||
this.pauseRight.beginFill(this.datas.headColor, 1);
|
|
||||||
this.pauseRight.drawRect(0, 0, pauseW, codeHeight);
|
|
||||||
this.pauseRight.endFill();
|
|
||||||
this.pauseRight.position.set(marginX + codeWidth / 2, -codeHeight / 2);
|
|
||||||
const arrowRight = this.arrowRight;
|
|
||||||
arrowRight.beginFill(this.datas.headColor, 1);
|
|
||||||
arrowRight.drawPolygon([
|
|
||||||
codeWidth / 2 + marginX + pauseW + marginX + codeHeight * 0.4,
|
|
||||||
0,
|
|
||||||
codeWidth / 2 + marginX + pauseW + marginX,
|
|
||||||
codeHeight / 2,
|
|
||||||
codeWidth / 2 + marginX + pauseW + marginX,
|
|
||||||
-codeHeight / 2,
|
|
||||||
]);
|
|
||||||
arrowRight.endFill();
|
|
||||||
if (this.datas.hasBorder) {
|
|
||||||
codeRact.visible = true;
|
|
||||||
codeRact.lineStyle(
|
|
||||||
this.datas.borderWidth,
|
|
||||||
new Color(this.datas.borderColor)
|
|
||||||
);
|
|
||||||
codeRact.beginFill(new Color(this.datas.bodyColor));
|
|
||||||
codeRact.drawRect(codeX, codeY, codeWidth, codeHeight);
|
|
||||||
codeRact.endFill();
|
|
||||||
} else {
|
|
||||||
codeRact.visible = false;
|
|
||||||
}
|
|
||||||
// 运行方向控制箭头停止显隐
|
|
||||||
if (this.datas.trainDirection == 'right') {
|
|
||||||
this.arrowLeft.visible = false;
|
|
||||||
this.arrowRight.visible = true;
|
|
||||||
this.pauseLeft.visible = false;
|
|
||||||
this.pauseRight.visible = true;
|
|
||||||
} else {
|
|
||||||
this.arrowLeft.visible = true;
|
|
||||||
this.arrowRight.visible = false;
|
|
||||||
this.pauseLeft.visible = true;
|
|
||||||
this.pauseRight.visible = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class TrainTemplate extends JlGraphicTemplate<Train> {
|
|
||||||
trainDirection: string;
|
|
||||||
codeFontSize: number;
|
|
||||||
hasBorder: boolean;
|
|
||||||
borderWidth: number;
|
|
||||||
borderColor: string;
|
|
||||||
headColor: string;
|
|
||||||
codeColor: string;
|
|
||||||
bodyColor: string;
|
|
||||||
constructor() {
|
|
||||||
super(Train.Type);
|
|
||||||
this.trainDirection = 'left';
|
|
||||||
this.codeFontSize = trainConsts.codeFontSize;
|
|
||||||
this.hasBorder = true;
|
|
||||||
this.borderWidth = trainConsts.borderWidth;
|
|
||||||
this.borderColor = TrainColorEnum.borderColor;
|
|
||||||
this.headColor = TrainColorEnum.headColor;
|
|
||||||
this.codeColor = TrainColorEnum.codeColor;
|
|
||||||
this.bodyColor = TrainColorEnum.bodyColor;
|
|
||||||
}
|
|
||||||
new(): Train {
|
|
||||||
return new Train();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,138 +0,0 @@
|
|||||||
import { Color, FederatedPointerEvent, Graphics, Point } from 'pixi.js';
|
|
||||||
import {
|
|
||||||
GraphicDrawAssistant,
|
|
||||||
GraphicInteractionPlugin,
|
|
||||||
JlDrawApp,
|
|
||||||
JlGraphic,
|
|
||||||
VectorText,
|
|
||||||
} from 'src/jlgraphic';
|
|
||||||
|
|
||||||
import { ITrainData, Train, TrainTemplate, trainConsts } from './Train';
|
|
||||||
|
|
||||||
export interface ITrainDrawOptions {
|
|
||||||
newData: () => ITrainData;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class TrainDraw extends GraphicDrawAssistant<TrainTemplate, ITrainData> {
|
|
||||||
point: Point = new Point(0, 0);
|
|
||||||
arrowLeft: Graphics = new Graphics();
|
|
||||||
pauseLeft: Graphics = new Graphics();
|
|
||||||
codeRact: Graphics = new Graphics();
|
|
||||||
|
|
||||||
constructor(app: JlDrawApp, createData: () => ITrainData) {
|
|
||||||
super(app, new TrainTemplate(), createData, Train.Type, '列车Train');
|
|
||||||
this.container.addChild(this.arrowLeft);
|
|
||||||
this.container.addChild(this.pauseLeft);
|
|
||||||
this.container.addChild(this.codeRact);
|
|
||||||
this.graphicTemplate.hasBorder = true;
|
|
||||||
trainInteraction.init(app);
|
|
||||||
}
|
|
||||||
|
|
||||||
bind(): void {
|
|
||||||
super.bind();
|
|
||||||
}
|
|
||||||
unbind(): void {
|
|
||||||
super.unbind();
|
|
||||||
}
|
|
||||||
|
|
||||||
clearCache(): void {
|
|
||||||
this.arrowLeft.clear();
|
|
||||||
this.pauseLeft.clear();
|
|
||||||
this.codeRact.clear();
|
|
||||||
}
|
|
||||||
onLeftDown(e: FederatedPointerEvent): void {
|
|
||||||
const { x, y } = this.toCanvasCoordinates(e.global);
|
|
||||||
const p = new Point(x, y);
|
|
||||||
this.point = p;
|
|
||||||
this.createAndStore(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
redraw(p: Point): void {
|
|
||||||
const template = this.graphicTemplate;
|
|
||||||
const codeGraph = new VectorText(''); // 车号
|
|
||||||
codeGraph.setVectorFontSize(22);
|
|
||||||
codeGraph.anchor.set(0.5);
|
|
||||||
codeGraph.text = '01110111';
|
|
||||||
const style = { padding: 5 };
|
|
||||||
codeGraph.style = style;
|
|
||||||
const { width, height } = codeGraph.getLocalBounds();
|
|
||||||
codeGraph.destroy();
|
|
||||||
const marginX = trainConsts.marginX;
|
|
||||||
const pauseW = trainConsts.pauseW;
|
|
||||||
// 边框
|
|
||||||
if (template.hasBorder) {
|
|
||||||
const codeRact = this.codeRact;
|
|
||||||
codeRact.clear();
|
|
||||||
codeRact.lineStyle(template.borderWidth, new Color(template.borderColor));
|
|
||||||
codeRact.beginFill(new Color(template.bodyColor));
|
|
||||||
codeRact.drawRect(-width / 2, -height / 2, width, height);
|
|
||||||
codeRact.endFill();
|
|
||||||
codeRact.position.set(p.x, p.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 箭头
|
|
||||||
const arrowLeft = this.arrowLeft;
|
|
||||||
arrowLeft.clear();
|
|
||||||
this.point.set(p.x, p.y);
|
|
||||||
arrowLeft.beginFill(template.headColor, 1);
|
|
||||||
arrowLeft.drawPolygon([
|
|
||||||
-height * 0.4 - marginX - pauseW - marginX - width / 2,
|
|
||||||
0,
|
|
||||||
-marginX - pauseW - marginX - width / 2,
|
|
||||||
height / 2,
|
|
||||||
-marginX - pauseW - marginX - width / 2,
|
|
||||||
-height / 2,
|
|
||||||
]);
|
|
||||||
arrowLeft.endFill();
|
|
||||||
arrowLeft.position.set(this.point.x, this.point.y);
|
|
||||||
|
|
||||||
// 停止框
|
|
||||||
const pauseLeft = this.pauseLeft;
|
|
||||||
pauseLeft.clear();
|
|
||||||
pauseLeft.beginFill(template.headColor, 1);
|
|
||||||
pauseLeft.drawRect(0, 0, pauseW, height);
|
|
||||||
pauseLeft.endFill();
|
|
||||||
pauseLeft.position.set(
|
|
||||||
this.point.x - marginX - pauseW - width / 2,
|
|
||||||
this.point.y - height / 2
|
|
||||||
);
|
|
||||||
}
|
|
||||||
prepareData(data: ITrainData): boolean {
|
|
||||||
const template = this.graphicTemplate;
|
|
||||||
data.code = '01110111';
|
|
||||||
data.codeColor = template.codeColor;
|
|
||||||
data.codeFontSize = template.codeFontSize;
|
|
||||||
data.hasBorder = template.hasBorder;
|
|
||||||
data.trainDirection = template.trainDirection;
|
|
||||||
data.point = this.point;
|
|
||||||
data.borderWidth = template.borderWidth;
|
|
||||||
data.borderColor = template.borderColor;
|
|
||||||
data.headColor = template.headColor;
|
|
||||||
data.bodyColor = template.bodyColor;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class trainInteraction extends GraphicInteractionPlugin<Train> {
|
|
||||||
static Name = 'train_transform';
|
|
||||||
constructor(app: JlDrawApp) {
|
|
||||||
super(trainInteraction.Name, app);
|
|
||||||
}
|
|
||||||
static init(app: JlDrawApp) {
|
|
||||||
return new trainInteraction(app);
|
|
||||||
}
|
|
||||||
filter(...grahpics: JlGraphic[]): Train[] | undefined {
|
|
||||||
return grahpics.filter((g) => g.type === Train.Type).map((g) => g as Train);
|
|
||||||
}
|
|
||||||
bind(g: Train): void {
|
|
||||||
g.eventMode = 'static';
|
|
||||||
g.cursor = 'pointer';
|
|
||||||
g.scalable = true;
|
|
||||||
g.rotatable = true;
|
|
||||||
}
|
|
||||||
unbind(g: Train): void {
|
|
||||||
g.eventMode = 'none';
|
|
||||||
g.scalable = false;
|
|
||||||
g.rotatable = false;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
import { GraphicData, JlGraphic } from 'src/jlgraphic';
|
|
||||||
|
|
||||||
export type ITrunoutData = GraphicData;
|
|
||||||
|
|
||||||
export class Turnout extends JlGraphic {
|
|
||||||
doRepaint(): void {
|
|
||||||
throw new Error('Method not implemented.');
|
|
||||||
}
|
|
||||||
}
|
|
7
src/index.ts
Normal file
7
src/index.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
export * from './core';
|
||||||
|
export * from './graphic';
|
||||||
|
export * from './app';
|
||||||
|
export * from './operation';
|
||||||
|
export * from './utils';
|
||||||
|
export * from './plugins';
|
||||||
|
export * from './message';
|
1
src/message/index.ts
Normal file
1
src/message/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './MessageBroker';
|
@ -70,7 +70,6 @@ export class OperationRecord {
|
|||||||
if (this.undoStack.length >= this.maxLen) {
|
if (this.undoStack.length >= this.maxLen) {
|
||||||
this.undoStack.shift();
|
this.undoStack.shift();
|
||||||
}
|
}
|
||||||
// console.log('operation record', op)
|
|
||||||
this.undoStack.push(op);
|
this.undoStack.push(op);
|
||||||
this.redoStack.splice(0, this.redoStack.length);
|
this.redoStack.splice(0, this.redoStack.length);
|
||||||
}
|
}
|
||||||
@ -79,7 +78,6 @@ export class OperationRecord {
|
|||||||
*/
|
*/
|
||||||
undo() {
|
undo() {
|
||||||
const op = this.undoStack.pop();
|
const op = this.undoStack.pop();
|
||||||
// console.log('撤销', op);
|
|
||||||
if (op) {
|
if (op) {
|
||||||
op.undo1();
|
op.undo1();
|
||||||
this.redoStack.push(op);
|
this.redoStack.push(op);
|
||||||
@ -90,7 +88,6 @@ export class OperationRecord {
|
|||||||
*/
|
*/
|
||||||
redo() {
|
redo() {
|
||||||
const op = this.redoStack.pop();
|
const op = this.redoStack.pop();
|
||||||
// console.log('重做', op);
|
|
||||||
if (op) {
|
if (op) {
|
||||||
op.redo1();
|
op.redo1();
|
||||||
this.undoStack.push(op);
|
this.undoStack.push(op);
|
1
src/operation/index.ts
Normal file
1
src/operation/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './JlOperation';
|
@ -153,10 +153,6 @@ export class CommonMouseTool extends AppInteractionPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onDragStart(event: AppDragEvent) {
|
onDragStart(event: AppDragEvent) {
|
||||||
// console.log(
|
|
||||||
// 'start',
|
|
||||||
// `pointerType:${event.original.pointerType},pointerId:${event.original.pointerId},button: ${event.original.button},buttons:${event.original.buttons}`
|
|
||||||
// );
|
|
||||||
if (this.boxSelect && event.target.isCanvas() && event.isLeftButton) {
|
if (this.boxSelect && event.target.isCanvas() && event.isLeftButton) {
|
||||||
this.box.visible = true;
|
this.box.visible = true;
|
||||||
this.app.interactionPlugin(ViewportMovePlugin.Name).resume();
|
this.app.interactionPlugin(ViewportMovePlugin.Name).resume();
|
||||||
@ -165,19 +161,11 @@ export class CommonMouseTool extends AppInteractionPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onDragMove(event: AppDragEvent) {
|
onDragMove(event: AppDragEvent) {
|
||||||
// console.log(
|
|
||||||
// 'moving',
|
|
||||||
// `pointerType:${event.original.pointerType},pointerId:${event.original.pointerId},button: ${event.original.button},buttons:${event.original.buttons}`
|
|
||||||
// );
|
|
||||||
if (this.boxSelect && event.target.isCanvas()) {
|
if (this.boxSelect && event.target.isCanvas()) {
|
||||||
this.boxSelectDraw(event.start, event.end);
|
this.boxSelectDraw(event.start, event.end);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onDragEnd(event: AppDragEvent) {
|
onDragEnd(event: AppDragEvent) {
|
||||||
// console.log(
|
|
||||||
// 'end',
|
|
||||||
// `pointerType:${event.original.pointerType},pointerId:${event.original.pointerId},button: ${event.original.button},buttons:${event.original.buttons}`
|
|
||||||
// );
|
|
||||||
if (this.boxSelect && event.target.isCanvas() && event.isLeftButton) {
|
if (this.boxSelect && event.target.isCanvas() && event.isLeftButton) {
|
||||||
this.boxSelectDraw(event.start, event.end);
|
this.boxSelectDraw(event.start, event.end);
|
||||||
this.boxSelectGraphicCheck();
|
this.boxSelectGraphicCheck();
|
||||||
@ -232,7 +220,6 @@ export class CommonMouseTool extends AppInteractionPlugin {
|
|||||||
const graphic = this.leftDownTarget.getGraphic();
|
const graphic = this.leftDownTarget.getGraphic();
|
||||||
if (graphic) {
|
if (graphic) {
|
||||||
const app = this.app;
|
const app = this.app;
|
||||||
// console.log(this.leftDownTarget.isGraphic());
|
|
||||||
// 图形选中
|
// 图形选中
|
||||||
if (!e.ctrlKey && !graphic.selected && graphic.selectable) {
|
if (!e.ctrlKey && !graphic.selected && graphic.selectable) {
|
||||||
app.updateSelected(graphic);
|
app.updateSelected(graphic);
|
@ -403,7 +403,6 @@ export class BezierCurveEditPlugin extends LineEditPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
initEditPoints() {
|
initEditPoints() {
|
||||||
// console.log('initEditPoints');
|
|
||||||
const cps = this.graphic.localToCanvasPoints(...this.linePoints);
|
const cps = this.graphic.localToCanvasPoints(...this.linePoints);
|
||||||
for (let i = 0; i < cps.length; i++) {
|
for (let i = 0; i < cps.length; i++) {
|
||||||
const p = cps[i];
|
const p = cps[i];
|
@ -204,7 +204,6 @@ export class GraphicTransformPlugin extends InteractionPluginBase {
|
|||||||
aps.push(ap);
|
aps.push(ap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// console.log(positions, aps);
|
|
||||||
return aps;
|
return aps;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -319,8 +318,6 @@ export class GraphicTransformPlugin extends InteractionPluginBase {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// const dt = new Date().getTime() - start;
|
|
||||||
// console.log('拖拽耗时', `${dt}ms`, targets);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -539,7 +536,6 @@ export class TransformPoints extends Container {
|
|||||||
KeyListener.create({
|
KeyListener.create({
|
||||||
value: '' + i,
|
value: '' + i,
|
||||||
onPress: () => {
|
onPress: () => {
|
||||||
// console.log('修改角度step');
|
|
||||||
this.angleStep = i;
|
this.angleStep = i;
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@ -707,7 +703,6 @@ export class TransformPoints extends Container {
|
|||||||
// 计算缩放比例,并根据是否保持纵横比两种情况进行缩放处理
|
// 计算缩放比例,并根据是否保持纵横比两种情况进行缩放处理
|
||||||
const sx = originWidth == 0 ? this.originScale.x : width / originWidth;
|
const sx = originWidth == 0 ? this.originScale.x : width / originWidth;
|
||||||
const sy = originHeight == 0 ? this.originScale.y : height / originHeight;
|
const sy = originHeight == 0 ? this.originScale.y : height / originHeight;
|
||||||
// console.log(originWidth, originHeight, width, height, sx, sy);
|
|
||||||
if (this.obj.keepAspectRatio) {
|
if (this.obj.keepAspectRatio) {
|
||||||
let max = Math.max(sx, sy);
|
let max = Math.max(sx, sy);
|
||||||
if (originWidth == 0) {
|
if (originWidth == 0) {
|
@ -238,7 +238,6 @@ export class DragPlugin extends OtherInteractionPlugin {
|
|||||||
|
|
||||||
// drag移动处理
|
// drag移动处理
|
||||||
if (this.target && this.drag && this.start) {
|
if (this.target && this.drag && this.start) {
|
||||||
// console.log('drag move', e.movement);
|
|
||||||
this.app.emit(
|
this.app.emit(
|
||||||
'drag_op_move',
|
'drag_op_move',
|
||||||
new AppDragEvent(this.app, 'move', this.target, e, this.start)
|
new AppDragEvent(this.app, 'move', this.target, e, this.start)
|
||||||
@ -249,7 +248,6 @@ export class DragPlugin extends OtherInteractionPlugin {
|
|||||||
|
|
||||||
onPointerUp(e: FederatedPointerEvent) {
|
onPointerUp(e: FederatedPointerEvent) {
|
||||||
if (this.target && this.drag && this.start) {
|
if (this.target && this.drag && this.start) {
|
||||||
// console.log('drag end');
|
|
||||||
this.app.emit(
|
this.app.emit(
|
||||||
'drag_op_end',
|
'drag_op_end',
|
||||||
new AppDragEvent(this.app, 'end', this.target, e, this.start)
|
new AppDragEvent(this.app, 'end', this.target, e, this.start)
|
@ -18,7 +18,6 @@ export class GlobalKeyboardHelper {
|
|||||||
if (e.ctrlKey) {
|
if (e.ctrlKey) {
|
||||||
if (e.code == 'KeyS') {
|
if (e.code == 'KeyS') {
|
||||||
// 屏蔽全局Ctrl+S保存操作
|
// 屏蔽全局Ctrl+S保存操作
|
||||||
// console.log('屏蔽全局Ctrl+S')
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -81,7 +80,6 @@ export class JlGraphicAppKeyboardPlugin {
|
|||||||
const onMouseUpdateTarget = (e: MouseEvent) => {
|
const onMouseUpdateTarget = (e: MouseEvent) => {
|
||||||
const node = e.target as Node;
|
const node = e.target as Node;
|
||||||
target = node;
|
target = node;
|
||||||
// console.log('Mousedown Event', node.nodeName, node.nodeType, node.nodeValue)
|
|
||||||
};
|
};
|
||||||
const keydownHandle = (e: KeyboardEvent) => {
|
const keydownHandle = (e: KeyboardEvent) => {
|
||||||
// console.debug(e.key, e.code, e.keyCode);
|
// console.debug(e.key, e.code, e.keyCode);
|
||||||
@ -147,7 +145,6 @@ export class JlGraphicAppKeyboardPlugin {
|
|||||||
stack.push(old);
|
stack.push(old);
|
||||||
}
|
}
|
||||||
map.set(keyListener.identifier, keyListener);
|
map.set(keyListener.identifier, keyListener);
|
||||||
// console.log(this.getAllListenedKeys());
|
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 移除按键监听,若是当前注册的监听,尝试从栈中取出作为按键监听器,若是旧的,则同时移除栈中的监听
|
* 移除按键监听,若是当前注册的监听,尝试从栈中取出作为按键监听器,若是旧的,则同时移除栈中的监听
|
||||||
@ -172,7 +169,6 @@ export class JlGraphicAppKeyboardPlugin {
|
|||||||
stack.splice(index, 1);
|
stack.splice(index, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// console.log(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getKeyListenerBy(key: string | number): Map<string, KeyListener> | undefined {
|
getKeyListenerBy(key: string | number): Map<string, KeyListener> | undefined {
|
||||||
@ -307,7 +303,6 @@ export class KeyListener {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this.pressTriggerEveryTime || !this.isPress) {
|
if (this.pressTriggerEveryTime || !this.isPress) {
|
||||||
// console.log('Keydown: ', e, this.onPress);
|
|
||||||
this.isPress = true;
|
this.isPress = true;
|
||||||
if (this.onPress) {
|
if (this.onPress) {
|
||||||
this.onPress(e, app);
|
this.onPress(e, app);
|
||||||
@ -338,7 +333,6 @@ export class KeyListener {
|
|||||||
|
|
||||||
release(e: KeyboardEvent, app: IGraphicApp): void {
|
release(e: KeyboardEvent, app: IGraphicApp): void {
|
||||||
if (this.isPress) {
|
if (this.isPress) {
|
||||||
// console.log('Keyup : ', e.key, e);
|
|
||||||
this.isPress = false;
|
this.isPress = false;
|
||||||
if (this.onRelease) {
|
if (this.onRelease) {
|
||||||
this.onRelease(e, app);
|
this.onRelease(e, app);
|
6
src/plugins/index.ts
Normal file
6
src/plugins/index.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
export * from './InteractionPlugin';
|
||||||
|
export * from './CommonMousePlugin';
|
||||||
|
export * from './KeyboardPlugin';
|
||||||
|
export * from './CopyPlugin';
|
||||||
|
export * from './GraphicTransformPlugin';
|
||||||
|
export * from './AnimationManager';
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user