目录结构及编译调整
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
6927
lib/index.js
6927
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>",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"main": "src/jlgraphic",
|
||||
"main": "lib",
|
||||
"scripts": {
|
||||
"build": "rollup -c rollup.config.ts --configPlugin typescript"
|
||||
},
|
||||
|
@ -3,14 +3,21 @@ import typescript from '@rollup/plugin-typescript'
|
||||
|
||||
|
||||
const config: RollupOptions = {
|
||||
input: 'src/jlgraphic/index.ts',
|
||||
input: 'src/index.ts',
|
||||
output: {
|
||||
file: 'lib/index.js',
|
||||
format: 'cjs',
|
||||
dir: 'lib',
|
||||
format: 'esm',
|
||||
},
|
||||
external: [
|
||||
'pixi.js', 'pixi-viewport', '@stomp/stompjs', 'mqtt', 'eventemitter3'
|
||||
],
|
||||
logLevel: 'debug',
|
||||
plugins: [
|
||||
typescript({
|
||||
|
||||
declaration: true,
|
||||
declarationDir: 'lib',
|
||||
include: ['src/**/*'],
|
||||
tsconfig: './tsconfig.json',
|
||||
})
|
||||
],
|
||||
}
|
||||
|
@ -719,7 +719,6 @@ abstract class GraphicSceneBase
|
||||
* @param options
|
||||
*/
|
||||
setOptions(options: GraphicAppOptions) {
|
||||
// console.log('更新选项', options);
|
||||
if (this._options) {
|
||||
this._options = Object.assign(this._options, options);
|
||||
} else {
|
||||
@ -807,13 +806,6 @@ abstract class GraphicSceneBase
|
||||
this.pixi.resizeTo = dom;
|
||||
dom.appendChild(this.pixi.view as unknown as Node);
|
||||
this._viewportResizer = setInterval(() => {
|
||||
// console.log(
|
||||
// 'dom resize ',
|
||||
// dom.style.width,
|
||||
// dom.style.height,
|
||||
// dom.clientWidth,
|
||||
// dom.clientHeight
|
||||
// );
|
||||
this.updateViewport(dom.clientWidth, dom.clientHeight);
|
||||
}, 1000);
|
||||
// 恢复
|
||||
@ -838,7 +830,6 @@ abstract class GraphicSceneBase
|
||||
for (const item of this.graphicTemplateMap) {
|
||||
await item[1].loadAssets();
|
||||
}
|
||||
// console.log('开始加载proto数据', protos);
|
||||
// 加载数据到图形存储
|
||||
protos.forEach((proto) => {
|
||||
const template = this.getGraphicTemplatesByType(proto.graphicType);
|
||||
@ -855,7 +846,6 @@ abstract class GraphicSceneBase
|
||||
.map((g) => g.id)
|
||||
.sort((a, b) => a - b)
|
||||
.pop() ?? 0;
|
||||
// console.log('最大值', max)
|
||||
GraphicIdGenerator.initSerial(max);
|
||||
// 数据加载完成后
|
||||
this.emit('postdataloaded');
|
||||
@ -900,11 +890,9 @@ abstract class GraphicSceneBase
|
||||
}
|
||||
if (graphic.eventMode == 'static' || graphic.eventMode == 'dynamic') {
|
||||
// 添加为可交互
|
||||
// console.log(`type=${graphic.type}的图形添加到交互容器`);
|
||||
this.canvas.addChild(graphic);
|
||||
} else {
|
||||
// 添加到不可交互容器
|
||||
// console.log(`type=${graphic.type}的图形添加到无交互容器`);
|
||||
this.canvas.addNonInteractiveChild(graphic);
|
||||
}
|
||||
graphic.repaint();
|
||||
@ -1253,7 +1241,6 @@ export class GraphicApp extends GraphicSceneBase implements IGraphicApp {
|
||||
|
||||
constructor(options: GraphicAppOptions) {
|
||||
super(options);
|
||||
// console.log('创建图形App')
|
||||
this.opRecord = new OperationRecord();
|
||||
// 绑定键盘监听
|
||||
this.keyboardPlugin = new JlGraphicAppKeyboardPlugin(this);
|
||||
@ -1264,7 +1251,6 @@ export class GraphicApp extends GraphicSceneBase implements IGraphicApp {
|
||||
}
|
||||
|
||||
setOptions(options: GraphicAppOptions) {
|
||||
// console.log('更新选项', options);
|
||||
if (options.maxOperationRecords && options.maxOperationRecords > 0) {
|
||||
this.opRecord.setMaxLen(options.maxOperationRecords);
|
||||
}
|
@ -20,7 +20,6 @@ export class IdGenerator {
|
||||
}
|
||||
|
||||
initSerial(serial: number): void {
|
||||
// console.log(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) {
|
||||
this.undoStack.shift();
|
||||
}
|
||||
// console.log('operation record', op)
|
||||
this.undoStack.push(op);
|
||||
this.redoStack.splice(0, this.redoStack.length);
|
||||
}
|
||||
@ -79,7 +78,6 @@ export class OperationRecord {
|
||||
*/
|
||||
undo() {
|
||||
const op = this.undoStack.pop();
|
||||
// console.log('撤销', op);
|
||||
if (op) {
|
||||
op.undo1();
|
||||
this.redoStack.push(op);
|
||||
@ -90,7 +88,6 @@ export class OperationRecord {
|
||||
*/
|
||||
redo() {
|
||||
const op = this.redoStack.pop();
|
||||
// console.log('重做', op);
|
||||
if (op) {
|
||||
op.redo1();
|
||||
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) {
|
||||
// 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) {
|
||||
this.box.visible = true;
|
||||
this.app.interactionPlugin(ViewportMovePlugin.Name).resume();
|
||||
@ -165,19 +161,11 @@ export class CommonMouseTool extends AppInteractionPlugin {
|
||||
}
|
||||
|
||||
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()) {
|
||||
this.boxSelectDraw(event.start, event.end);
|
||||
}
|
||||
}
|
||||
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) {
|
||||
this.boxSelectDraw(event.start, event.end);
|
||||
this.boxSelectGraphicCheck();
|
||||
@ -232,7 +220,6 @@ export class CommonMouseTool extends AppInteractionPlugin {
|
||||
const graphic = this.leftDownTarget.getGraphic();
|
||||
if (graphic) {
|
||||
const app = this.app;
|
||||
// console.log(this.leftDownTarget.isGraphic());
|
||||
// 图形选中
|
||||
if (!e.ctrlKey && !graphic.selected && graphic.selectable) {
|
||||
app.updateSelected(graphic);
|
@ -403,7 +403,6 @@ export class BezierCurveEditPlugin extends LineEditPlugin {
|
||||
}
|
||||
|
||||
initEditPoints() {
|
||||
// console.log('initEditPoints');
|
||||
const cps = this.graphic.localToCanvasPoints(...this.linePoints);
|
||||
for (let i = 0; i < cps.length; i++) {
|
||||
const p = cps[i];
|
@ -204,7 +204,6 @@ export class GraphicTransformPlugin extends InteractionPluginBase {
|
||||
aps.push(ap);
|
||||
}
|
||||
}
|
||||
// console.log(positions, 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({
|
||||
value: '' + i,
|
||||
onPress: () => {
|
||||
// console.log('修改角度step');
|
||||
this.angleStep = i;
|
||||
},
|
||||
})
|
||||
@ -707,7 +703,6 @@ export class TransformPoints extends Container {
|
||||
// 计算缩放比例,并根据是否保持纵横比两种情况进行缩放处理
|
||||
const sx = originWidth == 0 ? this.originScale.x : width / originWidth;
|
||||
const sy = originHeight == 0 ? this.originScale.y : height / originHeight;
|
||||
// console.log(originWidth, originHeight, width, height, sx, sy);
|
||||
if (this.obj.keepAspectRatio) {
|
||||
let max = Math.max(sx, sy);
|
||||
if (originWidth == 0) {
|
@ -238,7 +238,6 @@ export class DragPlugin extends OtherInteractionPlugin {
|
||||
|
||||
// drag移动处理
|
||||
if (this.target && this.drag && this.start) {
|
||||
// console.log('drag move', e.movement);
|
||||
this.app.emit(
|
||||
'drag_op_move',
|
||||
new AppDragEvent(this.app, 'move', this.target, e, this.start)
|
||||
@ -249,7 +248,6 @@ export class DragPlugin extends OtherInteractionPlugin {
|
||||
|
||||
onPointerUp(e: FederatedPointerEvent) {
|
||||
if (this.target && this.drag && this.start) {
|
||||
// console.log('drag end');
|
||||
this.app.emit(
|
||||
'drag_op_end',
|
||||
new AppDragEvent(this.app, 'end', this.target, e, this.start)
|
@ -18,7 +18,6 @@ export class GlobalKeyboardHelper {
|
||||
if (e.ctrlKey) {
|
||||
if (e.code == 'KeyS') {
|
||||
// 屏蔽全局Ctrl+S保存操作
|
||||
// console.log('屏蔽全局Ctrl+S')
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -81,7 +80,6 @@ export class JlGraphicAppKeyboardPlugin {
|
||||
const onMouseUpdateTarget = (e: MouseEvent) => {
|
||||
const node = e.target as Node;
|
||||
target = node;
|
||||
// console.log('Mousedown Event', node.nodeName, node.nodeType, node.nodeValue)
|
||||
};
|
||||
const keydownHandle = (e: KeyboardEvent) => {
|
||||
// console.debug(e.key, e.code, e.keyCode);
|
||||
@ -147,7 +145,6 @@ export class JlGraphicAppKeyboardPlugin {
|
||||
stack.push(old);
|
||||
}
|
||||
map.set(keyListener.identifier, keyListener);
|
||||
// console.log(this.getAllListenedKeys());
|
||||
}
|
||||
/**
|
||||
* 移除按键监听,若是当前注册的监听,尝试从栈中取出作为按键监听器,若是旧的,则同时移除栈中的监听
|
||||
@ -172,7 +169,6 @@ export class JlGraphicAppKeyboardPlugin {
|
||||
stack.splice(index, 1);
|
||||
}
|
||||
}
|
||||
// console.log(this);
|
||||
}
|
||||
|
||||
getKeyListenerBy(key: string | number): Map<string, KeyListener> | undefined {
|
||||
@ -307,7 +303,6 @@ export class KeyListener {
|
||||
return;
|
||||
}
|
||||
if (this.pressTriggerEveryTime || !this.isPress) {
|
||||
// console.log('Keydown: ', e, this.onPress);
|
||||
this.isPress = true;
|
||||
if (this.onPress) {
|
||||
this.onPress(e, app);
|
||||
@ -338,7 +333,6 @@ export class KeyListener {
|
||||
|
||||
release(e: KeyboardEvent, app: IGraphicApp): void {
|
||||
if (this.isPress) {
|
||||
// console.log('Keyup : ', e.key, e);
|
||||
this.isPress = false;
|
||||
if (this.onRelease) {
|
||||
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