处理图形Assets加载结构
添加风机图形和绘制 初步添加动画功能(不稳定,可能会有不兼容的修改)
This commit is contained in:
parent
fbc3a70cda
commit
f649cb4a3d
@ -5,6 +5,7 @@ package graphicData;
|
|||||||
message RtssGraphicStorage {
|
message RtssGraphicStorage {
|
||||||
Canvas canvas = 1;
|
Canvas canvas = 1;
|
||||||
repeated Link links = 2;
|
repeated Link links = 2;
|
||||||
|
repeated IscsFan iscsFans = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
message Canvas {
|
message Canvas {
|
||||||
@ -61,3 +62,8 @@ message Link {
|
|||||||
string lineColor = 6; // 线色
|
string lineColor = 6; // 线色
|
||||||
repeated Point points = 7; // 点坐标列表
|
repeated Point points = 7; // 点坐标列表
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message IscsFan {
|
||||||
|
CommonInfo common = 1;
|
||||||
|
string code = 2;
|
||||||
|
}
|
||||||
|
87
src/examples/app/graphics/BaseGraphicData.ts
Normal file
87
src/examples/app/graphics/BaseGraphicData.ts
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
import * as pb_1 from 'google-protobuf';
|
||||||
|
import {
|
||||||
|
ChildTransform,
|
||||||
|
GraphicData,
|
||||||
|
GraphicTransform,
|
||||||
|
IChildTransform,
|
||||||
|
IGraphicTransform,
|
||||||
|
} from 'src/jlgraphic';
|
||||||
|
import { toStorageTransform } from '..';
|
||||||
|
import { graphicData } from '../protos/draw_data_storage';
|
||||||
|
|
||||||
|
export interface ICommonInfo {
|
||||||
|
id: string;
|
||||||
|
graphicType: string;
|
||||||
|
transform: IGraphicTransform;
|
||||||
|
childTransforms: IChildTransform[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IProtoGraphicData extends pb_1.Message {
|
||||||
|
common: ICommonInfo;
|
||||||
|
code: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export abstract class BaseGraphicData implements GraphicData {
|
||||||
|
_data: IProtoGraphicData;
|
||||||
|
constructor(data: IProtoGraphicData) {
|
||||||
|
this._data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
getData<D extends IProtoGraphicData>(): D {
|
||||||
|
return this._data as D;
|
||||||
|
}
|
||||||
|
|
||||||
|
get id(): string {
|
||||||
|
return this._data.common.id;
|
||||||
|
}
|
||||||
|
set id(v: string) {
|
||||||
|
this._data.common.id = v;
|
||||||
|
}
|
||||||
|
get graphicType(): string {
|
||||||
|
return this._data.common.graphicType;
|
||||||
|
}
|
||||||
|
set graphicType(v: string) {
|
||||||
|
this._data.common.graphicType = v;
|
||||||
|
}
|
||||||
|
get transform(): GraphicTransform {
|
||||||
|
return GraphicTransform.from(this._data.common.transform);
|
||||||
|
}
|
||||||
|
set transform(v: GraphicTransform) {
|
||||||
|
this._data.common.transform = toStorageTransform(v);
|
||||||
|
}
|
||||||
|
get childTransforms(): ChildTransform[] | undefined {
|
||||||
|
const cts: ChildTransform[] = [];
|
||||||
|
if (this._data.common.childTransforms) {
|
||||||
|
this._data.common.childTransforms.forEach((ct) => {
|
||||||
|
cts.push(ChildTransform.from(ct));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return cts;
|
||||||
|
}
|
||||||
|
set childTransforms(v: ChildTransform[] | undefined) {
|
||||||
|
if (v) {
|
||||||
|
const cts: graphicData.ChildTransform[] = [];
|
||||||
|
v.forEach((ct) =>
|
||||||
|
cts.push(
|
||||||
|
new graphicData.ChildTransform({
|
||||||
|
...ct,
|
||||||
|
transform: toStorageTransform(ct.transform),
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
this._data.common.childTransforms = cts;
|
||||||
|
} else {
|
||||||
|
this._data.common.childTransforms = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
clone(): GraphicData {
|
||||||
|
throw new Error('Method not implemented.');
|
||||||
|
}
|
||||||
|
copyFrom(gd: BaseGraphicData): void {
|
||||||
|
pb_1.Message.copyInto(gd._data, this._data);
|
||||||
|
}
|
||||||
|
eq(other: BaseGraphicData): boolean {
|
||||||
|
return pb_1.Message.equals(this._data, other._data);
|
||||||
|
}
|
||||||
|
}
|
38
src/examples/app/graphics/IscsFanInteraction.ts
Normal file
38
src/examples/app/graphics/IscsFanInteraction.ts
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
import * as pb_1 from 'google-protobuf';
|
||||||
|
import { IIscsFanData } from 'src/graphics/iscs-fan/IscsFan';
|
||||||
|
import { graphicData } from '../protos/draw_data_storage';
|
||||||
|
import { BaseGraphicData } from './BaseGraphicData';
|
||||||
|
|
||||||
|
export class IscsFanData extends BaseGraphicData implements IIscsFanData {
|
||||||
|
constructor(data?: graphicData.IscsFan) {
|
||||||
|
let fan;
|
||||||
|
if (data) {
|
||||||
|
fan = data;
|
||||||
|
} else {
|
||||||
|
fan = new graphicData.IscsFan({
|
||||||
|
common: new graphicData.CommonInfo(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
super(fan);
|
||||||
|
}
|
||||||
|
|
||||||
|
public get data(): graphicData.IscsFan {
|
||||||
|
return this.getData<graphicData.IscsFan>();
|
||||||
|
}
|
||||||
|
|
||||||
|
get code(): string {
|
||||||
|
return this.data.code;
|
||||||
|
}
|
||||||
|
set code(v: string) {
|
||||||
|
this.data.code = v;
|
||||||
|
}
|
||||||
|
clone(): IscsFanData {
|
||||||
|
return new IscsFanData(this.data.cloneMessage());
|
||||||
|
}
|
||||||
|
copyFrom(data: IscsFanData): void {
|
||||||
|
pb_1.Message.copyInto(data.data, this.data);
|
||||||
|
}
|
||||||
|
eq(other: IscsFanData): boolean {
|
||||||
|
return pb_1.Message.equals(this.data, other.data);
|
||||||
|
}
|
||||||
|
}
|
@ -1,21 +1,26 @@
|
|||||||
import * as pb_1 from 'google-protobuf';
|
import * as pb_1 from 'google-protobuf';
|
||||||
import { IPointData } from 'pixi.js';
|
import { IPointData } from 'pixi.js';
|
||||||
import { ILinkData } from 'src/graphics/link/Link';
|
import { ILinkData } from 'src/graphics/link/Link';
|
||||||
import { ChildTransform, GraphicTransform } from 'src/jlgraphic';
|
|
||||||
import { toStorageTransform } from '..';
|
|
||||||
import { graphicData } from '../protos/draw_data_storage';
|
import { graphicData } from '../protos/draw_data_storage';
|
||||||
|
import { BaseGraphicData } from './BaseGraphicData';
|
||||||
|
|
||||||
export class LinkData implements ILinkData {
|
export class LinkData extends BaseGraphicData implements ILinkData {
|
||||||
data: graphicData.Link;
|
|
||||||
constructor(data?: graphicData.Link) {
|
constructor(data?: graphicData.Link) {
|
||||||
if (data) {
|
let link;
|
||||||
this.data = data;
|
if (!data) {
|
||||||
} else {
|
link = new graphicData.Link({
|
||||||
this.data = new graphicData.Link({
|
|
||||||
common: new graphicData.CommonInfo(),
|
common: new graphicData.CommonInfo(),
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
link = data;
|
||||||
}
|
}
|
||||||
|
super(link);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get data(): graphicData.Link {
|
||||||
|
return this.getData<graphicData.Link>();
|
||||||
|
}
|
||||||
|
|
||||||
get code(): string {
|
get code(): string {
|
||||||
return this.data.code;
|
return this.data.code;
|
||||||
}
|
}
|
||||||
@ -63,47 +68,4 @@ export class LinkData implements ILinkData {
|
|||||||
eq(other: LinkData): boolean {
|
eq(other: LinkData): boolean {
|
||||||
return pb_1.Message.equals(this.data, other.data);
|
return pb_1.Message.equals(this.data, other.data);
|
||||||
}
|
}
|
||||||
get id(): string {
|
|
||||||
return this.data.common.id;
|
|
||||||
}
|
|
||||||
set id(v: string) {
|
|
||||||
this.data.common.id = v;
|
|
||||||
}
|
|
||||||
get graphicType(): string {
|
|
||||||
return this.data.common.graphicType;
|
|
||||||
}
|
|
||||||
set graphicType(v: string) {
|
|
||||||
this.data.common.graphicType = v;
|
|
||||||
}
|
|
||||||
get transform(): GraphicTransform {
|
|
||||||
return GraphicTransform.from(this.data.common.transform);
|
|
||||||
}
|
|
||||||
set transform(v: GraphicTransform) {
|
|
||||||
this.data.common.transform = toStorageTransform(v);
|
|
||||||
}
|
|
||||||
get childTransforms(): ChildTransform[] | undefined {
|
|
||||||
const cts: ChildTransform[] = [];
|
|
||||||
if (this.data.common.childTransforms) {
|
|
||||||
this.data.common.childTransforms.forEach((ct) => {
|
|
||||||
cts.push(ChildTransform.from(ct));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return cts;
|
|
||||||
}
|
|
||||||
set childTransforms(v: ChildTransform[] | undefined) {
|
|
||||||
if (v) {
|
|
||||||
const cts: graphicData.ChildTransform[] = [];
|
|
||||||
v.forEach((ct) =>
|
|
||||||
cts.push(
|
|
||||||
new graphicData.ChildTransform({
|
|
||||||
...ct,
|
|
||||||
transform: toStorageTransform(ct.transform),
|
|
||||||
})
|
|
||||||
)
|
|
||||||
);
|
|
||||||
this.data.common.childTransforms = cts;
|
|
||||||
} else {
|
|
||||||
this.data.common.childTransforms = [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,9 @@ import {
|
|||||||
} from 'src/jlgraphic';
|
} from 'src/jlgraphic';
|
||||||
import { LinkData } from './graphics/LinkInteraction';
|
import { LinkData } from './graphics/LinkInteraction';
|
||||||
import { graphicData } from './protos/draw_data_storage';
|
import { graphicData } from './protos/draw_data_storage';
|
||||||
|
import { IscsFanDraw } from 'src/graphics/iscs-fan/IscsFanDrawAssistant';
|
||||||
|
import { IscsFanData } from './graphics/IscsFanInteraction';
|
||||||
|
import { IscsFan } from 'src/graphics/iscs-fan/IscsFan';
|
||||||
|
|
||||||
export function fromStoragePoint(p: graphicData.Point): Point {
|
export function fromStoragePoint(p: graphicData.Point): Point {
|
||||||
return new Point(p.x, p.y);
|
return new Point(p.x, p.y);
|
||||||
@ -46,13 +49,15 @@ export function toStorageTransform(
|
|||||||
export function initDrawApp(app: JlDrawApp) {
|
export function initDrawApp(app: JlDrawApp) {
|
||||||
app.setOptions({
|
app.setOptions({
|
||||||
drawAssistants: [
|
drawAssistants: [
|
||||||
new LinkDraw(app, {
|
new LinkDraw(app, () => {
|
||||||
newData: () => {
|
return new LinkData();
|
||||||
return new LinkData();
|
}),
|
||||||
},
|
new IscsFanDraw(app, () => {
|
||||||
|
return new IscsFanData();
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
app.addKeyboardListener(
|
app.addKeyboardListener(
|
||||||
new KeyListener({
|
new KeyListener({
|
||||||
value: 'KeyL',
|
value: 'KeyL',
|
||||||
@ -61,6 +66,25 @@ export function initDrawApp(app: JlDrawApp) {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
app.addKeyboardListener(
|
||||||
|
new KeyListener({
|
||||||
|
value: 'KeyF',
|
||||||
|
onPress: () => {
|
||||||
|
app.interactionPlugin(IscsFan.Type).resume();
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
app.addKeyboardListener(
|
||||||
|
new KeyListener({
|
||||||
|
value: 'KeyR',
|
||||||
|
onPress: () => {
|
||||||
|
app.queryStore.queryByType<IscsFan>(IscsFan.Type).forEach((fan) => {
|
||||||
|
fan._run = !fan._run;
|
||||||
|
fan.repaint();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
app.addKeyboardListener(
|
app.addKeyboardListener(
|
||||||
new KeyListener({
|
new KeyListener({
|
||||||
value: 'KeyS',
|
value: 'KeyS',
|
||||||
@ -86,6 +110,9 @@ export function saveDrawDatas(app: JlDrawApp) {
|
|||||||
if (Link.Type === g.type) {
|
if (Link.Type === g.type) {
|
||||||
const linkData = (g as Link).saveData();
|
const linkData = (g as Link).saveData();
|
||||||
storage.links.push((linkData as LinkData).data);
|
storage.links.push((linkData as LinkData).data);
|
||||||
|
} else if (IscsFan.Type === g.type) {
|
||||||
|
const IscsFanData = (g as IscsFan).saveData();
|
||||||
|
storage.iscsFans.push((IscsFanData as IscsFanData).data);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const base64 = fromUint8Array(storage.serialize());
|
const base64 = fromUint8Array(storage.serialize());
|
||||||
@ -96,6 +123,7 @@ export function saveDrawDatas(app: JlDrawApp) {
|
|||||||
export function loadDrawDatas(app: GraphicApp) {
|
export function loadDrawDatas(app: GraphicApp) {
|
||||||
// localStorage.removeItem(StorageKey);
|
// localStorage.removeItem(StorageKey);
|
||||||
const base64 = localStorage.getItem(StorageKey);
|
const base64 = localStorage.getItem(StorageKey);
|
||||||
|
// console.log('加载数据', base64);
|
||||||
if (base64) {
|
if (base64) {
|
||||||
const storage = graphicData.RtssGraphicStorage.deserialize(
|
const storage = graphicData.RtssGraphicStorage.deserialize(
|
||||||
toUint8Array(base64)
|
toUint8Array(base64)
|
||||||
@ -106,6 +134,9 @@ export function loadDrawDatas(app: GraphicApp) {
|
|||||||
storage.links.forEach((link) => {
|
storage.links.forEach((link) => {
|
||||||
datas.push(new LinkData(link));
|
datas.push(new LinkData(link));
|
||||||
});
|
});
|
||||||
|
storage.iscsFans.forEach((fan) => {
|
||||||
|
datas.push(new IscsFanData(fan));
|
||||||
|
});
|
||||||
app.loadGraphic(datas);
|
app.loadGraphic(datas);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
91
src/graphics/iscs-fan/IscsFan.ts
Normal file
91
src/graphics/iscs-fan/IscsFan.ts
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
import {
|
||||||
|
GraphicAnimation,
|
||||||
|
GraphicData,
|
||||||
|
JlGraphic,
|
||||||
|
JlGraphicTemplate,
|
||||||
|
} from 'src/jlgraphic';
|
||||||
|
import fanBorder from './assets/fan-border.png';
|
||||||
|
import fanBlue from './assets/fan-blue.png';
|
||||||
|
import fanGray from './assets/fan-gray.png';
|
||||||
|
import fanGreen from './assets/fan-green.png';
|
||||||
|
import fanRed from './assets/fan-red.png';
|
||||||
|
import fanYellow from './assets/fan-yellow.png';
|
||||||
|
import { Assets, Sprite, 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 class IscsFan extends JlGraphic {
|
||||||
|
static Type = 'IscsFan';
|
||||||
|
_border: Sprite;
|
||||||
|
_fan: Sprite;
|
||||||
|
fanTextures: FanTextures;
|
||||||
|
_run = false;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
doRepaint(): void {
|
||||||
|
if (this._run) {
|
||||||
|
this._fan.texture = this.fanTextures.green;
|
||||||
|
// 动画
|
||||||
|
this.addAnimation(
|
||||||
|
GraphicAnimation.init({
|
||||||
|
name: 'fan_run',
|
||||||
|
run: (dt: number) => {
|
||||||
|
this._fan.angle = (this._fan.angle + dt * 3) % 360;
|
||||||
|
},
|
||||||
|
}).resume()
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
this.removeAnimation('fan_run');
|
||||||
|
this._fan.rotation = 0;
|
||||||
|
this._fan.texture = this.fanTextures.gray;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class IscsFanTemplate extends JlGraphicTemplate<IscsFan> {
|
||||||
|
fanTextures?: FanTextures;
|
||||||
|
constructor() {
|
||||||
|
super(IscsFan.Type);
|
||||||
|
}
|
||||||
|
new(): IscsFan {
|
||||||
|
if (this.fanTextures) {
|
||||||
|
return new IscsFan(this.fanTextures);
|
||||||
|
}
|
||||||
|
throw new Error('资源未加载/加载失败');
|
||||||
|
}
|
||||||
|
async loadAssets(): Promise<FanTextures> {
|
||||||
|
Assets.addBundle('iscsFan', {
|
||||||
|
border: fanBorder,
|
||||||
|
blue: fanBlue,
|
||||||
|
gray: fanGray,
|
||||||
|
green: fanGreen,
|
||||||
|
red: fanRed,
|
||||||
|
yellow: fanYellow,
|
||||||
|
});
|
||||||
|
this.fanTextures = await Assets.loadBundle('iscsFan');
|
||||||
|
return this.fanTextures as FanTextures;
|
||||||
|
}
|
||||||
|
}
|
55
src/graphics/iscs-fan/IscsFanDrawAssistant.ts
Normal file
55
src/graphics/iscs-fan/IscsFanDrawAssistant.ts
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
import { FederatedMouseEvent, Point } from 'pixi.js';
|
||||||
|
import {
|
||||||
|
GraphicDrawAssistant,
|
||||||
|
GraphicTransform,
|
||||||
|
JlDrawApp,
|
||||||
|
} from 'src/jlgraphic';
|
||||||
|
import { IIscsFanData, IscsFan, IscsFanTemplate } from './IscsFan';
|
||||||
|
|
||||||
|
export class IscsFanDraw extends GraphicDrawAssistant<
|
||||||
|
IscsFanTemplate,
|
||||||
|
IIscsFanData
|
||||||
|
> {
|
||||||
|
_iscsFan: IscsFan | null = null;
|
||||||
|
|
||||||
|
constructor(app: JlDrawApp, createData: () => IIscsFanData) {
|
||||||
|
const template = new IscsFanTemplate();
|
||||||
|
super(app, template, createData, IscsFan.Type, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
onRightUp(): void {
|
||||||
|
this.finish();
|
||||||
|
}
|
||||||
|
prepareData(data: IIscsFanData): boolean {
|
||||||
|
// 变换设置必须新建变换赋值,不能直接修改变换数据
|
||||||
|
const transfrom = GraphicTransform.default();
|
||||||
|
transfrom.position = this.iscsFan.position.clone();
|
||||||
|
data.transform = transfrom;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
onEsc(): void {
|
||||||
|
this.finish();
|
||||||
|
}
|
||||||
|
}
|
BIN
src/graphics/iscs-fan/assets/fan-blue.png
Normal file
BIN
src/graphics/iscs-fan/assets/fan-blue.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.9 KiB |
BIN
src/graphics/iscs-fan/assets/fan-border.png
Normal file
BIN
src/graphics/iscs-fan/assets/fan-border.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.3 KiB |
BIN
src/graphics/iscs-fan/assets/fan-gray.png
Normal file
BIN
src/graphics/iscs-fan/assets/fan-gray.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.7 KiB |
BIN
src/graphics/iscs-fan/assets/fan-green.png
Normal file
BIN
src/graphics/iscs-fan/assets/fan-green.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.2 KiB |
BIN
src/graphics/iscs-fan/assets/fan-red.png
Normal file
BIN
src/graphics/iscs-fan/assets/fan-red.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.9 KiB |
BIN
src/graphics/iscs-fan/assets/fan-yellow.png
Normal file
BIN
src/graphics/iscs-fan/assets/fan-yellow.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.1 KiB |
@ -34,8 +34,7 @@ export interface ILinkDrawOptions {
|
|||||||
newData: () => ILinkData;
|
newData: () => ILinkData;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class LinkDraw extends GraphicDrawAssistant<LinkTemplate> {
|
export class LinkDraw extends GraphicDrawAssistant<LinkTemplate, ILinkData> {
|
||||||
_options: ILinkDrawOptions;
|
|
||||||
points: Point[] = [];
|
points: Point[] = [];
|
||||||
graphic: Graphics = new Graphics();
|
graphic: Graphics = new Graphics();
|
||||||
|
|
||||||
@ -60,18 +59,14 @@ export class LinkDraw extends GraphicDrawAssistant<LinkTemplate> {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
constructor(app: JlDrawApp, options: ILinkDrawOptions) {
|
constructor(app: JlDrawApp, createData: () => ILinkData) {
|
||||||
super(app, new LinkTemplate(), Link.Type, '轨道Link');
|
super(app, new LinkTemplate(), createData, Link.Type, '轨道Link');
|
||||||
this.container.addChild(this.graphic);
|
this.container.addChild(this.graphic);
|
||||||
this._options = options;
|
|
||||||
this.graphicTemplate.curve = true;
|
this.graphicTemplate.curve = true;
|
||||||
|
|
||||||
new LinkPointsEditPlugin(app);
|
new LinkPointsEditPlugin(app);
|
||||||
}
|
}
|
||||||
|
|
||||||
newLinkData(): ILinkData {
|
|
||||||
return this._options.newData();
|
|
||||||
}
|
|
||||||
bind(): void {
|
bind(): void {
|
||||||
super.bind();
|
super.bind();
|
||||||
this.app.addKeyboardListener(this.keyqListener, this.keyzListener);
|
this.app.addKeyboardListener(this.keyqListener, this.keyzListener);
|
||||||
@ -158,28 +153,25 @@ export class LinkDraw extends GraphicDrawAssistant<LinkTemplate> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
prepareData(): ILinkData | null {
|
prepareData(data: ILinkData): boolean {
|
||||||
const template = this.graphicTemplate;
|
const template = this.graphicTemplate;
|
||||||
if (
|
if (
|
||||||
(!template.curve && this.points.length < 2) ||
|
(!template.curve && this.points.length < 2) ||
|
||||||
(template.curve && this.points.length < 4)
|
(template.curve && this.points.length < 4)
|
||||||
) {
|
) {
|
||||||
console.log('Link绘制因点不够取消绘制');
|
console.log('Link绘制因点不够取消绘制');
|
||||||
return null;
|
return false;
|
||||||
}
|
}
|
||||||
if (template.curve) {
|
if (template.curve) {
|
||||||
this.points.pop();
|
this.points.pop();
|
||||||
}
|
}
|
||||||
const data = this.newLinkData();
|
|
||||||
data.id = this.nextId();
|
|
||||||
data.graphicType = Link.Type;
|
|
||||||
data.curve = template.curve;
|
data.curve = template.curve;
|
||||||
data.segmentsCount = template.segmentsCount;
|
data.segmentsCount = template.segmentsCount;
|
||||||
data.points = this.points;
|
data.points = this.points;
|
||||||
data.lineWidth = template.lineWidth;
|
data.lineWidth = template.lineWidth;
|
||||||
data.lineColor = template.lineColor;
|
data.lineColor = template.lineColor;
|
||||||
data.segmentsCount = template.segmentsCount;
|
data.segmentsCount = template.segmentsCount;
|
||||||
return data;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
0
src/graphics/signal/Signal.ts
Normal file
0
src/graphics/signal/Signal.ts
Normal file
@ -10,7 +10,7 @@ import {
|
|||||||
Point,
|
Point,
|
||||||
} from 'pixi.js';
|
} from 'pixi.js';
|
||||||
import { GraphicIdGenerator } from '../core/IdGenerator';
|
import { GraphicIdGenerator } from '../core/IdGenerator';
|
||||||
import { JlGraphic, GraphicData, GraphicTemplate } from '../core/JlGraphic';
|
import { GraphicData, GraphicTemplate, JlGraphic } from '../core/JlGraphic';
|
||||||
import { BoundsGraphic, TransformPoints } from '../graphic';
|
import { BoundsGraphic, TransformPoints } from '../graphic';
|
||||||
import { JlOperation } from '../operation/JlOperation';
|
import { JlOperation } from '../operation/JlOperation';
|
||||||
import {
|
import {
|
||||||
@ -35,33 +35,40 @@ import {
|
|||||||
* 图形绘制助手
|
* 图形绘制助手
|
||||||
*/
|
*/
|
||||||
export abstract class GraphicDrawAssistant<
|
export abstract class GraphicDrawAssistant<
|
||||||
GT extends GraphicTemplate
|
GT extends GraphicTemplate,
|
||||||
|
GD extends GraphicData
|
||||||
> extends AppInteractionPlugin {
|
> extends AppInteractionPlugin {
|
||||||
_isDrawAssistant = true;
|
|
||||||
app: JlDrawApp;
|
app: JlDrawApp;
|
||||||
type: string; // 图形对象类型
|
type: string; // 图形对象类型
|
||||||
description?: string; // 描述
|
description?: string; // 描述
|
||||||
icon: string; // 界面显示的图标
|
icon: string; // 界面显示的图标
|
||||||
container: Container = new Container();
|
container: Container = new Container();
|
||||||
graphicTemplate: GT;
|
graphicTemplate: GT;
|
||||||
|
createGraphicData: () => GD;
|
||||||
|
|
||||||
escListener: KeyListener = new KeyListener({
|
escListener: KeyListener = new KeyListener({
|
||||||
value: 'Escape',
|
value: 'Escape',
|
||||||
onPress: () => {
|
onRelease: () => {
|
||||||
this.createAndStore(true);
|
this.onEsc();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
onEsc() {
|
||||||
|
this.createAndStore(true);
|
||||||
|
}
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
graphicApp: JlDrawApp,
|
graphicApp: JlDrawApp,
|
||||||
graphicTemplate: GT,
|
graphicTemplate: GT,
|
||||||
|
createGraphicData: () => GD,
|
||||||
icon: string,
|
icon: string,
|
||||||
description?: string
|
description?: string
|
||||||
) {
|
) {
|
||||||
super(graphicTemplate.type, graphicApp);
|
super(graphicTemplate.type, graphicApp);
|
||||||
this.app = graphicApp;
|
this.app = graphicApp;
|
||||||
this.graphicTemplate = graphicTemplate;
|
|
||||||
this.type = graphicTemplate.type;
|
this.type = graphicTemplate.type;
|
||||||
|
this.graphicTemplate = graphicTemplate;
|
||||||
|
this.createGraphicData = createGraphicData;
|
||||||
this.icon = icon;
|
this.icon = icon;
|
||||||
this.description = description;
|
this.description = description;
|
||||||
this.app.registerGraphicTemplates(this.graphicTemplate);
|
this.app.registerGraphicTemplates(this.graphicTemplate);
|
||||||
@ -131,7 +138,7 @@ export abstract class GraphicDrawAssistant<
|
|||||||
*/
|
*/
|
||||||
abstract redraw(cp: Point): void;
|
abstract redraw(cp: Point): void;
|
||||||
|
|
||||||
abstract prepareData(): GraphicData | null;
|
abstract prepareData(data: GD): boolean;
|
||||||
|
|
||||||
toCanvasCoordinates(p: Point): Point {
|
toCanvasCoordinates(p: Point): Point {
|
||||||
return this.app.toCanvasCoordinates(p);
|
return this.app.toCanvasCoordinates(p);
|
||||||
@ -148,8 +155,10 @@ export abstract class GraphicDrawAssistant<
|
|||||||
* 创建并添加到图形App
|
* 创建并添加到图形App
|
||||||
*/
|
*/
|
||||||
createAndStore(finish: boolean): JlGraphic | null {
|
createAndStore(finish: boolean): JlGraphic | null {
|
||||||
const data = this.prepareData();
|
const data = this.createGraphicData();
|
||||||
if (!data) {
|
data.id = this.nextId();
|
||||||
|
data.graphicType = this.graphicTemplate.type;
|
||||||
|
if (!this.prepareData(data)) {
|
||||||
if (finish) {
|
if (finish) {
|
||||||
this.finish();
|
this.finish();
|
||||||
}
|
}
|
||||||
@ -158,7 +167,6 @@ export abstract class GraphicDrawAssistant<
|
|||||||
const template = this.graphicTemplate;
|
const template = this.graphicTemplate;
|
||||||
const g = template.new();
|
const g = template.new();
|
||||||
g.loadData(data);
|
g.loadData(data);
|
||||||
g.id = this.nextId();
|
|
||||||
this.storeGraphic(g);
|
this.storeGraphic(g);
|
||||||
if (finish) {
|
if (finish) {
|
||||||
this.finish(g);
|
this.finish(g);
|
||||||
@ -183,11 +191,13 @@ export enum DrawAppEvent {
|
|||||||
propertiesupdate = 'propertiesupdate', // 图形对象数据变更
|
propertiesupdate = 'propertiesupdate', // 图形对象数据变更
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type DrawAssistant = GraphicDrawAssistant<GraphicTemplate, GraphicData>;
|
||||||
|
|
||||||
export interface IDrawAppOptions {
|
export interface IDrawAppOptions {
|
||||||
/**
|
/**
|
||||||
* 绘制辅助交互插件
|
* 绘制辅助交互插件
|
||||||
*/
|
*/
|
||||||
drawAssistants: GraphicDrawAssistant<GraphicTemplate>[];
|
drawAssistants: DrawAssistant[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export type DrawAppOptions = GraphicAppOptions & IDrawAppOptions;
|
export type DrawAppOptions = GraphicAppOptions & IDrawAppOptions;
|
||||||
@ -212,7 +222,7 @@ export class JlDrawApp extends GraphicApp {
|
|||||||
fontName: 'coordinates',
|
fontName: 'coordinates',
|
||||||
});
|
});
|
||||||
|
|
||||||
drawAssistants: GraphicDrawAssistant<GraphicTemplate>[] = [];
|
drawAssistants: DrawAssistant[] = [];
|
||||||
|
|
||||||
selectedData: GraphicData | ICanvasProperties | null;
|
selectedData: GraphicData | ICanvasProperties | null;
|
||||||
|
|
||||||
@ -244,14 +254,14 @@ export class JlDrawApp extends GraphicApp {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getDrawAssistant(graphicType: string): GraphicDrawAssistant<GraphicTemplate> {
|
getDrawAssistant<DA extends DrawAssistant>(graphicType: string): DA {
|
||||||
const sda = this.drawAssistants
|
const sda = this.drawAssistants
|
||||||
.filter((da) => da.type === graphicType)
|
.filter((da) => da.type === graphicType)
|
||||||
.pop();
|
.pop();
|
||||||
if (!sda) {
|
if (!sda) {
|
||||||
throw new Error(`未找到图形绘制助手: ${graphicType}`);
|
throw new Error(`未找到图形绘制助手: ${graphicType}`);
|
||||||
}
|
}
|
||||||
return sda;
|
return sda as DA;
|
||||||
}
|
}
|
||||||
|
|
||||||
private appDragRecord() {
|
private appDragRecord() {
|
||||||
|
@ -432,6 +432,16 @@ export class GraphicApp extends EventEmitter<GraphicAppEvents> {
|
|||||||
tool.resume();
|
tool.resume();
|
||||||
// 视口移动插件
|
// 视口移动插件
|
||||||
ViewportMovePlugin.new(this);
|
ViewportMovePlugin.new(this);
|
||||||
|
|
||||||
|
this.app.ticker.add((dt: number) => {
|
||||||
|
this.queryStore.getAllGraphics().forEach((g) => {
|
||||||
|
g.animationMap.forEach((animation) => {
|
||||||
|
if (animation.running) {
|
||||||
|
animation.run(dt);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
setOptions(options: GraphicAppOptions) {
|
setOptions(options: GraphicAppOptions) {
|
||||||
@ -458,8 +468,6 @@ export class GraphicApp extends EventEmitter<GraphicAppEvents> {
|
|||||||
registerGraphicTemplates(...graphicTemplates: GraphicTemplate[]) {
|
registerGraphicTemplates(...graphicTemplates: GraphicTemplate[]) {
|
||||||
graphicTemplates.forEach((graphicTemplate) => {
|
graphicTemplates.forEach((graphicTemplate) => {
|
||||||
this.graphicTemplateMap.set(graphicTemplate.type, graphicTemplate);
|
this.graphicTemplateMap.set(graphicTemplate.type, graphicTemplate);
|
||||||
// 加载资源
|
|
||||||
graphicTemplate.loadAsserts();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -597,8 +605,11 @@ export class GraphicApp extends EventEmitter<GraphicAppEvents> {
|
|||||||
* @param protos
|
* @param protos
|
||||||
* @param options 添加到可交互/不可交互容器选项配置
|
* @param options 添加到可交互/不可交互容器选项配置
|
||||||
*/
|
*/
|
||||||
loadGraphic(protos: GraphicData[]) {
|
async loadGraphic(protos: GraphicData[]) {
|
||||||
// console.log('开始加载proto数据', protos);
|
for (const item of this.graphicTemplateMap) {
|
||||||
|
await item[1].loadAssets();
|
||||||
|
}
|
||||||
|
console.log('开始加载proto数据', protos);
|
||||||
// 加载数据到图形存储
|
// 加载数据到图形存储
|
||||||
protos.forEach((proto) => {
|
protos.forEach((proto) => {
|
||||||
const template = this.getGraphicTemplatesByType(proto.graphicType);
|
const template = this.getGraphicTemplatesByType(proto.graphicType);
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||||
/* eslint-disable @typescript-eslint/no-empty-function */
|
/* eslint-disable @typescript-eslint/no-empty-function */
|
||||||
import { Viewport } from 'pixi-viewport';
|
import { Viewport } from 'pixi-viewport';
|
||||||
@ -451,9 +452,9 @@ export interface GraphicData {
|
|||||||
copyFrom(data: GraphicData): void;
|
copyFrom(data: GraphicData): void;
|
||||||
/**
|
/**
|
||||||
* 是否相等
|
* 是否相等
|
||||||
* @param data
|
* @param other
|
||||||
*/
|
*/
|
||||||
eq(data: GraphicData): boolean;
|
eq(other: GraphicData): boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -478,6 +479,63 @@ export interface GraphicState {
|
|||||||
eq(data: GraphicState): boolean;
|
eq(data: GraphicState): boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface GraphicAnimationOptions {
|
||||||
|
name: string;
|
||||||
|
/**
|
||||||
|
* 位移路径
|
||||||
|
*/
|
||||||
|
path?: IPointData[];
|
||||||
|
/**
|
||||||
|
* 是否循环运动(运动到终点后重新从开始运动),与moveToAndFro互斥
|
||||||
|
*/
|
||||||
|
cycleMove?: boolean;
|
||||||
|
/**
|
||||||
|
* 是否往复运动(运动到终点后从终点往回运动),与cycleMove互斥
|
||||||
|
*/
|
||||||
|
moveToAndFro?: boolean;
|
||||||
|
|
||||||
|
run?: (dt: number) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class GraphicAnimation {
|
||||||
|
options: GraphicAnimationOptions;
|
||||||
|
_running: boolean;
|
||||||
|
_finish: boolean;
|
||||||
|
constructor(options: GraphicAnimationOptions) {
|
||||||
|
this.options = options;
|
||||||
|
this._running = false;
|
||||||
|
this._finish = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static init(options: GraphicAnimationOptions) {
|
||||||
|
return new GraphicAnimation(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
pause(): GraphicAnimation {
|
||||||
|
this._running = false;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
resume(): GraphicAnimation {
|
||||||
|
this._running = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get name(): string {
|
||||||
|
return this.options.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get running(): boolean {
|
||||||
|
return this._running;
|
||||||
|
}
|
||||||
|
|
||||||
|
run(dt: number): GraphicAnimation {
|
||||||
|
if (this.options.run) {
|
||||||
|
this.options.run(dt);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 图形对象基类
|
* 图形对象基类
|
||||||
*/
|
*/
|
||||||
@ -488,6 +546,7 @@ export abstract class JlGraphic extends Container {
|
|||||||
private _code = ''; // 业务编号/名称,用于标识图形对象,具有业务意义
|
private _code = ''; // 业务编号/名称,用于标识图形对象,具有业务意义
|
||||||
_datas?: GraphicData; // 图形数据
|
_datas?: GraphicData; // 图形数据
|
||||||
_states?: GraphicState; // 图形状态数据
|
_states?: GraphicState; // 图形状态数据
|
||||||
|
animationMap: Map<string, GraphicAnimation> = new Map();
|
||||||
private _relationManage?: RelationManage; // 图形关系管理
|
private _relationManage?: RelationManage; // 图形关系管理
|
||||||
private _queryStore?: GraphicQueryStore; // 图形对象查询仓库
|
private _queryStore?: GraphicQueryStore; // 图形对象查询仓库
|
||||||
|
|
||||||
@ -498,6 +557,13 @@ export abstract class JlGraphic extends Container {
|
|||||||
this.filters;
|
this.filters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addAnimation(animation: GraphicAnimation): void {
|
||||||
|
this.animationMap.set(animation.name, animation);
|
||||||
|
}
|
||||||
|
removeAnimation(name: string): void {
|
||||||
|
this.animationMap.delete(name);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新选中状态
|
* 更新选中状态
|
||||||
* @param selected
|
* @param selected
|
||||||
@ -803,6 +869,7 @@ export abstract class JlGraphic extends Container {
|
|||||||
* 处理重绘逻辑
|
* 处理重绘逻辑
|
||||||
*/
|
*/
|
||||||
abstract doRepaint(): void;
|
abstract doRepaint(): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理删除逻辑
|
* 处理删除逻辑
|
||||||
*/
|
*/
|
||||||
@ -838,7 +905,7 @@ export abstract class JlGraphicTemplate<G extends JlGraphic> {
|
|||||||
/**
|
/**
|
||||||
* 加载图形对象需要用到的资源
|
* 加载图形对象需要用到的资源
|
||||||
*/
|
*/
|
||||||
loadAsserts(): void {}
|
async loadAssets(): Promise<any> {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 克隆图形对象
|
* 克隆图形对象
|
||||||
|
@ -153,6 +153,7 @@ export class JlGraphicAppKeyboardPlugin {
|
|||||||
* @param keyListener
|
* @param keyListener
|
||||||
*/
|
*/
|
||||||
removeKeyListener(keyListener: KeyListener) {
|
removeKeyListener(keyListener: KeyListener) {
|
||||||
|
keyListener.onRemove();
|
||||||
const map = this.getOrInit(keyListener.value);
|
const map = this.getOrInit(keyListener.value);
|
||||||
const old = map.get(keyListener.identifier);
|
const old = map.get(keyListener.identifier);
|
||||||
map.delete(keyListener.identifier);
|
map.delete(keyListener.identifier);
|
||||||
@ -343,4 +344,8 @@ export class KeyListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
onRemove(): void {
|
||||||
|
// 重置按下状态
|
||||||
|
this.isPress = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
/**
|
|
||||||
* 判定是否代理对象
|
|
||||||
* @param obj
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
export function isProxy(obj: any): boolean {
|
|
||||||
return !!(obj && obj['__Proxy']);
|
|
||||||
}
|
|
@ -2,7 +2,6 @@ import { Point, Rectangle } from 'pixi.js';
|
|||||||
|
|
||||||
export * from './GraphicUtils';
|
export * from './GraphicUtils';
|
||||||
export * from './IntersectUtils';
|
export * from './IntersectUtils';
|
||||||
export * from './ObjectUtils';
|
|
||||||
|
|
||||||
export const UP: Point = new Point(0, -1);
|
export const UP: Point = new Point(0, -1);
|
||||||
export const DOWN: Point = new Point(0, 1);
|
export const DOWN: Point = new Point(0, 1);
|
||||||
|
Loading…
Reference in New Issue
Block a user