From 618752e037e84e24045b46feef15dee12f872968 Mon Sep 17 00:00:00 2001 From: joylink_zhaoerwei Date: Tue, 30 May 2023 18:06:52 +0800 Subject: [PATCH 01/44] =?UTF-8?q?=E7=AB=99=E5=8F=B0=E8=AF=A6=E7=BB=86?= =?UTF-8?q?=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/graphics/platform/Platform.ts | 109 ++++++++++++++++-- .../platform/PlatformDrawAssistant.ts | 3 +- 2 files changed, 99 insertions(+), 13 deletions(-) diff --git a/src/graphics/platform/Platform.ts b/src/graphics/platform/Platform.ts index 3f74ab5..cd6cd3d 100644 --- a/src/graphics/platform/Platform.ts +++ b/src/graphics/platform/Platform.ts @@ -3,6 +3,7 @@ import { GraphicData, JlGraphic, JlGraphicTemplate, + VectorText, getRectangleCenter, } from 'src/jlgraphic'; @@ -28,43 +29,94 @@ export interface IPlatformData extends GraphicData { 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; + besideGraphic: Graphics; + codeGraph: VectorText = new VectorText(''); //站台旁数字、字符 constructor() { super(Platform.Type); this.platformGraphic = new Graphics(); this.doorGraphic = new Graphics(); + this.besideGraphic = new Graphics(); this.addChild(this.platformGraphic); this.addChild(this.doorGraphic); + this.addChild(this.besideGraphic); + this.addChild(this.codeGraph); + this.codeGraph.setVectorFontSize(platformConsts.besideFontSize); } get datas(): IPlatformData { return this.getDatas(); } doRepaint(): void { + const width = this.datas.width; + const height = this.datas.height; //屏蔽门 const doorGraphic = this.doorGraphic; doorGraphic.clear(); if (this.datas.hasdoor) { - doorGraphic.clear(); doorGraphic.lineStyle( this.datas.lineWidth, new Color(this.datas.lineColorDoor) ); - const width = this.datas.width; - const height = this.datas.height; doorGraphic.moveTo( -width / 2 - this.datas.lineWidth / 2, -height / 2 - 10 ); - doorGraphic.lineTo( - width / 2 + this.datas.lineWidth / 2, - -height / 2 - 10 - ); + //屏蔽门打开 + if (this.datas.hasdoor) { + doorGraphic.lineTo( + -platformConsts.doorOpenSpacing, + -height / 2 - platformConsts.doorPlatformSpacing + ); + doorGraphic.moveTo( + platformConsts.doorOpenSpacing, + -height / 2 - platformConsts.doorPlatformSpacing + ); + doorGraphic.lineTo( + width / 2 + this.datas.lineWidth / 2, + -height / 2 - platformConsts.doorPlatformSpacing + ); + } else { + doorGraphic.lineTo( + width / 2 + this.datas.lineWidth / 2, + -height / 2 - platformConsts.doorPlatformSpacing + ); + } } + /* doorGraphic.position.set( + 0, + height + platformConsts.doorPlatformSpacing * 2 + ); */ + //站台 const platformGraphic = this.platformGraphic; platformGraphic.clear(); platformGraphic.lineStyle( @@ -77,6 +129,39 @@ export class Platform extends JlGraphic { const rect = new Rectangle(0, 0, this.datas.width, this.datas.height); platformGraphic.pivot = getRectangleCenter(rect); this.position.set(this.datas.point.x, this.datas.point.y); + //站台旁菱形图标 + const besideGraphic = this.besideGraphic; + besideGraphic.clear(); + if (this.datas.hasdoor) { + 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; } } @@ -89,12 +174,12 @@ export class PlatformTemplate extends JlGraphicTemplate { height: number; constructor() { super(Platform.Type); - this.lineWidth = 2; - this.lineColor = '#000000'; - this.lineColorDoor = '0x008000'; + this.lineWidth = platformConsts.lineWidth; + this.lineColor = PlatformColorEnum.yellow; + this.lineColorDoor = PlatformColorEnum.doorBlue; this.hasdoor = true; - this.width = 100; - this.height = 30; + this.width = platformConsts.width; + this.height = platformConsts.height; } new(): Platform { return new Platform(); diff --git a/src/graphics/platform/PlatformDrawAssistant.ts b/src/graphics/platform/PlatformDrawAssistant.ts index 634dead..e6b9188 100644 --- a/src/graphics/platform/PlatformDrawAssistant.ts +++ b/src/graphics/platform/PlatformDrawAssistant.ts @@ -14,7 +14,7 @@ import { import { IPlatformData, Platform, PlatformTemplate } from './Platform'; -export interface ILinkDrawOptions { +export interface IPlatformDrawOptions { newData: () => IPlatformData; } @@ -85,6 +85,7 @@ export class PlatformDraw extends GraphicDrawAssistant< 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); } //站台 From bc443be9a754d9a7277caeebf5eced341b0d2607 Mon Sep 17 00:00:00 2001 From: joylink_zhaoerwei Date: Wed, 31 May 2023 15:47:24 +0800 Subject: [PATCH 02/44] =?UTF-8?q?=E7=AB=99=E5=8F=B0=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../draw-app/properties/PlatformProperty.vue | 59 +++++--- .../protos/draw_data_storage.proto | 15 +- .../app/graphics/PlatformInteraction.ts | 6 + src/examples/app/protos/draw_data_storage.ts | 133 +++++++++++++----- src/graphics/platform/Platform.ts | 118 +++++++++------- .../platform/PlatformDrawAssistant.ts | 1 + 6 files changed, 216 insertions(+), 116 deletions(-) diff --git a/src/components/draw-app/properties/PlatformProperty.vue b/src/components/draw-app/properties/PlatformProperty.vue index 8f60b52..06c5498 100644 --- a/src/components/draw-app/properties/PlatformProperty.vue +++ b/src/components/draw-app/properties/PlatformProperty.vue @@ -1,19 +1,18 @@ - + @@ -49,37 +55,44 @@ import { PlatformData } from 'src/examples/app/graphics/PlatformInteraction'; import { Platform } from 'src/graphics/platform/Platform'; import { useDrawStore } from 'src/stores/draw-store'; -import { onMounted, reactive, watch } from 'vue'; +import { onMounted, reactive, ref, watch } from 'vue'; const drawStore = useDrawStore(); -const stationModel = reactive(new PlatformData()); -const options = [true, false]; +const platformModel = reactive(new PlatformData()); +const hasDoor = ref('是'); +const optionsDoor = ['是', '否']; +const trainDirection = ref('向左'); +const optionsDirection = ['向左', '向右']; +enum showSelect { + 是 = 'true', + 否 = 'false', + 向左 = 'left', + 向右 = 'right', +} drawStore.$subscribe; watch( () => drawStore.selectedGraphic, (val) => { if (val && val.type == Platform.Type) { - // console.log('station变更'); - stationModel.copyFrom(val.saveData() as PlatformData); + platformModel.copyFrom(val.saveData() as PlatformData); } } ); onMounted(() => { - //console.log('station 属性表单 mounted'); - const station = drawStore.selectedGraphic as Platform; - - if (station) { - stationModel.copyFrom(station.saveData()); + const platform = drawStore.selectedGraphic as Platform; + if (platform) { + platformModel.copyFrom(platform.saveData()); } }); function onUpdate() { - //console.log(stationModel, 'station 属性更新'); - const station = drawStore.selectedGraphic as Platform; - if (station) { - drawStore.getDrawApp().updateGraphicAndRecord(station, stationModel); + platformModel.hasdoor = JSON.parse((showSelect as never)[hasDoor.value]); + platformModel.trainDirection = (showSelect as never)[trainDirection.value]; + const platform = drawStore.selectedGraphic as Platform; + if (platform) { + drawStore.getDrawApp().updateGraphicAndRecord(platform, platformModel); } } diff --git a/src/examples/app/app_message/protos/draw_data_storage.proto b/src/examples/app/app_message/protos/draw_data_storage.proto index da44bc9..9b3f960 100644 --- a/src/examples/app/app_message/protos/draw_data_storage.proto +++ b/src/examples/app/app_message/protos/draw_data_storage.proto @@ -68,13 +68,14 @@ message Platform { CommonInfo common = 1; string code = 2; bool hasdoor = 3; // 是否有屏蔽门 - int32 lineWidth = 4; // 线宽 - string lineColor = 5; // 站台线色 - string lineColorDoor = 6; // 屏蔽门线色 - Point point = 7; // 位置坐标 - float width = 8;//宽度 - float height = 9; //高度 - repeated string orbitCode = 10;//站台轨 + string trainDirection = 4; // 行驶方向--屏蔽门上下 + int32 lineWidth = 5; // 线宽 + string lineColor = 6; // 站台线色 + string lineColorDoor = 7; // 屏蔽门线色 + Point point = 8; // 位置坐标 + float width = 9;//宽度 + float height = 10; //高度 + repeated string orbitCode = 11;//站台轨 } message IscsFan { diff --git a/src/examples/app/graphics/PlatformInteraction.ts b/src/examples/app/graphics/PlatformInteraction.ts index eaf61ed..b438c83 100644 --- a/src/examples/app/graphics/PlatformInteraction.ts +++ b/src/examples/app/graphics/PlatformInteraction.ts @@ -33,6 +33,12 @@ export class PlatformData extends GraphicDataBase implements IPlatformData { set hasdoor(v: boolean) { this.data.hasdoor = v; } + get trainDirection(): string { + return this.data.trainDirection; + } + set trainDirection(v: string) { + this.data.trainDirection = v; + } get lineWidth(): number { return this.data.lineWidth; } diff --git a/src/examples/app/protos/draw_data_storage.ts b/src/examples/app/protos/draw_data_storage.ts index 6f7ba94..f41d891 100644 --- a/src/examples/app/protos/draw_data_storage.ts +++ b/src/examples/app/protos/draw_data_storage.ts @@ -964,6 +964,7 @@ export namespace graphicData { common?: CommonInfo; code?: string; hasdoor?: boolean; + trainDirection?: string; lineWidth?: number; lineColor?: string; lineColorDoor?: string; @@ -973,7 +974,7 @@ export namespace graphicData { orbitCode?: string[]; }) { super(); - pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [10], this.#one_of_decls); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [11], this.#one_of_decls); if (!Array.isArray(data) && typeof data == "object") { if ("common" in data && data.common != undefined) { this.common = data.common; @@ -984,6 +985,9 @@ export namespace graphicData { if ("hasdoor" in data && data.hasdoor != undefined) { this.hasdoor = data.hasdoor; } + if ("trainDirection" in data && data.trainDirection != undefined) { + this.trainDirection = data.trainDirection; + } if ("lineWidth" in data && data.lineWidth != undefined) { this.lineWidth = data.lineWidth; } @@ -1028,55 +1032,62 @@ export namespace graphicData { set hasdoor(value: boolean) { pb_1.Message.setField(this, 3, value); } - get lineWidth() { - return pb_1.Message.getFieldWithDefault(this, 4, 0) as number; + get trainDirection() { + return pb_1.Message.getFieldWithDefault(this, 4, "") as string; } - set lineWidth(value: number) { + set trainDirection(value: string) { pb_1.Message.setField(this, 4, value); } - get lineColor() { - return pb_1.Message.getFieldWithDefault(this, 5, "") as string; + get lineWidth() { + return pb_1.Message.getFieldWithDefault(this, 5, 0) as number; } - set lineColor(value: string) { + set lineWidth(value: number) { pb_1.Message.setField(this, 5, value); } - get lineColorDoor() { + get lineColor() { return pb_1.Message.getFieldWithDefault(this, 6, "") as string; } - set lineColorDoor(value: string) { + set lineColor(value: string) { pb_1.Message.setField(this, 6, value); } + get lineColorDoor() { + return pb_1.Message.getFieldWithDefault(this, 7, "") as string; + } + set lineColorDoor(value: string) { + pb_1.Message.setField(this, 7, value); + } get point() { - return pb_1.Message.getWrapperField(this, Point, 7) as Point; + return pb_1.Message.getWrapperField(this, Point, 8) as Point; } set point(value: Point) { - pb_1.Message.setWrapperField(this, 7, value); + pb_1.Message.setWrapperField(this, 8, value); } get has_point() { - return pb_1.Message.getField(this, 7) != null; + return pb_1.Message.getField(this, 8) != null; } get width() { - return pb_1.Message.getFieldWithDefault(this, 8, 0) as number; - } - set width(value: number) { - pb_1.Message.setField(this, 8, value); - } - get height() { return pb_1.Message.getFieldWithDefault(this, 9, 0) as number; } - set height(value: number) { + set width(value: number) { pb_1.Message.setField(this, 9, value); } + get height() { + return pb_1.Message.getFieldWithDefault(this, 10, 0) as number; + } + set height(value: number) { + pb_1.Message.setField(this, 10, value); + } get orbitCode() { - return pb_1.Message.getFieldWithDefault(this, 10, []) as string[]; + return pb_1.Message.getFieldWithDefault(this, 11, []) as string[]; } set orbitCode(value: string[]) { - pb_1.Message.setField(this, 10, value); + pb_1.Message.setField(this, 11, value); } static fromObject(data: { common?: ReturnType; code?: string; hasdoor?: boolean; + trainDirection?: string; lineWidth?: number; lineColor?: string; lineColorDoor?: string; @@ -1095,6 +1106,9 @@ export namespace graphicData { if (data.hasdoor != null) { message.hasdoor = data.hasdoor; } + if (data.trainDirection != null) { + message.trainDirection = data.trainDirection; + } if (data.lineWidth != null) { message.lineWidth = data.lineWidth; } @@ -1123,6 +1137,7 @@ export namespace graphicData { common?: ReturnType; code?: string; hasdoor?: boolean; + trainDirection?: string; lineWidth?: number; lineColor?: string; lineColorDoor?: string; @@ -1140,6 +1155,9 @@ export namespace graphicData { if (this.hasdoor != null) { data.hasdoor = this.hasdoor; } + if (this.trainDirection != null) { + data.trainDirection = this.trainDirection; + } if (this.lineWidth != null) { data.lineWidth = this.lineWidth; } @@ -1173,20 +1191,22 @@ export namespace graphicData { writer.writeString(2, this.code); if (this.hasdoor != false) writer.writeBool(3, this.hasdoor); + if (this.trainDirection.length) + writer.writeString(4, this.trainDirection); if (this.lineWidth != 0) - writer.writeInt32(4, this.lineWidth); + writer.writeInt32(5, this.lineWidth); if (this.lineColor.length) - writer.writeString(5, this.lineColor); + writer.writeString(6, this.lineColor); if (this.lineColorDoor.length) - writer.writeString(6, this.lineColorDoor); + writer.writeString(7, this.lineColorDoor); if (this.has_point) - writer.writeMessage(7, this.point, () => this.point.serialize(writer)); + writer.writeMessage(8, this.point, () => this.point.serialize(writer)); if (this.width != 0) - writer.writeFloat(8, this.width); + writer.writeFloat(9, this.width); if (this.height != 0) - writer.writeFloat(9, this.height); + writer.writeFloat(10, this.height); if (this.orbitCode.length) - writer.writeRepeatedString(10, this.orbitCode); + writer.writeRepeatedString(11, this.orbitCode); if (!w) return writer.getResultBuffer(); } @@ -1206,25 +1226,28 @@ export namespace graphicData { message.hasdoor = reader.readBool(); break; case 4: - message.lineWidth = reader.readInt32(); + message.trainDirection = reader.readString(); break; case 5: - message.lineColor = reader.readString(); + message.lineWidth = reader.readInt32(); break; case 6: - message.lineColorDoor = reader.readString(); + message.lineColor = reader.readString(); break; case 7: - reader.readMessage(message.point, () => message.point = Point.deserialize(reader)); + message.lineColorDoor = reader.readString(); break; case 8: - message.width = reader.readFloat(); + reader.readMessage(message.point, () => message.point = Point.deserialize(reader)); break; case 9: - message.height = reader.readFloat(); + message.width = reader.readFloat(); break; case 10: - pb_1.Message.addToRepeatedField(message, 10, reader.readString()); + message.height = reader.readFloat(); + break; + case 11: + pb_1.Message.addToRepeatedField(message, 11, reader.readString()); break; default: reader.skipField(); } @@ -1331,4 +1354,44 @@ export namespace graphicData { return IscsFan.deserialize(bytes); } } + export class Turnout extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | {}) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { } + } + static fromObject(data: {}): Turnout { + const message = new Turnout({}); + return message; + } + toObject() { + const data: {} = {}; + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): Turnout { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new Turnout(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): Turnout { + return Turnout.deserialize(bytes); + } + } } diff --git a/src/graphics/platform/Platform.ts b/src/graphics/platform/Platform.ts index cd6cd3d..ba46c2e 100644 --- a/src/graphics/platform/Platform.ts +++ b/src/graphics/platform/Platform.ts @@ -12,6 +12,8 @@ export interface IPlatformData extends GraphicData { 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; // 站台线色 @@ -59,15 +61,18 @@ export class Platform extends JlGraphic { 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); @@ -81,41 +86,34 @@ export class Platform extends JlGraphic { 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, - -height / 2 - 10 + 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 ); - //屏蔽门打开 - if (this.datas.hasdoor) { - doorGraphic.lineTo( - -platformConsts.doorOpenSpacing, - -height / 2 - platformConsts.doorPlatformSpacing - ); - doorGraphic.moveTo( - platformConsts.doorOpenSpacing, - -height / 2 - platformConsts.doorPlatformSpacing - ); - doorGraphic.lineTo( - width / 2 + this.datas.lineWidth / 2, - -height / 2 - platformConsts.doorPlatformSpacing - ); - } else { - doorGraphic.lineTo( - width / 2 + this.datas.lineWidth / 2, - -height / 2 - platformConsts.doorPlatformSpacing - ); - } } - /* doorGraphic.position.set( - 0, - height + platformConsts.doorPlatformSpacing * 2 - ); */ //站台 const platformGraphic = this.platformGraphic; platformGraphic.clear(); @@ -126,33 +124,26 @@ export class Platform extends JlGraphic { platformGraphic.beginFill(this.datas.lineColor, 1); platformGraphic.drawRect(0, 0, this.datas.width, this.datas.height); platformGraphic.endFill; - const rect = new Rectangle(0, 0, this.datas.width, this.datas.height); - platformGraphic.pivot = getRectangleCenter(rect); + 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(); - if (this.datas.hasdoor) { - 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 - ); - } + 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'; @@ -162,11 +153,35 @@ export class Platform extends JlGraphic { 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 { hasdoor: boolean; + trainDirection: string; lineWidth: number; lineColor: string; lineColorDoor: string; @@ -174,10 +189,11 @@ export class PlatformTemplate extends JlGraphicTemplate { 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.hasdoor = true; this.width = platformConsts.width; this.height = platformConsts.height; } diff --git a/src/graphics/platform/PlatformDrawAssistant.ts b/src/graphics/platform/PlatformDrawAssistant.ts index e6b9188..c441d67 100644 --- a/src/graphics/platform/PlatformDrawAssistant.ts +++ b/src/graphics/platform/PlatformDrawAssistant.ts @@ -103,6 +103,7 @@ export class PlatformDraw extends GraphicDrawAssistant< 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; From ae471acea363f26b74e45ec243f71cfd050f01b2 Mon Sep 17 00:00:00 2001 From: joylink_zhaoerwei Date: Wed, 31 May 2023 17:53:34 +0800 Subject: [PATCH 03/44] =?UTF-8?q?=E8=BD=A6=E7=AB=99=E5=88=9D=E6=8F=90?= =?UTF-8?q?=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/draw-app/DrawProperties.vue | 9 + .../draw-app/properties/StationProperty.vue | 79 ++++++++ .../draw-app/templates/StationTemplate.vue | 70 +++++++ .../protos/draw_data_storage.proto | 10 + .../app/graphics/StationInteraction.ts | 56 ++++++ src/examples/app/index.ts | 20 ++ src/examples/app/protos/draw_data_storage.ts | 190 +++++++++++++++++- src/graphics/station/Station.ts | 61 ++++++ src/graphics/station/StationDrawAssistant.ts | 73 +++++++ 9 files changed, 567 insertions(+), 1 deletion(-) create mode 100644 src/components/draw-app/properties/StationProperty.vue create mode 100644 src/components/draw-app/templates/StationTemplate.vue create mode 100644 src/examples/app/graphics/StationInteraction.ts create mode 100644 src/graphics/station/Station.ts create mode 100644 src/graphics/station/StationDrawAssistant.ts diff --git a/src/components/draw-app/DrawProperties.vue b/src/components/draw-app/DrawProperties.vue index 578796d..7fe95d0 100644 --- a/src/components/draw-app/DrawProperties.vue +++ b/src/components/draw-app/DrawProperties.vue @@ -13,6 +13,9 @@ + @@ -36,6 +39,9 @@ + @@ -48,12 +54,15 @@ diff --git a/src/components/draw-app/templates/StationTemplate.vue b/src/components/draw-app/templates/StationTemplate.vue new file mode 100644 index 0000000..fe433bf --- /dev/null +++ b/src/components/draw-app/templates/StationTemplate.vue @@ -0,0 +1,70 @@ + + + diff --git a/src/examples/app/app_message/protos/draw_data_storage.proto b/src/examples/app/app_message/protos/draw_data_storage.proto index 9b3f960..b13dca4 100644 --- a/src/examples/app/app_message/protos/draw_data_storage.proto +++ b/src/examples/app/app_message/protos/draw_data_storage.proto @@ -7,6 +7,7 @@ message RtssGraphicStorage { repeated Link links = 2; repeated IscsFan iscsFans = 3; repeated Platform Platforms = 4; + repeated Station stations = 5; } message Canvas { @@ -78,6 +79,15 @@ message Platform { repeated string orbitCode = 11;//站台轨 } +message Station { + CommonInfo common = 1; + string code = 2; + string codeColor = 3; // 车站字体颜色 + int32 codeFontSize = 4; // 车站字体大小 + Point point = 5; // 位置坐标 + +} + message IscsFan { CommonInfo common = 1; string code = 2; diff --git a/src/examples/app/graphics/StationInteraction.ts b/src/examples/app/graphics/StationInteraction.ts new file mode 100644 index 0000000..0b4c467 --- /dev/null +++ b/src/examples/app/graphics/StationInteraction.ts @@ -0,0 +1,56 @@ +import * as pb_1 from 'google-protobuf'; +import { IPointData } from 'pixi.js'; +import { IStationData } from 'src/graphics/station/Station'; +import { graphicData } from '../protos/draw_data_storage'; +import { GraphicDataBase } from './GraphicDataBase'; + +export class StationData extends GraphicDataBase implements IStationData { + constructor(data?: graphicData.Station) { + let station; + if (!data) { + station = new graphicData.Station({ + common: GraphicDataBase.defaultCommonInfo(), + }); + } else { + station = data; + } + super(station); + } + + public get data(): graphicData.Station { + return this.getData(); + } + get code(): string { + return this.data.code; + } + set code(v: string) { + this.data.code = v; + } + get codeColor(): string { + return this.data.codeColor; + } + set codeColor(v: string) { + this.data.codeColor = v; + } + get codeFontSize(): number { + return this.data.codeFontSize; + } + set codeFontSize(v: number) { + this.data.codeFontSize = v; + } + get point(): IPointData { + return this.data.point; + } + set point(point: IPointData) { + this.data.point = new graphicData.Point({ x: point.x, y: point.y }); + } + clone(): StationData { + return new StationData(this.data.cloneMessage()); + } + copyFrom(data: StationData): void { + pb_1.Message.copyInto(data.data, this.data); + } + eq(other: StationData): boolean { + return pb_1.Message.equals(this.data, other.data); + } +} diff --git a/src/examples/app/index.ts b/src/examples/app/index.ts index 80fef97..3dcc8f2 100644 --- a/src/examples/app/index.ts +++ b/src/examples/app/index.ts @@ -6,6 +6,8 @@ import { Link } from 'src/graphics/link/Link'; import { LinkDraw } from 'src/graphics/link/LinkDrawAssistant'; import { Platform } from 'src/graphics/platform/Platform'; import { PlatformDraw } from 'src/graphics/platform/PlatformDrawAssistant'; +import { Station } from 'src/graphics/station/Station'; +import { StationDraw } from 'src/graphics/station/StationDrawAssistant'; import { CombinationKey, GraphicApp, @@ -19,6 +21,7 @@ import { MenuItemOptions } from 'src/jlgraphic/ui/Menu'; import { IscsFanData } from './graphics/IscsFanInteraction'; import { LinkData } from './graphics/LinkInteraction'; import { PlatformData } from './graphics/PlatformInteraction'; +import { StationData } from './graphics/StationInteraction'; import { graphicData } from './protos/draw_data_storage'; export function fromStoragePoint(p: graphicData.Point): Point { @@ -100,6 +103,9 @@ export function initDrawApp(dom: HTMLElement): JlDrawApp { new PlatformDraw(app, () => { return new PlatformData(); }), + new StationDraw(app, () => { + return new StationData(); + }), ], }); @@ -145,6 +151,14 @@ export function initDrawApp(dom: HTMLElement): JlDrawApp { }, }) ); + app.addKeyboardListener( + new KeyListener({ + value: 'KeyO', + onPress: () => { + app.interactionPlugin(Station.Type).resume(); + }, + }) + ); app.addKeyboardListener( new KeyListener({ value: '1', @@ -189,6 +203,9 @@ export function saveDrawDatas(app: JlDrawApp) { } else if (Platform.Type === g.type) { const platformData = (g as Platform).saveData(); storage.Platforms.push((platformData as PlatformData).data); + } else if (Station.Type === g.type) { + const stationData = (g as Station).saveData(); + storage.stations.push((stationData as StationData).data); } }); const base64 = fromUint8Array(storage.serialize()); @@ -216,6 +233,9 @@ export function loadDrawDatas(app: GraphicApp) { storage.Platforms.forEach((platform) => { datas.push(new PlatformData(platform)); }); + storage.stations.forEach((station) => { + datas.push(new StationData(station)); + }); app.loadGraphic(datas); } else { app.loadGraphic([]); diff --git a/src/examples/app/protos/draw_data_storage.ts b/src/examples/app/protos/draw_data_storage.ts index f41d891..7690882 100644 --- a/src/examples/app/protos/draw_data_storage.ts +++ b/src/examples/app/protos/draw_data_storage.ts @@ -12,9 +12,10 @@ export namespace graphicData { links?: Link[]; iscsFans?: IscsFan[]; Platforms?: Platform[]; + stations?: Station[]; }) { super(); - pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [2, 3, 4], this.#one_of_decls); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [2, 3, 4, 5], this.#one_of_decls); if (!Array.isArray(data) && typeof data == "object") { if ("canvas" in data && data.canvas != undefined) { this.canvas = data.canvas; @@ -28,6 +29,9 @@ export namespace graphicData { if ("Platforms" in data && data.Platforms != undefined) { this.Platforms = data.Platforms; } + if ("stations" in data && data.stations != undefined) { + this.stations = data.stations; + } } } get canvas() { @@ -57,11 +61,18 @@ export namespace graphicData { set Platforms(value: Platform[]) { pb_1.Message.setRepeatedWrapperField(this, 4, value); } + get stations() { + return pb_1.Message.getRepeatedWrapperField(this, Station, 5) as Station[]; + } + set stations(value: Station[]) { + pb_1.Message.setRepeatedWrapperField(this, 5, value); + } static fromObject(data: { canvas?: ReturnType; links?: ReturnType[]; iscsFans?: ReturnType[]; Platforms?: ReturnType[]; + stations?: ReturnType[]; }): RtssGraphicStorage { const message = new RtssGraphicStorage({}); if (data.canvas != null) { @@ -76,6 +87,9 @@ export namespace graphicData { if (data.Platforms != null) { message.Platforms = data.Platforms.map(item => Platform.fromObject(item)); } + if (data.stations != null) { + message.stations = data.stations.map(item => Station.fromObject(item)); + } return message; } toObject() { @@ -84,6 +98,7 @@ export namespace graphicData { links?: ReturnType[]; iscsFans?: ReturnType[]; Platforms?: ReturnType[]; + stations?: ReturnType[]; } = {}; if (this.canvas != null) { data.canvas = this.canvas.toObject(); @@ -97,6 +112,9 @@ export namespace graphicData { if (this.Platforms != null) { data.Platforms = this.Platforms.map((item: Platform) => item.toObject()); } + if (this.stations != null) { + data.stations = this.stations.map((item: Station) => item.toObject()); + } return data; } serialize(): Uint8Array; @@ -111,6 +129,8 @@ export namespace graphicData { writer.writeRepeatedMessage(3, this.iscsFans, (item: IscsFan) => item.serialize(writer)); if (this.Platforms.length) writer.writeRepeatedMessage(4, this.Platforms, (item: Platform) => item.serialize(writer)); + if (this.stations.length) + writer.writeRepeatedMessage(5, this.stations, (item: Station) => item.serialize(writer)); if (!w) return writer.getResultBuffer(); } @@ -132,6 +152,9 @@ export namespace graphicData { case 4: reader.readMessage(message.Platforms, () => pb_1.Message.addToRepeatedWrapperField(message, 4, Platform.deserialize(reader), Platform)); break; + case 5: + reader.readMessage(message.stations, () => pb_1.Message.addToRepeatedWrapperField(message, 5, Station.deserialize(reader), Station)); + break; default: reader.skipField(); } } @@ -1261,6 +1284,171 @@ export namespace graphicData { return Platform.deserialize(bytes); } } + export class Station extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + common?: CommonInfo; + code?: string; + codeColor?: string; + codeFontSize?: number; + point?: Point; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("common" in data && data.common != undefined) { + this.common = data.common; + } + if ("code" in data && data.code != undefined) { + this.code = data.code; + } + if ("codeColor" in data && data.codeColor != undefined) { + this.codeColor = data.codeColor; + } + if ("codeFontSize" in data && data.codeFontSize != undefined) { + this.codeFontSize = data.codeFontSize; + } + if ("point" in data && data.point != undefined) { + this.point = data.point; + } + } + } + get common() { + return pb_1.Message.getWrapperField(this, CommonInfo, 1) as CommonInfo; + } + set common(value: CommonInfo) { + pb_1.Message.setWrapperField(this, 1, value); + } + get has_common() { + return pb_1.Message.getField(this, 1) != null; + } + get code() { + return pb_1.Message.getFieldWithDefault(this, 2, "") as string; + } + set code(value: string) { + pb_1.Message.setField(this, 2, value); + } + get codeColor() { + return pb_1.Message.getFieldWithDefault(this, 3, "") as string; + } + set codeColor(value: string) { + pb_1.Message.setField(this, 3, value); + } + get codeFontSize() { + return pb_1.Message.getFieldWithDefault(this, 4, 0) as number; + } + set codeFontSize(value: number) { + pb_1.Message.setField(this, 4, value); + } + get point() { + return pb_1.Message.getWrapperField(this, Point, 5) as Point; + } + set point(value: Point) { + pb_1.Message.setWrapperField(this, 5, value); + } + get has_point() { + return pb_1.Message.getField(this, 5) != null; + } + static fromObject(data: { + common?: ReturnType; + code?: string; + codeColor?: string; + codeFontSize?: number; + point?: ReturnType; + }): Station { + const message = new Station({}); + if (data.common != null) { + message.common = CommonInfo.fromObject(data.common); + } + if (data.code != null) { + message.code = data.code; + } + if (data.codeColor != null) { + message.codeColor = data.codeColor; + } + if (data.codeFontSize != null) { + message.codeFontSize = data.codeFontSize; + } + if (data.point != null) { + message.point = Point.fromObject(data.point); + } + return message; + } + toObject() { + const data: { + common?: ReturnType; + code?: string; + codeColor?: string; + codeFontSize?: number; + point?: ReturnType; + } = {}; + if (this.common != null) { + data.common = this.common.toObject(); + } + if (this.code != null) { + data.code = this.code; + } + if (this.codeColor != null) { + data.codeColor = this.codeColor; + } + if (this.codeFontSize != null) { + data.codeFontSize = this.codeFontSize; + } + if (this.point != null) { + data.point = this.point.toObject(); + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.has_common) + writer.writeMessage(1, this.common, () => this.common.serialize(writer)); + if (this.code.length) + writer.writeString(2, this.code); + if (this.codeColor.length) + writer.writeString(3, this.codeColor); + if (this.codeFontSize != 0) + writer.writeInt32(4, this.codeFontSize); + if (this.has_point) + writer.writeMessage(5, this.point, () => this.point.serialize(writer)); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): Station { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new Station(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + reader.readMessage(message.common, () => message.common = CommonInfo.deserialize(reader)); + break; + case 2: + message.code = reader.readString(); + break; + case 3: + message.codeColor = reader.readString(); + break; + case 4: + message.codeFontSize = reader.readInt32(); + break; + case 5: + reader.readMessage(message.point, () => message.point = Point.deserialize(reader)); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): Station { + return Station.deserialize(bytes); + } + } export class IscsFan extends pb_1.Message { #one_of_decls: number[][] = []; constructor(data?: any[] | { diff --git a/src/graphics/station/Station.ts b/src/graphics/station/Station.ts new file mode 100644 index 0000000..1b41740 --- /dev/null +++ b/src/graphics/station/Station.ts @@ -0,0 +1,61 @@ +import { IPointData } from 'pixi.js'; +import { + GraphicData, + JlGraphic, + JlGraphicTemplate, + VectorText, +} from 'src/jlgraphic'; + +export interface IStationData extends GraphicData { + get code(): string; // 编号 + set code(v: string); + get codeColor(): string; // 车站字体颜色 + set codeColor(v: string); + get codeFontSize(): number; // 车站字体大小 + set codeFontSize(v: number); + get point(): IPointData; // 位置坐标 + set point(point: IPointData); + clone(): IStationData; + copyFrom(data: IStationData): void; + eq(other: IStationData): boolean; +} + +export class Station extends JlGraphic { + static Type = 'station'; + codeGraph: VectorText = new VectorText(''); //站台旁数字、字符 + constructor() { + super(Station.Type); + this.addChild(this.codeGraph); + this.codeGraph.setVectorFontSize(22); + } + + get datas(): IStationData { + return this.getDatas(); + } + doRepaint(): void { + 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); + codeGraph.position.set(this.datas.point.x, this.datas.point.y); + codeGraph.style.fill = this.datas.codeColor; + } +} + +export class StationTemplate extends JlGraphicTemplate { + codeColor: string; + codeFontSize: number; + constructor() { + super(Station.Type); + this.codeColor = '0xF48815'; + this.codeFontSize = 22; + } + new(): Station { + return new Station(); + } +} diff --git a/src/graphics/station/StationDrawAssistant.ts b/src/graphics/station/StationDrawAssistant.ts new file mode 100644 index 0000000..3b991b9 --- /dev/null +++ b/src/graphics/station/StationDrawAssistant.ts @@ -0,0 +1,73 @@ +import { FederatedPointerEvent, Point } from 'pixi.js'; +import { + GraphicDrawAssistant, + JlDrawApp, + KeyListener, + 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(''); + + // 快捷绘制 + keypListener: KeyListener = new KeyListener({ + value: 'KeyO', + global: true, + onPress: () => { + //this.graphicTemplate.hasdoor = true; + }, + }); + + constructor(app: JlDrawApp, createData: () => IStationData) { + super(app, new StationTemplate(), createData, Station.Type, '车站Station'); + this.container.addChild(this.codeGraph); + this.codeGraph.setVectorFontSize(22); + } + + bind(): void { + super.bind(); + this.app.addKeyboardListener(this.keypListener); + } + unbind(): void { + super.unbind(); + this.app.removeKeyboardListener(this.keypListener); + } + + clearCache(): void { + //this.codeGraph.clear(); + } + onRightClick(): void { + this.createAndStore(true); + } + 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); + } + prepareData(data: IStationData): boolean { + const template = this.graphicTemplate; + data.point = this.point; + data.codeColor = template.codeColor; + data.codeFontSize = template.codeFontSize; + return true; + } +} From 241de95414f4e31a6e5bc723a2da3c6c279371ce Mon Sep 17 00:00:00 2001 From: joylink_zhaoerwei Date: Thu, 1 Jun 2023 10:15:16 +0800 Subject: [PATCH 04/44] =?UTF-8?q?=E7=AB=99=E5=8F=B0=E5=92=8C=E8=BD=A6?= =?UTF-8?q?=E7=AB=99=E5=BE=AE=E8=B0=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../draw-app/properties/PlatformProperty.vue | 14 +++++++++ .../draw-app/properties/StationProperty.vue | 2 +- .../platform/PlatformDrawAssistant.ts | 31 ++++++++++++++++++- src/graphics/station/StationDrawAssistant.ts | 29 +++++++++++++++++ 4 files changed, 74 insertions(+), 2 deletions(-) diff --git a/src/components/draw-app/properties/PlatformProperty.vue b/src/components/draw-app/properties/PlatformProperty.vue index 06c5498..147eeeb 100644 --- a/src/components/draw-app/properties/PlatformProperty.vue +++ b/src/components/draw-app/properties/PlatformProperty.vue @@ -69,6 +69,12 @@ enum showSelect { 向左 = 'left', 向右 = 'right', } +enum showSelectData { + true = '是', + false = '否', + left = '向左', + right = '向右', +} drawStore.$subscribe; watch( @@ -76,6 +82,10 @@ watch( (val) => { if (val && val.type == Platform.Type) { platformModel.copyFrom(val.saveData() as PlatformData); + hasDoor.value = (showSelectData as never)[platformModel.hasdoor + '']; + trainDirection.value = (showSelectData as never)[ + platformModel.trainDirection + ]; } } ); @@ -84,6 +94,10 @@ onMounted(() => { const platform = drawStore.selectedGraphic as Platform; if (platform) { platformModel.copyFrom(platform.saveData()); + hasDoor.value = (showSelectData as never)[platformModel.hasdoor + '']; + trainDirection.value = (showSelectData as never)[ + platformModel.trainDirection + ]; } }); diff --git a/src/components/draw-app/properties/StationProperty.vue b/src/components/draw-app/properties/StationProperty.vue index 8bfb79c..0b763fe 100644 --- a/src/components/draw-app/properties/StationProperty.vue +++ b/src/components/draw-app/properties/StationProperty.vue @@ -15,7 +15,7 @@ @blur="onUpdate" label="字体大小" lazy-rules - :rules="[(val) => (val && val > 0) || '画布宽必须大于0']" + :rules="[(val) => (val && val > 0) || '字体大小必须大于0']" /> { + static Name = 'platform_transform'; + constructor(app: JlDrawApp) { + super(platformInteraction.Name, app); + } + static init(app: JlDrawApp) { + 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; + } +} diff --git a/src/graphics/station/StationDrawAssistant.ts b/src/graphics/station/StationDrawAssistant.ts index 3b991b9..ebbdc30 100644 --- a/src/graphics/station/StationDrawAssistant.ts +++ b/src/graphics/station/StationDrawAssistant.ts @@ -1,7 +1,9 @@ import { FederatedPointerEvent, Point } from 'pixi.js'; import { GraphicDrawAssistant, + GraphicInteractionPlugin, JlDrawApp, + JlGraphic, KeyListener, VectorText, } from 'src/jlgraphic'; @@ -32,6 +34,7 @@ export class StationDraw extends GraphicDrawAssistant< super(app, new StationTemplate(), createData, Station.Type, '车站Station'); this.container.addChild(this.codeGraph); this.codeGraph.setVectorFontSize(22); + stationInteraction.init(app); } bind(): void { @@ -71,3 +74,29 @@ export class StationDraw extends GraphicDrawAssistant< return true; } } + +export class stationInteraction extends GraphicInteractionPlugin { + 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; + } +} From bb9e8345bd56e9332e690fb73664020bb1241ab7 Mon Sep 17 00:00:00 2001 From: joylink_zhaoerwei Date: Thu, 1 Jun 2023 10:50:55 +0800 Subject: [PATCH 05/44] =?UTF-8?q?=E5=BE=AE=E8=B0=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/graphics/station/StationDrawAssistant.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/graphics/station/StationDrawAssistant.ts b/src/graphics/station/StationDrawAssistant.ts index ebbdc30..bee53ae 100644 --- a/src/graphics/station/StationDrawAssistant.ts +++ b/src/graphics/station/StationDrawAssistant.ts @@ -33,7 +33,6 @@ export class StationDraw extends GraphicDrawAssistant< constructor(app: JlDrawApp, createData: () => IStationData) { super(app, new StationTemplate(), createData, Station.Type, '车站Station'); this.container.addChild(this.codeGraph); - this.codeGraph.setVectorFontSize(22); stationInteraction.init(app); } @@ -65,6 +64,7 @@ export class StationDraw extends GraphicDrawAssistant< 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; From 9be2d014bcb2015df90a828240a2beca8737e881 Mon Sep 17 00:00:00 2001 From: joylink_zhaoerwei Date: Thu, 1 Jun 2023 13:41:53 +0800 Subject: [PATCH 06/44] =?UTF-8?q?=E8=BD=A6=E7=AB=99=E5=BE=AE=E8=B0=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/graphics/station/Station.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/graphics/station/Station.ts b/src/graphics/station/Station.ts index 1b41740..e653380 100644 --- a/src/graphics/station/Station.ts +++ b/src/graphics/station/Station.ts @@ -26,13 +26,13 @@ export class Station extends JlGraphic { constructor() { super(Station.Type); this.addChild(this.codeGraph); - this.codeGraph.setVectorFontSize(22); } get datas(): IStationData { return this.getDatas(); } doRepaint(): void { + this.position.set(this.datas.point.x, this.datas.point.y); const codeGraph = this.codeGraph; if (this.datas.code == '') { codeGraph.text = '车站Station'; @@ -42,7 +42,6 @@ export class Station extends JlGraphic { codeGraph.style.fill = this.datas.codeColor; codeGraph.setVectorFontSize(this.datas.codeFontSize); codeGraph.anchor.set(0.5); - codeGraph.position.set(this.datas.point.x, this.datas.point.y); codeGraph.style.fill = this.datas.codeColor; } } From f4b9ba2b37e5094872e7862fac74e9836a562865 Mon Sep 17 00:00:00 2001 From: joylink_zhaoerwei Date: Fri, 2 Jun 2023 14:16:02 +0800 Subject: [PATCH 07/44] =?UTF-8?q?=E5=A4=9A=E8=BE=B9=E5=BD=A2=E7=BA=BF?= =?UTF-8?q?=E6=AE=B5=E7=BB=86=E5=88=86=E5=A4=87=E7=94=A8--=E5=88=86?= =?UTF-8?q?=E5=89=B2=E5=A4=9A=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/jlgraphic/plugins/GraphicEditPlugin.ts | 19 ++++++++++++++++ src/jlgraphic/utils/GraphicUtils.ts | 25 ++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/src/jlgraphic/plugins/GraphicEditPlugin.ts b/src/jlgraphic/plugins/GraphicEditPlugin.ts index 276b519..39075ca 100644 --- a/src/jlgraphic/plugins/GraphicEditPlugin.ts +++ b/src/jlgraphic/plugins/GraphicEditPlugin.ts @@ -19,6 +19,7 @@ import { distance2, linePoint, pointPolygon, + calculateLineSegmentingPoint, } from '../utils'; import { GraphicTransformEvent, ShiftData } from './GraphicTransformPlugin'; @@ -57,6 +58,9 @@ export abstract class GraphicEditPlugin< export const addWaypointConfig: MenuItemOptions = { name: '添加路径点', }; +export const addWaySegmentingConfig: MenuItemOptions = { + name: '细分', +}; export const removeWaypointConfig: MenuItemOptions = { name: '移除路径点', }; @@ -251,6 +255,21 @@ export function addLineWayPoint( graphic.linePoints = points; } +export function addPolygonSegmentingPoint( + graphic: ILineGraphic, + start: number, + end: number, + knife = 2 +) { + const linePoints = graphic.linePoints; + const points = linePoints.slice(0, start + 1); + points.push( + ...calculateLineSegmentingPoint(linePoints[start], linePoints[end], knife) + ); + points.push(...linePoints.slice(end)); + graphic.linePoints = points; +} + function assertBezierWayPoint(i: number) { const c = i % 3; if (c !== 0) { diff --git a/src/jlgraphic/utils/GraphicUtils.ts b/src/jlgraphic/utils/GraphicUtils.ts index 362935e..9cd3ff8 100644 --- a/src/jlgraphic/utils/GraphicUtils.ts +++ b/src/jlgraphic/utils/GraphicUtils.ts @@ -287,6 +287,31 @@ export function calculateLineMidpoint(p1: IPointData, p2: IPointData): Point { return new Point(x, y); } +/** + * 计算线段细分坐标--线段分成几份 + * @param p1 + * @param p2 + * @param knife + * @returns + */ +export function calculateLineSegmentingPoint( + p1: IPointData, + p2: IPointData, + knife: number +): IPointData[] { + const segmentingPoints: IPointData[] = []; + const x = p1.x < p2.x ? p1.x : p2.x; + const y = p1.y < p2.y ? p1.y : p2.y; + const w = Math.abs(p1.x - p2.x); + const h = Math.abs(p1.y - p2.y); + for (let i = 0; i < knife - 1; i++) { + const pointX = x + (w * (i + 1)) / knife; + const pointy = y + (h * (i + 1)) / knife; + segmentingPoints.push(new Point(pointX, pointy)); + } + return segmentingPoints; +} + /** * 计算点到直线距离 * @param p1 From a30e2113d101120642e3946886bb46022ee2bca1 Mon Sep 17 00:00:00 2001 From: joylink_zhaoerwei Date: Fri, 2 Jun 2023 16:53:28 +0800 Subject: [PATCH 08/44] =?UTF-8?q?=E7=9F=A9=E5=BD=A2--=E5=8F=AF=E5=8F=98?= =?UTF-8?q?=E5=A4=9A=E8=BE=B9=E5=BD=A2--=E4=BB=A3=E7=A0=81=E5=A4=87?= =?UTF-8?q?=E7=94=A8=EF=BC=88=E5=BE=85=E4=BC=98=E5=8C=96=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../protos/draw_data_storage.proto | 12 + src/examples/app/graphics/RectInteraction.ts | 77 +++++ src/examples/app/index.ts | 20 ++ src/examples/app/protos/draw_data_storage.ts | 259 ++++++++++++++++- src/graphics/rect/Rect.ts | 86 ++++++ src/graphics/rect/RectDrawAssistant.ts | 272 ++++++++++++++++++ 6 files changed, 725 insertions(+), 1 deletion(-) create mode 100644 src/examples/app/graphics/RectInteraction.ts create mode 100644 src/graphics/rect/Rect.ts create mode 100644 src/graphics/rect/RectDrawAssistant.ts diff --git a/src/examples/app/app_message/protos/draw_data_storage.proto b/src/examples/app/app_message/protos/draw_data_storage.proto index b13dca4..6b9cc35 100644 --- a/src/examples/app/app_message/protos/draw_data_storage.proto +++ b/src/examples/app/app_message/protos/draw_data_storage.proto @@ -8,6 +8,7 @@ message RtssGraphicStorage { repeated IscsFan iscsFans = 3; repeated Platform Platforms = 4; repeated Station stations = 5; + repeated Rect Rects = 6; } message Canvas { @@ -65,6 +66,17 @@ message Link { repeated Point points = 7; // 点坐标列表 } +message Rect { + CommonInfo common = 1; + string code = 2; + int32 lineWidth = 3; // 线宽 + string lineColor = 4; // 线色 + Point point = 5; // 位置坐标 + float width = 6;//宽度 + float height = 7; //高度 + repeated Point points = 8; // 点坐标列表 +} + message Platform { CommonInfo common = 1; string code = 2; diff --git a/src/examples/app/graphics/RectInteraction.ts b/src/examples/app/graphics/RectInteraction.ts new file mode 100644 index 0000000..9951752 --- /dev/null +++ b/src/examples/app/graphics/RectInteraction.ts @@ -0,0 +1,77 @@ +import * as pb_1 from 'google-protobuf'; +import { IPointData } from 'pixi.js'; +import { IRectData } from 'src/graphics/rect/Rect'; +import { graphicData } from '../protos/draw_data_storage'; +import { GraphicDataBase } from './GraphicDataBase'; + +export class RectData extends GraphicDataBase implements IRectData { + constructor(data?: graphicData.Rect) { + let rect; + if (!data) { + rect = new graphicData.Rect({ + common: GraphicDataBase.defaultCommonInfo(), + }); + } else { + rect = data; + } + super(rect); + } + + public get data(): graphicData.Rect { + return this.getData(); + } + + get code(): string { + return this.data.code; + } + set code(v: string) { + this.data.code = v; + } + get lineWidth(): number { + return this.data.lineWidth; + } + set lineWidth(v: number) { + this.data.lineWidth = v; + } + get lineColor(): string { + return this.data.lineColor; + } + set lineColor(v: string) { + this.data.lineColor = v; + } + get point(): IPointData { + return this.data.point; + } + set point(point: IPointData) { + this.data.point = new graphicData.Point({ x: point.x, y: point.y }); + } + get width(): number { + return this.data.width; + } + set width(v: number) { + this.data.width = v; + } + get height(): number { + return this.data.height; + } + set height(v: number) { + this.data.height = v; + } + get points(): IPointData[] { + return this.data.points; + } + set points(points: IPointData[]) { + this.data.points = points.map( + (p) => new graphicData.Point({ x: p.x, y: p.y }) + ); + } + clone(): RectData { + return new RectData(this.data.cloneMessage()); + } + copyFrom(data: RectData): void { + pb_1.Message.copyInto(data.data, this.data); + } + eq(other: RectData): boolean { + return pb_1.Message.equals(this.data, other.data); + } +} diff --git a/src/examples/app/index.ts b/src/examples/app/index.ts index 3dcc8f2..b120fa1 100644 --- a/src/examples/app/index.ts +++ b/src/examples/app/index.ts @@ -4,6 +4,8 @@ import { IscsFan } from 'src/graphics/iscs-fan/IscsFan'; import { IscsFanDraw } from 'src/graphics/iscs-fan/IscsFanDrawAssistant'; import { Link } from 'src/graphics/link/Link'; import { LinkDraw } from 'src/graphics/link/LinkDrawAssistant'; +import { Rect } from 'src/graphics/rect/Rect'; +import { RectDraw } from 'src/graphics/rect/RectDrawAssistant'; import { Platform } from 'src/graphics/platform/Platform'; import { PlatformDraw } from 'src/graphics/platform/PlatformDrawAssistant'; import { Station } from 'src/graphics/station/Station'; @@ -20,6 +22,7 @@ import { ContextMenu } from 'src/jlgraphic/ui/ContextMenu'; import { MenuItemOptions } from 'src/jlgraphic/ui/Menu'; import { IscsFanData } from './graphics/IscsFanInteraction'; import { LinkData } from './graphics/LinkInteraction'; +import { RectData } from './graphics/RectInteraction'; import { PlatformData } from './graphics/PlatformInteraction'; import { StationData } from './graphics/StationInteraction'; import { graphicData } from './protos/draw_data_storage'; @@ -97,6 +100,9 @@ export function initDrawApp(dom: HTMLElement): JlDrawApp { new LinkDraw(app, () => { return new LinkData(); }), + new RectDraw(app, () => { + return new RectData(); + }), new IscsFanDraw(app, () => { return new IscsFanData(); }), @@ -135,6 +141,14 @@ export function initDrawApp(dom: HTMLElement): JlDrawApp { }, }) ); + app.addKeyboardListener( + new KeyListener({ + value: 'KeyR', + onPress: () => { + app.interactionPlugin(Rect.Type).resume(); + }, + }) + ); app.addKeyboardListener( new KeyListener({ value: 'KeyF', @@ -197,6 +211,9 @@ export function saveDrawDatas(app: JlDrawApp) { if (Link.Type === g.type) { const linkData = (g as Link).saveData(); storage.links.push((linkData as LinkData).data); + } else if (Rect.Type === g.type) { + const rectData = (g as Rect).saveData(); + storage.Rects.push((rectData as RectData).data); } else if (IscsFan.Type === g.type) { const IscsFanData = (g as IscsFan).saveData(); storage.iscsFans.push((IscsFanData as IscsFanData).data); @@ -227,6 +244,9 @@ export function loadDrawDatas(app: GraphicApp) { storage.links.forEach((link) => { datas.push(new LinkData(link)); }); + storage.Rects.forEach((rect) => { + datas.push(new RectData(rect)); + }); storage.iscsFans.forEach((fan) => { datas.push(new IscsFanData(fan)); }); diff --git a/src/examples/app/protos/draw_data_storage.ts b/src/examples/app/protos/draw_data_storage.ts index 7690882..7f01476 100644 --- a/src/examples/app/protos/draw_data_storage.ts +++ b/src/examples/app/protos/draw_data_storage.ts @@ -13,9 +13,10 @@ export namespace graphicData { iscsFans?: IscsFan[]; Platforms?: Platform[]; stations?: Station[]; + Rects?: Rect[]; }) { super(); - pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [2, 3, 4, 5], this.#one_of_decls); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [2, 3, 4, 5, 6], this.#one_of_decls); if (!Array.isArray(data) && typeof data == "object") { if ("canvas" in data && data.canvas != undefined) { this.canvas = data.canvas; @@ -32,6 +33,9 @@ export namespace graphicData { if ("stations" in data && data.stations != undefined) { this.stations = data.stations; } + if ("Rects" in data && data.Rects != undefined) { + this.Rects = data.Rects; + } } } get canvas() { @@ -67,12 +71,19 @@ export namespace graphicData { set stations(value: Station[]) { pb_1.Message.setRepeatedWrapperField(this, 5, value); } + get Rects() { + return pb_1.Message.getRepeatedWrapperField(this, Rect, 6) as Rect[]; + } + set Rects(value: Rect[]) { + pb_1.Message.setRepeatedWrapperField(this, 6, value); + } static fromObject(data: { canvas?: ReturnType; links?: ReturnType[]; iscsFans?: ReturnType[]; Platforms?: ReturnType[]; stations?: ReturnType[]; + Rects?: ReturnType[]; }): RtssGraphicStorage { const message = new RtssGraphicStorage({}); if (data.canvas != null) { @@ -90,6 +101,9 @@ export namespace graphicData { if (data.stations != null) { message.stations = data.stations.map(item => Station.fromObject(item)); } + if (data.Rects != null) { + message.Rects = data.Rects.map(item => Rect.fromObject(item)); + } return message; } toObject() { @@ -99,6 +113,7 @@ export namespace graphicData { iscsFans?: ReturnType[]; Platforms?: ReturnType[]; stations?: ReturnType[]; + Rects?: ReturnType[]; } = {}; if (this.canvas != null) { data.canvas = this.canvas.toObject(); @@ -115,6 +130,9 @@ export namespace graphicData { if (this.stations != null) { data.stations = this.stations.map((item: Station) => item.toObject()); } + if (this.Rects != null) { + data.Rects = this.Rects.map((item: Rect) => item.toObject()); + } return data; } serialize(): Uint8Array; @@ -131,6 +149,8 @@ export namespace graphicData { writer.writeRepeatedMessage(4, this.Platforms, (item: Platform) => item.serialize(writer)); if (this.stations.length) writer.writeRepeatedMessage(5, this.stations, (item: Station) => item.serialize(writer)); + if (this.Rects.length) + writer.writeRepeatedMessage(6, this.Rects, (item: Rect) => item.serialize(writer)); if (!w) return writer.getResultBuffer(); } @@ -155,6 +175,9 @@ export namespace graphicData { case 5: reader.readMessage(message.stations, () => pb_1.Message.addToRepeatedWrapperField(message, 5, Station.deserialize(reader), Station)); break; + case 6: + reader.readMessage(message.Rects, () => pb_1.Message.addToRepeatedWrapperField(message, 6, Rect.deserialize(reader), Rect)); + break; default: reader.skipField(); } } @@ -981,6 +1004,240 @@ export namespace graphicData { return Link.deserialize(bytes); } } + export class Rect extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + common?: CommonInfo; + code?: string; + lineWidth?: number; + lineColor?: string; + point?: Point; + width?: number; + height?: number; + points?: Point[]; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [8], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("common" in data && data.common != undefined) { + this.common = data.common; + } + if ("code" in data && data.code != undefined) { + this.code = data.code; + } + if ("lineWidth" in data && data.lineWidth != undefined) { + this.lineWidth = data.lineWidth; + } + if ("lineColor" in data && data.lineColor != undefined) { + this.lineColor = data.lineColor; + } + if ("point" in data && data.point != undefined) { + this.point = data.point; + } + if ("width" in data && data.width != undefined) { + this.width = data.width; + } + if ("height" in data && data.height != undefined) { + this.height = data.height; + } + if ("points" in data && data.points != undefined) { + this.points = data.points; + } + } + } + get common() { + return pb_1.Message.getWrapperField(this, CommonInfo, 1) as CommonInfo; + } + set common(value: CommonInfo) { + pb_1.Message.setWrapperField(this, 1, value); + } + get has_common() { + return pb_1.Message.getField(this, 1) != null; + } + get code() { + return pb_1.Message.getFieldWithDefault(this, 2, "") as string; + } + set code(value: string) { + pb_1.Message.setField(this, 2, value); + } + get lineWidth() { + return pb_1.Message.getFieldWithDefault(this, 3, 0) as number; + } + set lineWidth(value: number) { + pb_1.Message.setField(this, 3, value); + } + get lineColor() { + return pb_1.Message.getFieldWithDefault(this, 4, "") as string; + } + set lineColor(value: string) { + pb_1.Message.setField(this, 4, value); + } + get point() { + return pb_1.Message.getWrapperField(this, Point, 5) as Point; + } + set point(value: Point) { + pb_1.Message.setWrapperField(this, 5, value); + } + get has_point() { + return pb_1.Message.getField(this, 5) != null; + } + get width() { + return pb_1.Message.getFieldWithDefault(this, 6, 0) as number; + } + set width(value: number) { + pb_1.Message.setField(this, 6, value); + } + get height() { + return pb_1.Message.getFieldWithDefault(this, 7, 0) as number; + } + set height(value: number) { + pb_1.Message.setField(this, 7, value); + } + get points() { + return pb_1.Message.getRepeatedWrapperField(this, Point, 8) as Point[]; + } + set points(value: Point[]) { + pb_1.Message.setRepeatedWrapperField(this, 8, value); + } + static fromObject(data: { + common?: ReturnType; + code?: string; + lineWidth?: number; + lineColor?: string; + point?: ReturnType; + width?: number; + height?: number; + points?: ReturnType[]; + }): Rect { + const message = new Rect({}); + if (data.common != null) { + message.common = CommonInfo.fromObject(data.common); + } + if (data.code != null) { + message.code = data.code; + } + if (data.lineWidth != null) { + message.lineWidth = data.lineWidth; + } + if (data.lineColor != null) { + message.lineColor = data.lineColor; + } + if (data.point != null) { + message.point = Point.fromObject(data.point); + } + if (data.width != null) { + message.width = data.width; + } + if (data.height != null) { + message.height = data.height; + } + if (data.points != null) { + message.points = data.points.map(item => Point.fromObject(item)); + } + return message; + } + toObject() { + const data: { + common?: ReturnType; + code?: string; + lineWidth?: number; + lineColor?: string; + point?: ReturnType; + width?: number; + height?: number; + points?: ReturnType[]; + } = {}; + if (this.common != null) { + data.common = this.common.toObject(); + } + if (this.code != null) { + data.code = this.code; + } + if (this.lineWidth != null) { + data.lineWidth = this.lineWidth; + } + if (this.lineColor != null) { + data.lineColor = this.lineColor; + } + if (this.point != null) { + data.point = this.point.toObject(); + } + if (this.width != null) { + data.width = this.width; + } + if (this.height != null) { + data.height = this.height; + } + if (this.points != null) { + data.points = this.points.map((item: Point) => item.toObject()); + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.has_common) + writer.writeMessage(1, this.common, () => this.common.serialize(writer)); + if (this.code.length) + writer.writeString(2, this.code); + if (this.lineWidth != 0) + writer.writeInt32(3, this.lineWidth); + if (this.lineColor.length) + writer.writeString(4, this.lineColor); + if (this.has_point) + writer.writeMessage(5, this.point, () => this.point.serialize(writer)); + if (this.width != 0) + writer.writeFloat(6, this.width); + if (this.height != 0) + writer.writeFloat(7, this.height); + if (this.points.length) + writer.writeRepeatedMessage(8, this.points, (item: Point) => item.serialize(writer)); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): Rect { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new Rect(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + reader.readMessage(message.common, () => message.common = CommonInfo.deserialize(reader)); + break; + case 2: + message.code = reader.readString(); + break; + case 3: + message.lineWidth = reader.readInt32(); + break; + case 4: + message.lineColor = reader.readString(); + break; + case 5: + reader.readMessage(message.point, () => message.point = Point.deserialize(reader)); + break; + case 6: + message.width = reader.readFloat(); + break; + case 7: + message.height = reader.readFloat(); + break; + case 8: + reader.readMessage(message.points, () => pb_1.Message.addToRepeatedWrapperField(message, 8, Point.deserialize(reader), Point)); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): Rect { + return Rect.deserialize(bytes); + } + } export class Platform extends pb_1.Message { #one_of_decls: number[][] = []; constructor(data?: any[] | { diff --git a/src/graphics/rect/Rect.ts b/src/graphics/rect/Rect.ts new file mode 100644 index 0000000..222707f --- /dev/null +++ b/src/graphics/rect/Rect.ts @@ -0,0 +1,86 @@ +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(); + } + 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]; + } + 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 { + 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(); + } +} diff --git a/src/graphics/rect/RectDrawAssistant.ts b/src/graphics/rect/RectDrawAssistant.ts new file mode 100644 index 0000000..15eea6a --- /dev/null +++ b/src/graphics/rect/RectDrawAssistant.ts @@ -0,0 +1,272 @@ +import { + FederatedPointerEvent, + Graphics, + Point, + IHitArea, + DisplayObject, + FederatedMouseEvent, +} from 'pixi.js'; +import { + DraggablePoint, + GraphicApp, + GraphicDrawAssistant, + GraphicInteractionPlugin, + GraphicTransformEvent, + JlDrawApp, + JlGraphic, + KeyListener, + linePoint, +} from 'src/jlgraphic'; + +import AbsorbablePoint, { + AbsorbablePosition, +} from 'src/jlgraphic/graphic/AbsorbablePosition'; +import { + ILineGraphic, + PolylineEditPlugin, + addWaySegmentingConfig, + addPolygonSegmentingPoint, + clearWayPoint, + clearWaypointsConfig, + getWaypointRangeIndex, +} 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 { + point1: Point | null = null; + point2: Point | null = null; + rectGraphic: Graphics = new Graphics(); + + // 快捷绘制 + keypListener: KeyListener = new KeyListener({ + value: 'KeyR', + global: true, + onPress: () => { + //this.graphicTemplate.hasdoor = true; + }, + }); + + 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(); + this.app.addKeyboardListener(this.keypListener); + } + unbind(): void { + super.unbind(); + this.app.removeKeyboardListener(this.keypListener); + } + + clearCache(): void { + this.rectGraphic.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.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 { + const p1 = this.point1 as Point; + const p2 = this.point2 as Point; + if (p1 !== null) { + 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.Type); + const links = rect.queryStore.queryByType(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(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 { + 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 } = getWaypointRangeIndex(linePoints, false, 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.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.Name + ); + if (lep) { + lep.hideAll(); + } + } +} From c3171654e710f868c4889a5bec719a1c8a7fee64 Mon Sep 17 00:00:00 2001 From: joylink_zhaoerwei Date: Fri, 2 Jun 2023 17:03:17 +0800 Subject: [PATCH 09/44] =?UTF-8?q?=E5=BE=AE=E8=B0=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/examples/app/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/examples/app/index.ts b/src/examples/app/index.ts index b120fa1..da432d6 100644 --- a/src/examples/app/index.ts +++ b/src/examples/app/index.ts @@ -244,9 +244,9 @@ export function loadDrawDatas(app: GraphicApp) { storage.links.forEach((link) => { datas.push(new LinkData(link)); }); - storage.Rects.forEach((rect) => { + /* storage.Rects.forEach((rect) => { datas.push(new RectData(rect)); - }); + }); */ storage.iscsFans.forEach((fan) => { datas.push(new IscsFanData(fan)); }); From 64ab0b7d00a32429df916182e39d1fededf9cddc Mon Sep 17 00:00:00 2001 From: dong <58670809@qq.com> Date: Mon, 5 Jun 2023 14:24:25 +0800 Subject: [PATCH 10/44] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=88=97=E8=BD=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/draw-app/DrawProperties.vue | 8 + .../draw-app/properties/TrainProperty.vue | 198 +++++++++++ .../draw-app/templates/TrainTemplate.vue | 69 ++++ .../protos/draw_data_storage.proto | 15 + src/examples/app/graphics/TrainInteraction.ts | 92 +++++ src/examples/app/index.ts | 20 ++ src/examples/app/protos/draw_data_storage.ts | 328 +++++++++++++++++- src/graphics/train/Train.ts | 185 ++++++++++ src/graphics/train/TrainDrawAssistant.ts | 141 ++++++++ 9 files changed, 1055 insertions(+), 1 deletion(-) create mode 100644 src/components/draw-app/properties/TrainProperty.vue create mode 100644 src/components/draw-app/templates/TrainTemplate.vue create mode 100644 src/examples/app/graphics/TrainInteraction.ts create mode 100644 src/graphics/train/Train.ts create mode 100644 src/graphics/train/TrainDrawAssistant.ts diff --git a/src/components/draw-app/DrawProperties.vue b/src/components/draw-app/DrawProperties.vue index 7fe95d0..df4f5f9 100644 --- a/src/components/draw-app/DrawProperties.vue +++ b/src/components/draw-app/DrawProperties.vue @@ -16,6 +16,9 @@ + @@ -42,6 +45,9 @@ + @@ -59,10 +65,12 @@ import CanvasProperty from './properties/CanvasProperty.vue'; import LinkProperty from './properties/LinkProperty.vue'; import PlatformProperty from './properties/PlatformProperty.vue'; import StationProperty from './properties/StationProperty.vue'; +import TrainProperty from './properties/TrainProperty.vue'; import IscsFanProperty from './properties/IscsFanProperty.vue'; import { Link } from 'src/graphics/link/Link'; import { Platform } from 'src/graphics/platform/Platform'; import { Station } from 'src/graphics/station/Station'; +import { Train } from 'src/graphics/train/Train'; import { useDrawStore } from 'src/stores/draw-store'; import { IscsFan } from 'src/graphics/iscs-fan/IscsFan'; diff --git a/src/components/draw-app/properties/TrainProperty.vue b/src/components/draw-app/properties/TrainProperty.vue new file mode 100644 index 0000000..9e6360c --- /dev/null +++ b/src/components/draw-app/properties/TrainProperty.vue @@ -0,0 +1,198 @@ + + + diff --git a/src/components/draw-app/templates/TrainTemplate.vue b/src/components/draw-app/templates/TrainTemplate.vue new file mode 100644 index 0000000..84c3cd2 --- /dev/null +++ b/src/components/draw-app/templates/TrainTemplate.vue @@ -0,0 +1,69 @@ + + + diff --git a/src/examples/app/app_message/protos/draw_data_storage.proto b/src/examples/app/app_message/protos/draw_data_storage.proto index 6b9cc35..e129790 100644 --- a/src/examples/app/app_message/protos/draw_data_storage.proto +++ b/src/examples/app/app_message/protos/draw_data_storage.proto @@ -9,6 +9,7 @@ message RtssGraphicStorage { repeated Platform Platforms = 4; repeated Station stations = 5; repeated Rect Rects = 6; + repeated Train train = 7; } message Canvas { @@ -100,6 +101,20 @@ message Station { } +message Train { + CommonInfo common = 1; + string code = 2; + string codeColor = 3; // 车号颜色 + int32 codeFontSize = 4; // 车号字体大小 + Point point = 5; // 位置坐标 + string trainDirection = 6; // 行驶方向 + bool hasBorder = 7; // 是否有边框 + int32 borderWidth = 8; // 边框线宽 + string borderColor = 9; // 边框颜色 + string headColor = 10; // 箭头颜色 + string bodyColor = 11; // 背景色 +} + message IscsFan { CommonInfo common = 1; string code = 2; diff --git a/src/examples/app/graphics/TrainInteraction.ts b/src/examples/app/graphics/TrainInteraction.ts new file mode 100644 index 0000000..db770cc --- /dev/null +++ b/src/examples/app/graphics/TrainInteraction.ts @@ -0,0 +1,92 @@ +import * as pb_1 from 'google-protobuf'; +import { IPointData } from 'pixi.js'; +import { ITrainData } from 'src/graphics/train/Train'; +import { graphicData } from '../protos/draw_data_storage'; +import { GraphicDataBase } from './GraphicDataBase'; + +export class TrainData extends GraphicDataBase implements ITrainData { + constructor(data?: graphicData.Train) { + let train; + if (!data) { + train = new graphicData.Train({ + common: GraphicDataBase.defaultCommonInfo(), + }); + } else { + train = data; + } + super(train); + } + + public get data(): graphicData.Train { + return this.getData(); + } + get code(): string { + return this.data.code; + } + set code(v: string) { + this.data.code = v; + } + get codeColor(): string { + return this.data.codeColor; + } + set codeColor(v: string) { + this.data.codeColor = v; + } + get codeFontSize(): number { + return this.data.codeFontSize; + } + set codeFontSize(v: number) { + this.data.codeFontSize = v; + } + get trainDirection(): string { + return this.data.trainDirection; + } + set trainDirection(v: string) { + this.data.trainDirection = v; + } + get hasBorder(): boolean { + return this.data.hasBorder; + } + set hasBorder(v: boolean) { + this.data.hasBorder = v; + } + get borderWidth(): number { + return this.data.borderWidth; + } + set borderWidth(v: number) { + this.data.borderWidth = v; + } + get borderColor(): string { + return this.data.borderColor; + } + set borderColor(v: string) { + this.data.borderColor = v; + } + get headColor(): string { + return this.data.headColor; + } + set headColor(v: string) { + this.data.headColor = v; + } + get bodyColor(): string { + return this.data.bodyColor; + } + set bodyColor(v: string) { + this.data.bodyColor = v; + } + get point(): IPointData { + return this.data.point; + } + set point(point: IPointData) { + this.data.point = new graphicData.Point({ x: point.x, y: point.y }); + } + clone(): TrainData { + return new TrainData(this.data.cloneMessage()); + } + copyFrom(data: TrainData): void { + pb_1.Message.copyInto(data.data, this.data); + } + eq(other: TrainData): boolean { + return pb_1.Message.equals(this.data, other.data); + } +} diff --git a/src/examples/app/index.ts b/src/examples/app/index.ts index da432d6..148f480 100644 --- a/src/examples/app/index.ts +++ b/src/examples/app/index.ts @@ -9,7 +9,9 @@ import { RectDraw } from 'src/graphics/rect/RectDrawAssistant'; import { Platform } from 'src/graphics/platform/Platform'; import { PlatformDraw } from 'src/graphics/platform/PlatformDrawAssistant'; import { Station } from 'src/graphics/station/Station'; +import { Train } from 'src/graphics/train/Train'; import { StationDraw } from 'src/graphics/station/StationDrawAssistant'; +import { TrainDraw } from 'src/graphics/train/TrainDrawAssistant'; import { CombinationKey, GraphicApp, @@ -25,6 +27,7 @@ import { LinkData } from './graphics/LinkInteraction'; import { RectData } from './graphics/RectInteraction'; import { PlatformData } from './graphics/PlatformInteraction'; import { StationData } from './graphics/StationInteraction'; +import { TrainData } from './graphics/TrainInteraction'; import { graphicData } from './protos/draw_data_storage'; export function fromStoragePoint(p: graphicData.Point): Point { @@ -112,6 +115,9 @@ export function initDrawApp(dom: HTMLElement): JlDrawApp { new StationDraw(app, () => { return new StationData(); }), + new TrainDraw(app, () => { + return new TrainData(); + }), ], }); @@ -173,6 +179,14 @@ export function initDrawApp(dom: HTMLElement): JlDrawApp { }, }) ); + app.addKeyboardListener( + new KeyListener({ + value: 'KeyT', + onPress: () => { + app.interactionPlugin(Train.Type).resume(); + }, + }) + ); app.addKeyboardListener( new KeyListener({ value: '1', @@ -223,6 +237,9 @@ export function saveDrawDatas(app: JlDrawApp) { } else if (Station.Type === g.type) { const stationData = (g as Station).saveData(); storage.stations.push((stationData as StationData).data); + } else if (Train.Type === g.type) { + const trainData = (g as Train).saveData(); + storage.train.push((trainData as TrainData).data); } }); const base64 = fromUint8Array(storage.serialize()); @@ -256,6 +273,9 @@ export function loadDrawDatas(app: GraphicApp) { storage.stations.forEach((station) => { datas.push(new StationData(station)); }); + storage.train.forEach((train) => { + datas.push(new TrainData(train)); + }); app.loadGraphic(datas); } else { app.loadGraphic([]); diff --git a/src/examples/app/protos/draw_data_storage.ts b/src/examples/app/protos/draw_data_storage.ts index 7f01476..e600536 100644 --- a/src/examples/app/protos/draw_data_storage.ts +++ b/src/examples/app/protos/draw_data_storage.ts @@ -14,9 +14,10 @@ export namespace graphicData { Platforms?: Platform[]; stations?: Station[]; Rects?: Rect[]; + train?: Train[]; }) { super(); - pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [2, 3, 4, 5, 6], this.#one_of_decls); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [2, 3, 4, 5, 6, 7], this.#one_of_decls); if (!Array.isArray(data) && typeof data == "object") { if ("canvas" in data && data.canvas != undefined) { this.canvas = data.canvas; @@ -36,6 +37,9 @@ export namespace graphicData { if ("Rects" in data && data.Rects != undefined) { this.Rects = data.Rects; } + if ("train" in data && data.train != undefined) { + this.train = data.train; + } } } get canvas() { @@ -77,6 +81,12 @@ export namespace graphicData { set Rects(value: Rect[]) { pb_1.Message.setRepeatedWrapperField(this, 6, value); } + get train() { + return pb_1.Message.getRepeatedWrapperField(this, Train, 7) as Train[]; + } + set train(value: Train[]) { + pb_1.Message.setRepeatedWrapperField(this, 7, value); + } static fromObject(data: { canvas?: ReturnType; links?: ReturnType[]; @@ -84,6 +94,7 @@ export namespace graphicData { Platforms?: ReturnType[]; stations?: ReturnType[]; Rects?: ReturnType[]; + train?: ReturnType[]; }): RtssGraphicStorage { const message = new RtssGraphicStorage({}); if (data.canvas != null) { @@ -104,6 +115,9 @@ export namespace graphicData { if (data.Rects != null) { message.Rects = data.Rects.map(item => Rect.fromObject(item)); } + if (data.train != null) { + message.train = data.train.map(item => Train.fromObject(item)); + } return message; } toObject() { @@ -114,6 +128,7 @@ export namespace graphicData { Platforms?: ReturnType[]; stations?: ReturnType[]; Rects?: ReturnType[]; + train?: ReturnType[]; } = {}; if (this.canvas != null) { data.canvas = this.canvas.toObject(); @@ -133,6 +148,9 @@ export namespace graphicData { if (this.Rects != null) { data.Rects = this.Rects.map((item: Rect) => item.toObject()); } + if (this.train != null) { + data.train = this.train.map((item: Train) => item.toObject()); + } return data; } serialize(): Uint8Array; @@ -151,6 +169,8 @@ export namespace graphicData { writer.writeRepeatedMessage(5, this.stations, (item: Station) => item.serialize(writer)); if (this.Rects.length) writer.writeRepeatedMessage(6, this.Rects, (item: Rect) => item.serialize(writer)); + if (this.train.length) + writer.writeRepeatedMessage(7, this.train, (item: Train) => item.serialize(writer)); if (!w) return writer.getResultBuffer(); } @@ -178,6 +198,9 @@ export namespace graphicData { case 6: reader.readMessage(message.Rects, () => pb_1.Message.addToRepeatedWrapperField(message, 6, Rect.deserialize(reader), Rect)); break; + case 7: + reader.readMessage(message.train, () => pb_1.Message.addToRepeatedWrapperField(message, 7, Train.deserialize(reader), Train)); + break; default: reader.skipField(); } } @@ -1706,6 +1729,309 @@ export namespace graphicData { return Station.deserialize(bytes); } } + export class Train extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + common?: CommonInfo; + code?: string; + codeColor?: string; + codeFontSize?: number; + point?: Point; + trainDirection?: string; + hasBorder?: boolean; + borderWidth?: number; + borderColor?: string; + headColor?: string; + bodyColor?: string; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("common" in data && data.common != undefined) { + this.common = data.common; + } + if ("code" in data && data.code != undefined) { + this.code = data.code; + } + if ("codeColor" in data && data.codeColor != undefined) { + this.codeColor = data.codeColor; + } + if ("codeFontSize" in data && data.codeFontSize != undefined) { + this.codeFontSize = data.codeFontSize; + } + if ("point" in data && data.point != undefined) { + this.point = data.point; + } + if ("trainDirection" in data && data.trainDirection != undefined) { + this.trainDirection = data.trainDirection; + } + if ("hasBorder" in data && data.hasBorder != undefined) { + this.hasBorder = data.hasBorder; + } + if ("borderWidth" in data && data.borderWidth != undefined) { + this.borderWidth = data.borderWidth; + } + if ("borderColor" in data && data.borderColor != undefined) { + this.borderColor = data.borderColor; + } + if ("headColor" in data && data.headColor != undefined) { + this.headColor = data.headColor; + } + if ("bodyColor" in data && data.bodyColor != undefined) { + this.bodyColor = data.bodyColor; + } + } + } + get common() { + return pb_1.Message.getWrapperField(this, CommonInfo, 1) as CommonInfo; + } + set common(value: CommonInfo) { + pb_1.Message.setWrapperField(this, 1, value); + } + get has_common() { + return pb_1.Message.getField(this, 1) != null; + } + get code() { + return pb_1.Message.getFieldWithDefault(this, 2, "") as string; + } + set code(value: string) { + pb_1.Message.setField(this, 2, value); + } + get codeColor() { + return pb_1.Message.getFieldWithDefault(this, 3, "") as string; + } + set codeColor(value: string) { + pb_1.Message.setField(this, 3, value); + } + get codeFontSize() { + return pb_1.Message.getFieldWithDefault(this, 4, 0) as number; + } + set codeFontSize(value: number) { + pb_1.Message.setField(this, 4, value); + } + get point() { + return pb_1.Message.getWrapperField(this, Point, 5) as Point; + } + set point(value: Point) { + pb_1.Message.setWrapperField(this, 5, value); + } + get has_point() { + return pb_1.Message.getField(this, 5) != null; + } + get trainDirection() { + return pb_1.Message.getFieldWithDefault(this, 6, "") as string; + } + set trainDirection(value: string) { + pb_1.Message.setField(this, 6, value); + } + get hasBorder() { + return pb_1.Message.getFieldWithDefault(this, 7, false) as boolean; + } + set hasBorder(value: boolean) { + pb_1.Message.setField(this, 7, value); + } + get borderWidth() { + return pb_1.Message.getFieldWithDefault(this, 8, 0) as number; + } + set borderWidth(value: number) { + pb_1.Message.setField(this, 8, value); + } + get borderColor() { + return pb_1.Message.getFieldWithDefault(this, 9, "") as string; + } + set borderColor(value: string) { + pb_1.Message.setField(this, 9, value); + } + get headColor() { + return pb_1.Message.getFieldWithDefault(this, 10, "") as string; + } + set headColor(value: string) { + pb_1.Message.setField(this, 10, value); + } + get bodyColor() { + return pb_1.Message.getFieldWithDefault(this, 11, "") as string; + } + set bodyColor(value: string) { + pb_1.Message.setField(this, 11, value); + } + static fromObject(data: { + common?: ReturnType; + code?: string; + codeColor?: string; + codeFontSize?: number; + point?: ReturnType; + trainDirection?: string; + hasBorder?: boolean; + borderWidth?: number; + borderColor?: string; + headColor?: string; + bodyColor?: string; + }): Train { + const message = new Train({}); + if (data.common != null) { + message.common = CommonInfo.fromObject(data.common); + } + if (data.code != null) { + message.code = data.code; + } + if (data.codeColor != null) { + message.codeColor = data.codeColor; + } + if (data.codeFontSize != null) { + message.codeFontSize = data.codeFontSize; + } + if (data.point != null) { + message.point = Point.fromObject(data.point); + } + if (data.trainDirection != null) { + message.trainDirection = data.trainDirection; + } + if (data.hasBorder != null) { + message.hasBorder = data.hasBorder; + } + if (data.borderWidth != null) { + message.borderWidth = data.borderWidth; + } + if (data.borderColor != null) { + message.borderColor = data.borderColor; + } + if (data.headColor != null) { + message.headColor = data.headColor; + } + if (data.bodyColor != null) { + message.bodyColor = data.bodyColor; + } + return message; + } + toObject() { + const data: { + common?: ReturnType; + code?: string; + codeColor?: string; + codeFontSize?: number; + point?: ReturnType; + trainDirection?: string; + hasBorder?: boolean; + borderWidth?: number; + borderColor?: string; + headColor?: string; + bodyColor?: string; + } = {}; + if (this.common != null) { + data.common = this.common.toObject(); + } + if (this.code != null) { + data.code = this.code; + } + if (this.codeColor != null) { + data.codeColor = this.codeColor; + } + if (this.codeFontSize != null) { + data.codeFontSize = this.codeFontSize; + } + if (this.point != null) { + data.point = this.point.toObject(); + } + if (this.trainDirection != null) { + data.trainDirection = this.trainDirection; + } + if (this.hasBorder != null) { + data.hasBorder = this.hasBorder; + } + if (this.borderWidth != null) { + data.borderWidth = this.borderWidth; + } + if (this.borderColor != null) { + data.borderColor = this.borderColor; + } + if (this.headColor != null) { + data.headColor = this.headColor; + } + if (this.bodyColor != null) { + data.bodyColor = this.bodyColor; + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.has_common) + writer.writeMessage(1, this.common, () => this.common.serialize(writer)); + if (this.code.length) + writer.writeString(2, this.code); + if (this.codeColor.length) + writer.writeString(3, this.codeColor); + if (this.codeFontSize != 0) + writer.writeInt32(4, this.codeFontSize); + if (this.has_point) + writer.writeMessage(5, this.point, () => this.point.serialize(writer)); + if (this.trainDirection.length) + writer.writeString(6, this.trainDirection); + if (this.hasBorder != false) + writer.writeBool(7, this.hasBorder); + if (this.borderWidth != 0) + writer.writeInt32(8, this.borderWidth); + if (this.borderColor.length) + writer.writeString(9, this.borderColor); + if (this.headColor.length) + writer.writeString(10, this.headColor); + if (this.bodyColor.length) + writer.writeString(11, this.bodyColor); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): Train { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new Train(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + reader.readMessage(message.common, () => message.common = CommonInfo.deserialize(reader)); + break; + case 2: + message.code = reader.readString(); + break; + case 3: + message.codeColor = reader.readString(); + break; + case 4: + message.codeFontSize = reader.readInt32(); + break; + case 5: + reader.readMessage(message.point, () => message.point = Point.deserialize(reader)); + break; + case 6: + message.trainDirection = reader.readString(); + break; + case 7: + message.hasBorder = reader.readBool(); + break; + case 8: + message.borderWidth = reader.readInt32(); + break; + case 9: + message.borderColor = reader.readString(); + break; + case 10: + message.headColor = reader.readString(); + break; + case 11: + message.bodyColor = reader.readString(); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): Train { + return Train.deserialize(bytes); + } + } export class IscsFan extends pb_1.Message { #one_of_decls: number[][] = []; constructor(data?: any[] | { diff --git a/src/graphics/train/Train.ts b/src/graphics/train/Train.ts new file mode 100644 index 0000000..217ac3c --- /dev/null +++ b/src/graphics/train/Train.ts @@ -0,0 +1,185 @@ +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(); + } + 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 { + 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(); + } +} diff --git a/src/graphics/train/TrainDrawAssistant.ts b/src/graphics/train/TrainDrawAssistant.ts new file mode 100644 index 0000000..bb4d479 --- /dev/null +++ b/src/graphics/train/TrainDrawAssistant.ts @@ -0,0 +1,141 @@ +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 { + 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(); + } + onRightClick(): void { + this.createAndStore(true); + } + 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 { + 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; + } +} From fb82a1339f051a7d67541087a4027c7681278869 Mon Sep 17 00:00:00 2001 From: joylink_zhaoerwei Date: Mon, 5 Jun 2023 15:56:44 +0800 Subject: [PATCH 11/44] =?UTF-8?q?=E7=9F=A9=E5=BD=A2--=E5=A4=9A=E8=BE=B9?= =?UTF-8?q?=E5=BD=A2-=E7=BB=86=E5=88=86=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/draw-app/DrawProperties.vue | 9 +++ .../draw-app/properties/RectProperty.vue | 74 ++++++++++++++++++ .../draw-app/templates/RectTemplate.vue | 76 +++++++++++++++++++ src/graphics/rect/Rect.ts | 2 +- src/graphics/rect/RectDrawAssistant.ts | 4 +- src/graphics/station/Station.ts | 1 - src/jlgraphic/plugins/GraphicEditPlugin.ts | 40 ++++++++++ 7 files changed, 202 insertions(+), 4 deletions(-) create mode 100644 src/components/draw-app/properties/RectProperty.vue create mode 100644 src/components/draw-app/templates/RectTemplate.vue diff --git a/src/components/draw-app/DrawProperties.vue b/src/components/draw-app/DrawProperties.vue index df4f5f9..6bb35e0 100644 --- a/src/components/draw-app/DrawProperties.vue +++ b/src/components/draw-app/DrawProperties.vue @@ -10,6 +10,9 @@ + @@ -39,6 +42,9 @@ + @@ -59,15 +65,18 @@ diff --git a/src/components/draw-app/templates/RectTemplate.vue b/src/components/draw-app/templates/RectTemplate.vue new file mode 100644 index 0000000..75c2ee2 --- /dev/null +++ b/src/components/draw-app/templates/RectTemplate.vue @@ -0,0 +1,76 @@ + + + diff --git a/src/graphics/rect/Rect.ts b/src/graphics/rect/Rect.ts index 222707f..5cde77a 100644 --- a/src/graphics/rect/Rect.ts +++ b/src/graphics/rect/Rect.ts @@ -48,7 +48,7 @@ export class Rect extends JlGraphic { 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]; + this.datas.points = [r1, r2, r3, r4, r1]; } const rectGraphic = this.rectGraphic; rectGraphic.clear(); diff --git a/src/graphics/rect/RectDrawAssistant.ts b/src/graphics/rect/RectDrawAssistant.ts index 15eea6a..c40293f 100644 --- a/src/graphics/rect/RectDrawAssistant.ts +++ b/src/graphics/rect/RectDrawAssistant.ts @@ -28,7 +28,7 @@ import { addPolygonSegmentingPoint, clearWayPoint, clearWaypointsConfig, - getWaypointRangeIndex, + getWayLineIndex, } from 'src/jlgraphic/plugins/GraphicEditPlugin'; import { ContextMenu } from 'src/jlgraphic/ui/ContextMenu'; @@ -240,7 +240,7 @@ export class RectPointsEditPlugin extends GraphicInteractionPlugin { addWaySegmentingConfig.handler = () => { const linePoints = rect.linePoints; const p = rect.screenToLocalPoint(e.global); - const { start, end } = getWaypointRangeIndex(linePoints, false, p); + const { start, end } = getWayLineIndex(linePoints, p); addPolygonSegmentingPoint(rect, start, end); }; clearWaypointsConfig.handler = () => { diff --git a/src/graphics/station/Station.ts b/src/graphics/station/Station.ts index e653380..974c8df 100644 --- a/src/graphics/station/Station.ts +++ b/src/graphics/station/Station.ts @@ -42,7 +42,6 @@ export class Station extends JlGraphic { codeGraph.style.fill = this.datas.codeColor; codeGraph.setVectorFontSize(this.datas.codeFontSize); codeGraph.anchor.set(0.5); - codeGraph.style.fill = this.datas.codeColor; } } diff --git a/src/jlgraphic/plugins/GraphicEditPlugin.ts b/src/jlgraphic/plugins/GraphicEditPlugin.ts index 39075ca..88a3116 100644 --- a/src/jlgraphic/plugins/GraphicEditPlugin.ts +++ b/src/jlgraphic/plugins/GraphicEditPlugin.ts @@ -20,6 +20,7 @@ import { linePoint, pointPolygon, calculateLineSegmentingPoint, + calculateDistanceFromPointToLine, } from '../utils'; import { GraphicTransformEvent, ShiftData } from './GraphicTransformPlugin'; @@ -107,6 +108,45 @@ export abstract class LineEditPlugin extends GraphicEditPlugin { abstract initEditPoints(): void; } +export function getWayLineIndex( + points: IPointData[], + p: IPointData +): { start: number; end: number } { + let start = 0; + let end = 0; + let minDistance = 0; + for (let i = 1; i < points.length; i++) { + const sp = points[i - 1]; + const ep = points[i]; + let distance = calculateDistanceFromPointToLine(sp, ep, p); + distance = Math.round(distance * 100) / 100; + if (i == 1) { + minDistance = distance; + } + if (distance == minDistance) { + const minX = Math.min(sp.x, ep.x); + const maxX = Math.max(sp.x, ep.x); + const minY = Math.min(sp.y, ep.y); + const maxY = Math.max(sp.y, ep.y); + const point = calculateFootPointFromPointToLine(sp, ep, p); + if ( + point.x >= minX && + point.x <= maxX && + point.y >= minY && + point.y <= maxY + ) { + start = i - 1; + } + } + if (distance < minDistance) { + minDistance = distance; + start = i - 1; + } + } + end = start + 1; + return { start, end }; +} + export function getWaypointRangeIndex( points: IPointData[], curve: boolean, From d541e1445b5d7ac31db855af62d1812d32b4a9ed Mon Sep 17 00:00:00 2001 From: joylink_zhaoerwei Date: Mon, 5 Jun 2023 16:03:53 +0800 Subject: [PATCH 12/44] =?UTF-8?q?=E5=BE=AE=E8=B0=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/graphics/platform/PlatformDrawAssistant.ts | 12 ------------ src/graphics/rect/RectDrawAssistant.ts | 12 ------------ src/graphics/station/StationDrawAssistant.ts | 12 ------------ 3 files changed, 36 deletions(-) diff --git a/src/graphics/platform/PlatformDrawAssistant.ts b/src/graphics/platform/PlatformDrawAssistant.ts index e5d24df..fb6b17a 100644 --- a/src/graphics/platform/PlatformDrawAssistant.ts +++ b/src/graphics/platform/PlatformDrawAssistant.ts @@ -10,7 +10,6 @@ import { GraphicInteractionPlugin, JlDrawApp, JlGraphic, - KeyListener, getRectangleCenter, } from 'src/jlgraphic'; @@ -28,15 +27,6 @@ export class PlatformDraw extends GraphicDrawAssistant< platformGraphic: Graphics = new Graphics(); doorGraphic: Graphics = new Graphics(); - // 快捷绘制 - keypListener: KeyListener = new KeyListener({ - value: 'KeyP', - global: true, - onPress: () => { - this.graphicTemplate.hasdoor = true; - }, - }); - constructor(app: JlDrawApp, createData: () => IPlatformData) { super( app, @@ -53,11 +43,9 @@ export class PlatformDraw extends GraphicDrawAssistant< bind(): void { super.bind(); - this.app.addKeyboardListener(this.keypListener); } unbind(): void { super.unbind(); - this.app.removeKeyboardListener(this.keypListener); } clearCache(): void { diff --git a/src/graphics/rect/RectDrawAssistant.ts b/src/graphics/rect/RectDrawAssistant.ts index c40293f..e186ce4 100644 --- a/src/graphics/rect/RectDrawAssistant.ts +++ b/src/graphics/rect/RectDrawAssistant.ts @@ -14,7 +14,6 @@ import { GraphicTransformEvent, JlDrawApp, JlGraphic, - KeyListener, linePoint, } from 'src/jlgraphic'; @@ -44,15 +43,6 @@ export class RectDraw extends GraphicDrawAssistant { point2: Point | null = null; rectGraphic: Graphics = new Graphics(); - // 快捷绘制 - keypListener: KeyListener = new KeyListener({ - value: 'KeyR', - global: true, - onPress: () => { - //this.graphicTemplate.hasdoor = true; - }, - }); - constructor(app: JlDrawApp, createData: () => IRectData) { super(app, new RectTemplate(), createData, Rect.Type, '站台Rect'); this.container.addChild(this.rectGraphic); @@ -61,11 +51,9 @@ export class RectDraw extends GraphicDrawAssistant { bind(): void { super.bind(); - this.app.addKeyboardListener(this.keypListener); } unbind(): void { super.unbind(); - this.app.removeKeyboardListener(this.keypListener); } clearCache(): void { diff --git a/src/graphics/station/StationDrawAssistant.ts b/src/graphics/station/StationDrawAssistant.ts index bee53ae..2d73efd 100644 --- a/src/graphics/station/StationDrawAssistant.ts +++ b/src/graphics/station/StationDrawAssistant.ts @@ -4,7 +4,6 @@ import { GraphicInteractionPlugin, JlDrawApp, JlGraphic, - KeyListener, VectorText, } from 'src/jlgraphic'; @@ -21,15 +20,6 @@ export class StationDraw extends GraphicDrawAssistant< point: Point = new Point(0, 0); codeGraph: VectorText = new VectorText(''); - // 快捷绘制 - keypListener: KeyListener = new KeyListener({ - value: 'KeyO', - global: true, - onPress: () => { - //this.graphicTemplate.hasdoor = true; - }, - }); - constructor(app: JlDrawApp, createData: () => IStationData) { super(app, new StationTemplate(), createData, Station.Type, '车站Station'); this.container.addChild(this.codeGraph); @@ -38,11 +28,9 @@ export class StationDraw extends GraphicDrawAssistant< bind(): void { super.bind(); - this.app.addKeyboardListener(this.keypListener); } unbind(): void { super.unbind(); - this.app.removeKeyboardListener(this.keypListener); } clearCache(): void { From 4131233113f542df4a234617177a2fa9ff2864d8 Mon Sep 17 00:00:00 2001 From: joylink_zhaoerwei Date: Mon, 5 Jun 2023 17:42:42 +0800 Subject: [PATCH 13/44] =?UTF-8?q?=E5=BE=AE=E8=B0=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/examples/app/index.ts | 4 ++-- src/graphics/rect/RectDrawAssistant.ts | 20 +++++++++++--------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/examples/app/index.ts b/src/examples/app/index.ts index 148f480..744e051 100644 --- a/src/examples/app/index.ts +++ b/src/examples/app/index.ts @@ -261,9 +261,9 @@ export function loadDrawDatas(app: GraphicApp) { storage.links.forEach((link) => { datas.push(new LinkData(link)); }); - /* storage.Rects.forEach((rect) => { + storage.Rects.forEach((rect) => { datas.push(new RectData(rect)); - }); */ + }); storage.iscsFans.forEach((fan) => { datas.push(new IscsFanData(fan)); }); diff --git a/src/graphics/rect/RectDrawAssistant.ts b/src/graphics/rect/RectDrawAssistant.ts index e186ce4..a8ed20e 100644 --- a/src/graphics/rect/RectDrawAssistant.ts +++ b/src/graphics/rect/RectDrawAssistant.ts @@ -93,17 +93,19 @@ export class RectDraw extends GraphicDrawAssistant { 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; - if (p1 !== null) { - 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; - } + 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; } } From 528873959ed9ed3d62c659347174ba6e55bec58f Mon Sep 17 00:00:00 2001 From: joylink_zhaoerwei Date: Tue, 6 Jun 2023 11:02:29 +0800 Subject: [PATCH 14/44] =?UTF-8?q?=E8=BD=A6=E7=AB=99=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E5=9C=86=E5=9C=88--=E7=BA=BF=E7=BD=91=E5=9B=BE=E5=A4=87?= =?UTF-8?q?=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../draw-app/properties/StationProperty.vue | 88 ++++++++- .../protos/draw_data_storage.proto | 13 +- .../app/graphics/StationInteraction.ts | 36 ++++ src/examples/app/protos/draw_data_storage.ts | 167 ++++++++++++++++-- src/graphics/station/Station.ts | 44 ++++- src/graphics/station/StationDrawAssistant.ts | 6 + 6 files changed, 335 insertions(+), 19 deletions(-) diff --git a/src/components/draw-app/properties/StationProperty.vue b/src/components/draw-app/properties/StationProperty.vue index 0b763fe..438cff9 100644 --- a/src/components/draw-app/properties/StationProperty.vue +++ b/src/components/draw-app/properties/StationProperty.vue @@ -41,6 +41,79 @@ + + + + + + + + + @@ -48,10 +121,20 @@ import { StationData } from 'src/examples/app/graphics/StationInteraction'; import { Station } from 'src/graphics/station/Station'; import { useDrawStore } from 'src/stores/draw-store'; -import { onMounted, reactive, watch } from 'vue'; +import { onMounted, reactive, ref, watch } from 'vue'; const drawStore = useDrawStore(); const stationModel = reactive(new StationData()); +const hasCircle = ref('是'); +const optionsCircle = ['是', '否']; +enum showSelect { + 是 = 'true', + 否 = 'false', +} +enum showSelectData { + true = '是', + false = '否', +} drawStore.$subscribe; watch( @@ -59,6 +142,7 @@ watch( (val) => { if (val && val.type == Station.Type) { stationModel.copyFrom(val.saveData() as StationData); + hasCircle.value = (showSelectData as never)[stationModel.hasCircle + '']; } } ); @@ -67,10 +151,12 @@ onMounted(() => { const station = drawStore.selectedGraphic as Station; if (station) { stationModel.copyFrom(station.saveData()); + hasCircle.value = (showSelectData as never)[stationModel.hasCircle + '']; } }); function onUpdate() { + stationModel.hasCircle = JSON.parse((showSelect as never)[hasCircle.value]); const station = drawStore.selectedGraphic as Station; if (station) { drawStore.getDrawApp().updateGraphicAndRecord(station, stationModel); diff --git a/src/examples/app/app_message/protos/draw_data_storage.proto b/src/examples/app/app_message/protos/draw_data_storage.proto index e129790..abe7512 100644 --- a/src/examples/app/app_message/protos/draw_data_storage.proto +++ b/src/examples/app/app_message/protos/draw_data_storage.proto @@ -95,10 +95,15 @@ message Platform { message Station { CommonInfo common = 1; string code = 2; - string codeColor = 3; // 车站字体颜色 - int32 codeFontSize = 4; // 车站字体大小 - Point point = 5; // 位置坐标 - + bool hasCircle = 3; // 是否有圆圈--线网图 + int32 radius = 4; // 半径 + int32 borderWidth = 5; // 边框线宽 + string borderColor = 6; // 边框颜色 + string fillColor = 7; // 圆填充颜色 + string codeColor = 8; // 车站字体颜色 + int32 codeFontSize = 9; // 车站字体大小 + Point point = 10; // 位置坐标 + Point circlePoint = 11; // 位置坐标 } message Train { diff --git a/src/examples/app/graphics/StationInteraction.ts b/src/examples/app/graphics/StationInteraction.ts index 0b4c467..9022621 100644 --- a/src/examples/app/graphics/StationInteraction.ts +++ b/src/examples/app/graphics/StationInteraction.ts @@ -26,6 +26,36 @@ export class StationData extends GraphicDataBase implements IStationData { set code(v: string) { this.data.code = v; } + get hasCircle(): boolean { + return this.data.hasCircle; + } + set hasCircle(v: boolean) { + this.data.hasCircle = v; + } + get radius(): number { + return this.data.radius; + } + set radius(v: number) { + this.data.radius = v; + } + get borderWidth(): number { + return this.data.borderWidth; + } + set borderWidth(v: number) { + this.data.borderWidth = v; + } + get borderColor(): string { + return this.data.borderColor; + } + set borderColor(v: string) { + this.data.borderColor = v; + } + get fillColor(): string { + return this.data.fillColor; + } + set fillColor(v: string) { + this.data.fillColor = v; + } get codeColor(): string { return this.data.codeColor; } @@ -44,6 +74,12 @@ export class StationData extends GraphicDataBase implements IStationData { set point(point: IPointData) { this.data.point = new graphicData.Point({ x: point.x, y: point.y }); } + get circlePoint(): IPointData { + return this.data.circlePoint; + } + set circlePoint(point: IPointData) { + this.data.circlePoint = new graphicData.Point({ x: point.x, y: point.y }); + } clone(): StationData { return new StationData(this.data.cloneMessage()); } diff --git a/src/examples/app/protos/draw_data_storage.ts b/src/examples/app/protos/draw_data_storage.ts index e600536..1894ee2 100644 --- a/src/examples/app/protos/draw_data_storage.ts +++ b/src/examples/app/protos/draw_data_storage.ts @@ -1569,9 +1569,15 @@ export namespace graphicData { constructor(data?: any[] | { common?: CommonInfo; code?: string; + hasCircle?: boolean; + radius?: number; + borderWidth?: number; + borderColor?: string; + fillColor?: string; codeColor?: string; codeFontSize?: number; point?: Point; + circlePoint?: Point; }) { super(); pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); @@ -1582,6 +1588,21 @@ export namespace graphicData { if ("code" in data && data.code != undefined) { this.code = data.code; } + if ("hasCircle" in data && data.hasCircle != undefined) { + this.hasCircle = data.hasCircle; + } + if ("radius" in data && data.radius != undefined) { + this.radius = data.radius; + } + if ("borderWidth" in data && data.borderWidth != undefined) { + this.borderWidth = data.borderWidth; + } + if ("borderColor" in data && data.borderColor != undefined) { + this.borderColor = data.borderColor; + } + if ("fillColor" in data && data.fillColor != undefined) { + this.fillColor = data.fillColor; + } if ("codeColor" in data && data.codeColor != undefined) { this.codeColor = data.codeColor; } @@ -1591,6 +1612,9 @@ export namespace graphicData { if ("point" in data && data.point != undefined) { this.point = data.point; } + if ("circlePoint" in data && data.circlePoint != undefined) { + this.circlePoint = data.circlePoint; + } } } get common() { @@ -1608,33 +1632,78 @@ export namespace graphicData { set code(value: string) { pb_1.Message.setField(this, 2, value); } - get codeColor() { - return pb_1.Message.getFieldWithDefault(this, 3, "") as string; + get hasCircle() { + return pb_1.Message.getFieldWithDefault(this, 3, false) as boolean; } - set codeColor(value: string) { + set hasCircle(value: boolean) { pb_1.Message.setField(this, 3, value); } - get codeFontSize() { + get radius() { return pb_1.Message.getFieldWithDefault(this, 4, 0) as number; } - set codeFontSize(value: number) { + set radius(value: number) { pb_1.Message.setField(this, 4, value); } + get borderWidth() { + return pb_1.Message.getFieldWithDefault(this, 5, 0) as number; + } + set borderWidth(value: number) { + pb_1.Message.setField(this, 5, value); + } + get borderColor() { + return pb_1.Message.getFieldWithDefault(this, 6, "") as string; + } + set borderColor(value: string) { + pb_1.Message.setField(this, 6, value); + } + get fillColor() { + return pb_1.Message.getFieldWithDefault(this, 7, "") as string; + } + set fillColor(value: string) { + pb_1.Message.setField(this, 7, value); + } + get codeColor() { + return pb_1.Message.getFieldWithDefault(this, 8, "") as string; + } + set codeColor(value: string) { + pb_1.Message.setField(this, 8, value); + } + get codeFontSize() { + return pb_1.Message.getFieldWithDefault(this, 9, 0) as number; + } + set codeFontSize(value: number) { + pb_1.Message.setField(this, 9, value); + } get point() { - return pb_1.Message.getWrapperField(this, Point, 5) as Point; + return pb_1.Message.getWrapperField(this, Point, 10) as Point; } set point(value: Point) { - pb_1.Message.setWrapperField(this, 5, value); + pb_1.Message.setWrapperField(this, 10, value); } get has_point() { - return pb_1.Message.getField(this, 5) != null; + return pb_1.Message.getField(this, 10) != null; + } + get circlePoint() { + return pb_1.Message.getWrapperField(this, Point, 11) as Point; + } + set circlePoint(value: Point) { + pb_1.Message.setWrapperField(this, 11, value); + } + get has_circlePoint() { + return pb_1.Message.getField(this, 11) != null; } static fromObject(data: { common?: ReturnType; code?: string; + hasCircle?: boolean; + radius?: number; + borderWidth?: number; + borderColor?: string; + fillColor?: string; codeColor?: string; codeFontSize?: number; point?: ReturnType; + circlePoint?: ReturnType; }): Station { const message = new Station({}); if (data.common != null) { @@ -1643,6 +1712,21 @@ export namespace graphicData { if (data.code != null) { message.code = data.code; } + if (data.hasCircle != null) { + message.hasCircle = data.hasCircle; + } + if (data.radius != null) { + message.radius = data.radius; + } + if (data.borderWidth != null) { + message.borderWidth = data.borderWidth; + } + if (data.borderColor != null) { + message.borderColor = data.borderColor; + } + if (data.fillColor != null) { + message.fillColor = data.fillColor; + } if (data.codeColor != null) { message.codeColor = data.codeColor; } @@ -1652,15 +1736,24 @@ export namespace graphicData { if (data.point != null) { message.point = Point.fromObject(data.point); } + if (data.circlePoint != null) { + message.circlePoint = Point.fromObject(data.circlePoint); + } return message; } toObject() { const data: { common?: ReturnType; code?: string; + hasCircle?: boolean; + radius?: number; + borderWidth?: number; + borderColor?: string; + fillColor?: string; codeColor?: string; codeFontSize?: number; point?: ReturnType; + circlePoint?: ReturnType; } = {}; if (this.common != null) { data.common = this.common.toObject(); @@ -1668,6 +1761,21 @@ export namespace graphicData { if (this.code != null) { data.code = this.code; } + if (this.hasCircle != null) { + data.hasCircle = this.hasCircle; + } + if (this.radius != null) { + data.radius = this.radius; + } + if (this.borderWidth != null) { + data.borderWidth = this.borderWidth; + } + if (this.borderColor != null) { + data.borderColor = this.borderColor; + } + if (this.fillColor != null) { + data.fillColor = this.fillColor; + } if (this.codeColor != null) { data.codeColor = this.codeColor; } @@ -1677,6 +1785,9 @@ export namespace graphicData { if (this.point != null) { data.point = this.point.toObject(); } + if (this.circlePoint != null) { + data.circlePoint = this.circlePoint.toObject(); + } return data; } serialize(): Uint8Array; @@ -1687,12 +1798,24 @@ export namespace graphicData { writer.writeMessage(1, this.common, () => this.common.serialize(writer)); if (this.code.length) writer.writeString(2, this.code); + if (this.hasCircle != false) + writer.writeBool(3, this.hasCircle); + if (this.radius != 0) + writer.writeInt32(4, this.radius); + if (this.borderWidth != 0) + writer.writeInt32(5, this.borderWidth); + if (this.borderColor.length) + writer.writeString(6, this.borderColor); + if (this.fillColor.length) + writer.writeString(7, this.fillColor); if (this.codeColor.length) - writer.writeString(3, this.codeColor); + writer.writeString(8, this.codeColor); if (this.codeFontSize != 0) - writer.writeInt32(4, this.codeFontSize); + writer.writeInt32(9, this.codeFontSize); if (this.has_point) - writer.writeMessage(5, this.point, () => this.point.serialize(writer)); + writer.writeMessage(10, this.point, () => this.point.serialize(writer)); + if (this.has_circlePoint) + writer.writeMessage(11, this.circlePoint, () => this.circlePoint.serialize(writer)); if (!w) return writer.getResultBuffer(); } @@ -1709,14 +1832,32 @@ export namespace graphicData { message.code = reader.readString(); break; case 3: - message.codeColor = reader.readString(); + message.hasCircle = reader.readBool(); break; case 4: - message.codeFontSize = reader.readInt32(); + message.radius = reader.readInt32(); break; case 5: + message.borderWidth = reader.readInt32(); + break; + case 6: + message.borderColor = reader.readString(); + break; + case 7: + message.fillColor = reader.readString(); + break; + case 8: + message.codeColor = reader.readString(); + break; + case 9: + message.codeFontSize = reader.readInt32(); + break; + case 10: reader.readMessage(message.point, () => message.point = Point.deserialize(reader)); break; + case 11: + reader.readMessage(message.circlePoint, () => message.circlePoint = Point.deserialize(reader)); + break; default: reader.skipField(); } } diff --git a/src/graphics/station/Station.ts b/src/graphics/station/Station.ts index 974c8df..8e94ae7 100644 --- a/src/graphics/station/Station.ts +++ b/src/graphics/station/Station.ts @@ -1,4 +1,4 @@ -import { IPointData } from 'pixi.js'; +import { Color, Graphics, IPointData, Point } from 'pixi.js'; import { GraphicData, JlGraphic, @@ -9,12 +9,24 @@ import { 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; @@ -23,15 +35,19 @@ export interface IStationData extends GraphicData { 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(); } doRepaint(): void { + this.circleGraphic.clear(); this.position.set(this.datas.point.x, this.datas.point.y); const codeGraph = this.codeGraph; if (this.datas.code == '') { @@ -42,16 +58,42 @@ export class Station extends JlGraphic { 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 { + 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(); diff --git a/src/graphics/station/StationDrawAssistant.ts b/src/graphics/station/StationDrawAssistant.ts index 2d73efd..9776752 100644 --- a/src/graphics/station/StationDrawAssistant.ts +++ b/src/graphics/station/StationDrawAssistant.ts @@ -57,8 +57,14 @@ export class StationDraw extends GraphicDrawAssistant< 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; } } From 7789ad9dc210c3c5c61bbb7e5b507b518f0abcf5 Mon Sep 17 00:00:00 2001 From: joylink_zhaoerwei Date: Tue, 6 Jun 2023 15:05:30 +0800 Subject: [PATCH 15/44] =?UTF-8?q?=E8=BD=A6=E7=AB=99--=E5=9C=86=E5=9C=88?= =?UTF-8?q?=E4=BD=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../draw-app/properties/StationProperty.vue | 163 +++++++++++------- 1 file changed, 99 insertions(+), 64 deletions(-) diff --git a/src/components/draw-app/properties/StationProperty.vue b/src/components/draw-app/properties/StationProperty.vue index 438cff9..3699cf0 100644 --- a/src/components/draw-app/properties/StationProperty.vue +++ b/src/components/draw-app/properties/StationProperty.vue @@ -48,72 +48,107 @@ :options="optionsCircle" label="是否有圆圈" /> - - - - - - - - + + + + + + + + + + + + From e7d765d8a7ec3a3444876af2da98055779318702 Mon Sep 17 00:00:00 2001 From: fan Date: Tue, 6 Jun 2023 15:43:41 +0800 Subject: [PATCH 16/44] =?UTF-8?q?=E4=BF=A1=E5=8F=B7=E6=9C=BA=E4=BF=AE?= =?UTF-8?q?=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/draw-app/DrawProperties.vue | 5 + .../draw-app/properties/SignalProperty.vue | 57 +++++ .../protos/draw_data_storage.proto | 10 + .../app/graphics/SignalInteraction.ts | 62 +++++ src/examples/app/index.ts | 20 ++ src/examples/app/protos/draw_data_storage.ts | 213 +++++++++++++++++- src/graphics/signal/Signal.ts | 192 ++++++++++++++++ src/graphics/signal/SignalDrawAssistant.ts | 173 ++++++++++++++ yarn.lock | 5 + 9 files changed, 736 insertions(+), 1 deletion(-) create mode 100644 src/components/draw-app/properties/SignalProperty.vue create mode 100644 src/examples/app/graphics/SignalInteraction.ts create mode 100644 src/graphics/signal/SignalDrawAssistant.ts diff --git a/src/components/draw-app/DrawProperties.vue b/src/components/draw-app/DrawProperties.vue index 7fe95d0..552573c 100644 --- a/src/components/draw-app/DrawProperties.vue +++ b/src/components/draw-app/DrawProperties.vue @@ -45,6 +45,9 @@ + @@ -60,11 +63,13 @@ import LinkProperty from './properties/LinkProperty.vue'; import PlatformProperty from './properties/PlatformProperty.vue'; import StationProperty from './properties/StationProperty.vue'; import IscsFanProperty from './properties/IscsFanProperty.vue'; +import SignalProperty from './properties/SignalProperty.vue'; import { Link } from 'src/graphics/link/Link'; import { Platform } from 'src/graphics/platform/Platform'; import { Station } from 'src/graphics/station/Station'; import { useDrawStore } from 'src/stores/draw-store'; import { IscsFan } from 'src/graphics/iscs-fan/IscsFan'; +import { Signal } from 'src/graphics/signal/Signal'; const drawStore = useDrawStore(); diff --git a/src/components/draw-app/properties/SignalProperty.vue b/src/components/draw-app/properties/SignalProperty.vue new file mode 100644 index 0000000..3e3362e --- /dev/null +++ b/src/components/draw-app/properties/SignalProperty.vue @@ -0,0 +1,57 @@ + + + diff --git a/src/examples/app/app_message/protos/draw_data_storage.proto b/src/examples/app/app_message/protos/draw_data_storage.proto index b13dca4..8573d4f 100644 --- a/src/examples/app/app_message/protos/draw_data_storage.proto +++ b/src/examples/app/app_message/protos/draw_data_storage.proto @@ -8,6 +8,7 @@ message RtssGraphicStorage { repeated IscsFan iscsFans = 3; repeated Platform Platforms = 4; repeated Station stations = 5; + repeated Signal signals = 6; } message Canvas { @@ -94,3 +95,12 @@ message IscsFan { } message Turnout {} + +message Signal { + CommonInfo common = 1; + string code = 2; + string codeColor = 3; // 信号机字体颜色 + int32 codeFontSize = 4; // 信号机字体大小 + Point point = 5; // 位置坐标 + string direction = 6; //信号机朝向 +} diff --git a/src/examples/app/graphics/SignalInteraction.ts b/src/examples/app/graphics/SignalInteraction.ts new file mode 100644 index 0000000..6ff2540 --- /dev/null +++ b/src/examples/app/graphics/SignalInteraction.ts @@ -0,0 +1,62 @@ +import * as pb_1 from 'google-protobuf'; +import { IPointData } from 'pixi.js'; +import { ISignalData } from 'src/graphics/signal/Signal'; +import { graphicData } from '../protos/draw_data_storage'; +import { GraphicDataBase } from './GraphicDataBase'; + +export class SignalData extends GraphicDataBase implements ISignalData { + constructor(data?: graphicData.Signal) { + let signal; + if (!data) { + signal = new graphicData.Signal({ + common: GraphicDataBase.defaultCommonInfo(), + }); + } else { + signal = data; + } + super(signal); + } + + public get data(): graphicData.Signal { + return this.getData(); + } + get code(): string { + return this.data.code; + } + set code(v: string) { + this.data.code = v; + } + get codeColor(): string { + return this.data.codeColor; + } + set codeColor(v: string) { + this.data.codeColor = v; + } + get codeFontSize(): number { + return this.data.codeFontSize; + } + set codeFontSize(v: number) { + this.data.codeFontSize = v; + } + get point(): IPointData { + return this.data.point; + } + set point(point: IPointData) { + this.data.point = new graphicData.Point({ x: point.x, y: point.y }); + } + get direction(): string { + return this.data.direction; + } + set direction(v: string) { + this.data.direction = v; + } + clone(): SignalData { + return new SignalData(this.data.cloneMessage()); + } + copyFrom(data: SignalData): void { + pb_1.Message.copyInto(data.data, this.data); + } + eq(other: SignalData): boolean { + return pb_1.Message.equals(this.data, other.data); + } +} diff --git a/src/examples/app/index.ts b/src/examples/app/index.ts index 3dcc8f2..e2d89cf 100644 --- a/src/examples/app/index.ts +++ b/src/examples/app/index.ts @@ -8,6 +8,8 @@ import { Platform } from 'src/graphics/platform/Platform'; import { PlatformDraw } from 'src/graphics/platform/PlatformDrawAssistant'; import { Station } from 'src/graphics/station/Station'; import { StationDraw } from 'src/graphics/station/StationDrawAssistant'; +import { Signal } from 'src/graphics/signal/Signal'; +import { SignalDraw } from 'src/graphics/signal/SignalDrawAssistant'; import { CombinationKey, GraphicApp, @@ -22,6 +24,7 @@ import { IscsFanData } from './graphics/IscsFanInteraction'; import { LinkData } from './graphics/LinkInteraction'; import { PlatformData } from './graphics/PlatformInteraction'; import { StationData } from './graphics/StationInteraction'; +import { SignalData } from './graphics/SignalInteraction'; import { graphicData } from './protos/draw_data_storage'; export function fromStoragePoint(p: graphicData.Point): Point { @@ -106,6 +109,9 @@ export function initDrawApp(dom: HTMLElement): JlDrawApp { new StationDraw(app, () => { return new StationData(); }), + new SignalDraw(app, () => { + return new SignalData(); + }), ], }); @@ -159,6 +165,14 @@ export function initDrawApp(dom: HTMLElement): JlDrawApp { }, }) ); + app.addKeyboardListener( + new KeyListener({ + value: 'KeyH', + onPress: () => { + app.interactionPlugin(Signal.Type).resume(); + }, + }) + ); app.addKeyboardListener( new KeyListener({ value: '1', @@ -206,6 +220,9 @@ export function saveDrawDatas(app: JlDrawApp) { } else if (Station.Type === g.type) { const stationData = (g as Station).saveData(); storage.stations.push((stationData as StationData).data); + } else if (Signal.Type === g.type) { + const signalData = (g as Signal).saveData(); + storage.signals.push((signalData as SignalData).data); } }); const base64 = fromUint8Array(storage.serialize()); @@ -236,6 +253,9 @@ export function loadDrawDatas(app: GraphicApp) { storage.stations.forEach((station) => { datas.push(new StationData(station)); }); + storage.signals.forEach((signal) => { + datas.push(new SignalData(signal)); + }); app.loadGraphic(datas); } else { app.loadGraphic([]); diff --git a/src/examples/app/protos/draw_data_storage.ts b/src/examples/app/protos/draw_data_storage.ts index 7690882..72fac27 100644 --- a/src/examples/app/protos/draw_data_storage.ts +++ b/src/examples/app/protos/draw_data_storage.ts @@ -13,9 +13,10 @@ export namespace graphicData { iscsFans?: IscsFan[]; Platforms?: Platform[]; stations?: Station[]; + signals?: Signal[]; }) { super(); - pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [2, 3, 4, 5], this.#one_of_decls); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [2, 3, 4, 5, 6], this.#one_of_decls); if (!Array.isArray(data) && typeof data == "object") { if ("canvas" in data && data.canvas != undefined) { this.canvas = data.canvas; @@ -32,6 +33,9 @@ export namespace graphicData { if ("stations" in data && data.stations != undefined) { this.stations = data.stations; } + if ("signals" in data && data.signals != undefined) { + this.signals = data.signals; + } } } get canvas() { @@ -67,12 +71,19 @@ export namespace graphicData { set stations(value: Station[]) { pb_1.Message.setRepeatedWrapperField(this, 5, value); } + get signals() { + return pb_1.Message.getRepeatedWrapperField(this, Signal, 6) as Signal[]; + } + set signals(value: Signal[]) { + pb_1.Message.setRepeatedWrapperField(this, 6, value); + } static fromObject(data: { canvas?: ReturnType; links?: ReturnType[]; iscsFans?: ReturnType[]; Platforms?: ReturnType[]; stations?: ReturnType[]; + signals?: ReturnType[]; }): RtssGraphicStorage { const message = new RtssGraphicStorage({}); if (data.canvas != null) { @@ -90,6 +101,9 @@ export namespace graphicData { if (data.stations != null) { message.stations = data.stations.map(item => Station.fromObject(item)); } + if (data.signals != null) { + message.signals = data.signals.map(item => Signal.fromObject(item)); + } return message; } toObject() { @@ -99,6 +113,7 @@ export namespace graphicData { iscsFans?: ReturnType[]; Platforms?: ReturnType[]; stations?: ReturnType[]; + signals?: ReturnType[]; } = {}; if (this.canvas != null) { data.canvas = this.canvas.toObject(); @@ -115,6 +130,9 @@ export namespace graphicData { if (this.stations != null) { data.stations = this.stations.map((item: Station) => item.toObject()); } + if (this.signals != null) { + data.signals = this.signals.map((item: Signal) => item.toObject()); + } return data; } serialize(): Uint8Array; @@ -131,6 +149,8 @@ export namespace graphicData { writer.writeRepeatedMessage(4, this.Platforms, (item: Platform) => item.serialize(writer)); if (this.stations.length) writer.writeRepeatedMessage(5, this.stations, (item: Station) => item.serialize(writer)); + if (this.signals.length) + writer.writeRepeatedMessage(6, this.signals, (item: Signal) => item.serialize(writer)); if (!w) return writer.getResultBuffer(); } @@ -155,6 +175,9 @@ export namespace graphicData { case 5: reader.readMessage(message.stations, () => pb_1.Message.addToRepeatedWrapperField(message, 5, Station.deserialize(reader), Station)); break; + case 6: + reader.readMessage(message.signals, () => pb_1.Message.addToRepeatedWrapperField(message, 6, Signal.deserialize(reader), Signal)); + break; default: reader.skipField(); } } @@ -1582,4 +1605,192 @@ export namespace graphicData { return Turnout.deserialize(bytes); } } + export class Signal extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + common?: CommonInfo; + code?: string; + codeColor?: string; + codeFontSize?: number; + point?: Point; + direction?: string; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("common" in data && data.common != undefined) { + this.common = data.common; + } + if ("code" in data && data.code != undefined) { + this.code = data.code; + } + if ("codeColor" in data && data.codeColor != undefined) { + this.codeColor = data.codeColor; + } + if ("codeFontSize" in data && data.codeFontSize != undefined) { + this.codeFontSize = data.codeFontSize; + } + if ("point" in data && data.point != undefined) { + this.point = data.point; + } + if ("direction" in data && data.direction != undefined) { + this.direction = data.direction; + } + } + } + get common() { + return pb_1.Message.getWrapperField(this, CommonInfo, 1) as CommonInfo; + } + set common(value: CommonInfo) { + pb_1.Message.setWrapperField(this, 1, value); + } + get has_common() { + return pb_1.Message.getField(this, 1) != null; + } + get code() { + return pb_1.Message.getFieldWithDefault(this, 2, "") as string; + } + set code(value: string) { + pb_1.Message.setField(this, 2, value); + } + get codeColor() { + return pb_1.Message.getFieldWithDefault(this, 3, "") as string; + } + set codeColor(value: string) { + pb_1.Message.setField(this, 3, value); + } + get codeFontSize() { + return pb_1.Message.getFieldWithDefault(this, 4, 0) as number; + } + set codeFontSize(value: number) { + pb_1.Message.setField(this, 4, value); + } + get point() { + return pb_1.Message.getWrapperField(this, Point, 5) as Point; + } + set point(value: Point) { + pb_1.Message.setWrapperField(this, 5, value); + } + get has_point() { + return pb_1.Message.getField(this, 5) != null; + } + get direction() { + return pb_1.Message.getFieldWithDefault(this, 6, "") as string; + } + set direction(value: string) { + pb_1.Message.setField(this, 6, value); + } + static fromObject(data: { + common?: ReturnType; + code?: string; + codeColor?: string; + codeFontSize?: number; + point?: ReturnType; + direction?: string; + }): Signal { + const message = new Signal({}); + if (data.common != null) { + message.common = CommonInfo.fromObject(data.common); + } + if (data.code != null) { + message.code = data.code; + } + if (data.codeColor != null) { + message.codeColor = data.codeColor; + } + if (data.codeFontSize != null) { + message.codeFontSize = data.codeFontSize; + } + if (data.point != null) { + message.point = Point.fromObject(data.point); + } + if (data.direction != null) { + message.direction = data.direction; + } + return message; + } + toObject() { + const data: { + common?: ReturnType; + code?: string; + codeColor?: string; + codeFontSize?: number; + point?: ReturnType; + direction?: string; + } = {}; + if (this.common != null) { + data.common = this.common.toObject(); + } + if (this.code != null) { + data.code = this.code; + } + if (this.codeColor != null) { + data.codeColor = this.codeColor; + } + if (this.codeFontSize != null) { + data.codeFontSize = this.codeFontSize; + } + if (this.point != null) { + data.point = this.point.toObject(); + } + if (this.direction != null) { + data.direction = this.direction; + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.has_common) + writer.writeMessage(1, this.common, () => this.common.serialize(writer)); + if (this.code.length) + writer.writeString(2, this.code); + if (this.codeColor.length) + writer.writeString(3, this.codeColor); + if (this.codeFontSize != 0) + writer.writeInt32(4, this.codeFontSize); + if (this.has_point) + writer.writeMessage(5, this.point, () => this.point.serialize(writer)); + if (this.direction.length) + writer.writeString(6, this.direction); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): Signal { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new Signal(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + reader.readMessage(message.common, () => message.common = CommonInfo.deserialize(reader)); + break; + case 2: + message.code = reader.readString(); + break; + case 3: + message.codeColor = reader.readString(); + break; + case 4: + message.codeFontSize = reader.readInt32(); + break; + case 5: + reader.readMessage(message.point, () => message.point = Point.deserialize(reader)); + break; + case 6: + message.direction = reader.readString(); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): Signal { + return Signal.deserialize(bytes); + } + } } diff --git a/src/graphics/signal/Signal.ts b/src/graphics/signal/Signal.ts index e69de29..edabfb3 100644 --- a/src/graphics/signal/Signal.ts +++ b/src/graphics/signal/Signal.ts @@ -0,0 +1,192 @@ +import { IPointData, Graphics, Color } from 'pixi.js'; +import { + GraphicData, + JlGraphic, + JlGraphicTemplate, + VectorText, +} from 'src/jlgraphic'; + +export interface ISignalData extends GraphicData { + get code(): string; // 编号 + set code(v: string); + get codeColor(): string; + set codeColor(v: string); + get codeFontSize(): number; + set codeFontSize(v: number); + get point(): IPointData; + set point(point: IPointData); + get direction(): string; + set direction(v: string); + clone(): ISignalData; + copyFrom(data: ISignalData): void; + eq(other: ISignalData): boolean; +} + +//站台颜色 +export enum SignalColorEnum { + lampPostColor = '0xc0c0c0', + lampColor = '0xff0000', + humanControlColor = '0xffff00', + fleetModeColor = '0x00ff00', + logicModeColor = '0x000000', +} + +const signalConsts = { + verticalLampPostLength: 20, + levelLampPostLength: 5, + lineWidth: 3, + lampRadius: 10, + nameOffsetY: 20, + humanControlPath: [-2, 0, -17, 10, -17, -10], + logicModeLineWidth: 2, + logicModeDistance: 7, + fleetModePath: [2, -4, 22, -4, 22, -10, 35, 0, 22, 10, 22, 4, 2, 4], +}; +export class Signal extends JlGraphic { + static Type = 'signal'; + codeGraph: VectorText = new VectorText(''); + lampPost: Graphics = new Graphics(); + circularLamp: Graphics = new Graphics(); + humanControl: Graphics = new Graphics(); + fleetMode: Graphics = new Graphics(); + logicMode: Graphics = new Graphics(); + + constructor() { + super(Signal.Type); + this.addChild(this.codeGraph); + this.addChild(this.lampPost); + this.addChild(this.circularLamp); + this.addChild(this.humanControl); + this.addChild(this.fleetMode); + this.addChild(this.logicMode); + } + + get datas(): ISignalData { + return this.getDatas(); + } + doRepaint(): void { + console.log(this.datas, 'this.datas'); + const codeGraph = this.codeGraph; + this.lampPost.clear(); + this.lampPost.lineStyle( + signalConsts.lineWidth, + new Color(SignalColorEnum.lampPostColor) + ); + this.lampPost.moveTo(0, -signalConsts.verticalLampPostLength / 2); + this.lampPost.lineTo(0, signalConsts.verticalLampPostLength / 2); + this.lampPost.moveTo(0, 0); + this.lampPost.lineTo(signalConsts.levelLampPostLength, 0); + this.circularLamp.beginFill(SignalColorEnum.lampColor, 1); + this.circularLamp.drawCircle( + signalConsts.levelLampPostLength + signalConsts.lampRadius, + 0, + signalConsts.lampRadius + ); + this.circularLamp.endFill(); + this.humanControl.beginFill(SignalColorEnum.humanControlColor, 1); + this.humanControl.drawPolygon(signalConsts.humanControlPath); + this.humanControl.endFill(); + this.fleetMode.beginFill(SignalColorEnum.fleetModeColor, 1); + const fleetModePath: number[] = []; + signalConsts.fleetModePath.forEach((item: number, index: number) => { + if (!(index % 2)) { + fleetModePath.push( + item + signalConsts.levelLampPostLength + signalConsts.lampRadius * 2 + ); + } else { + fleetModePath.push(item); + } + }); + this.fleetMode.drawPolygon(fleetModePath); + this.fleetMode.endFill(); + this.logicMode.lineStyle(2, new Color(SignalColorEnum.logicModeColor)); + this.logicMode.moveTo( + signalConsts.levelLampPostLength + + signalConsts.lampRadius - + signalConsts.logicModeDistance, + signalConsts.logicModeDistance + ); + this.logicMode.lineTo( + signalConsts.levelLampPostLength + + signalConsts.lampRadius + + signalConsts.logicModeDistance, + -signalConsts.logicModeDistance + ); + this.logicMode.moveTo( + signalConsts.levelLampPostLength + + signalConsts.lampRadius - + signalConsts.logicModeDistance, + -signalConsts.logicModeDistance + ); + this.logicMode.lineTo( + signalConsts.levelLampPostLength + + signalConsts.lampRadius + + signalConsts.logicModeDistance, + signalConsts.logicModeDistance + ); + if (this.datas.code == '') { + codeGraph.text = '信号机Signal'; + } else { + codeGraph.text = this.datas.code; + } + codeGraph.style.fill = this.datas.codeColor; + codeGraph.setVectorFontSize(this.datas.codeFontSize); + codeGraph.anchor.set(0.5); + codeGraph.style.fill = this.datas.codeColor; + codeGraph.position.set(0, signalConsts.nameOffsetY); + this.position.set(this.datas.point.x, this.datas.point.y); + } +} + +export class SignalTemplate extends JlGraphicTemplate { + codeColor: string; + codeFontSize: number; + direction: string; + verticalLampPostLength: number; + levelLampPostLength: number; + lineWidth: number; + lampRadius: number; + lampPostColor: string; + lampColor: string; + humanControlColor: string; + fleetModeColor: string; + logicModeColor: string; + humanControlPath: number[]; + logicModeLineWidth: number; + logicModeDistance: number; + fleetModePath: number[]; + nameOffsetY: number; + constructor() { + super(Signal.Type); + this.codeColor = '0xff0000'; + this.codeFontSize = 11; + this.direction = 'right'; + this.verticalLampPostLength = signalConsts.verticalLampPostLength; + this.levelLampPostLength = signalConsts.levelLampPostLength; + this.lineWidth = signalConsts.lineWidth; + this.lampRadius = signalConsts.lampRadius; + this.lampPostColor = SignalColorEnum.lampPostColor; + this.lampColor = SignalColorEnum.lampColor; + this.humanControlColor = SignalColorEnum.humanControlColor; + this.fleetModeColor = SignalColorEnum.fleetModeColor; + this.logicModeColor = SignalColorEnum.logicModeColor; + this.humanControlPath = signalConsts.humanControlPath; + this.logicModeLineWidth = signalConsts.logicModeLineWidth; + this.logicModeDistance = signalConsts.logicModeDistance; + this.nameOffsetY = signalConsts.nameOffsetY; + const fleetModePath: number[] = []; + signalConsts.fleetModePath.forEach((item: number, index: number) => { + if (!(index % 2)) { + fleetModePath.push( + item + signalConsts.levelLampPostLength + signalConsts.lampRadius * 2 + ); + } else { + fleetModePath.push(item); + } + }); + this.fleetModePath = fleetModePath; + } + new(): Signal { + return new Signal(); + } +} diff --git a/src/graphics/signal/SignalDrawAssistant.ts b/src/graphics/signal/SignalDrawAssistant.ts new file mode 100644 index 0000000..0e3de06 --- /dev/null +++ b/src/graphics/signal/SignalDrawAssistant.ts @@ -0,0 +1,173 @@ +import { FederatedPointerEvent, Point, Graphics, Color } from 'pixi.js'; +import { + GraphicDrawAssistant, + GraphicInteractionPlugin, + JlDrawApp, + JlGraphic, + KeyListener, + VectorText, +} from 'src/jlgraphic'; + +import { ISignalData, Signal, SignalTemplate } from './Signal'; + +export interface ISignalDrawOptions { + newData: () => ISignalData; +} + +export class SignalDraw extends GraphicDrawAssistant< + SignalTemplate, + ISignalData +> { + point: Point = new Point(0, 0); + codeGraph: VectorText = new VectorText(''); + lampPost: Graphics = new Graphics(); + circularLamp: Graphics = new Graphics(); + humanControl: Graphics = new Graphics(); + fleetMode: Graphics = new Graphics(); + logicMode: Graphics = new Graphics(); + + // 快捷绘制 + keypListener: KeyListener = new KeyListener({ + value: 'KeyH', + global: true, + onPress: () => { + //this.graphicTemplate.hasdoor = true; + }, + }); + + constructor(app: JlDrawApp, createData: () => ISignalData) { + super(app, new SignalTemplate(), createData, Signal.Type, '信号机Signal'); + this.container.addChild(this.codeGraph); + this.container.addChild(this.lampPost); + this.container.addChild(this.circularLamp); + this.container.addChild(this.humanControl); + this.container.addChild(this.fleetMode); + this.container.addChild(this.logicMode); + signalInteraction.init(app); + } + + bind(): void { + super.bind(); + this.app.addKeyboardListener(this.keypListener); + } + unbind(): void { + super.unbind(); + this.app.removeKeyboardListener(this.keypListener); + } + + clearCache(): void { + //this.codeGraph.clear(); + } + onRightClick(): void { + this.createAndStore(true); + } + 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; + const template = this.graphicTemplate; + this.point.set(p.x, p.y); + this.lampPost.lineStyle( + template.lineWidth, + new Color(template.lampPostColor) + ); + this.lampPost.moveTo(0, -template.verticalLampPostLength / 2); + this.lampPost.lineTo(0, template.verticalLampPostLength / 2); + + this.lampPost.moveTo(0, 0); + this.lampPost.lineTo(template.levelLampPostLength, 0); + + this.lampPost.position.set(p.x, p.y); + this.circularLamp.beginFill(template.lampColor, 1); + this.circularLamp.drawCircle( + template.levelLampPostLength + template.lampRadius, + 0, + template.lampRadius + ); + this.circularLamp.endFill(); + this.circularLamp.position.set(p.x, p.y); + this.humanControl.beginFill(template.humanControlColor, 1); + this.humanControl.drawPolygon(template.humanControlPath); + this.humanControl.endFill(); + this.humanControl.position.set(p.x, p.y); + this.fleetMode.beginFill(template.fleetModeColor, 1); + this.fleetMode.drawPolygon(template.fleetModePath); + this.fleetMode.endFill(); + this.fleetMode.position.set(p.x, p.y); + this.logicMode.lineStyle( + template.logicModeLineWidth, + new Color(template.logicModeColor) + ); + this.logicMode.moveTo( + template.levelLampPostLength + + template.lampRadius - + template.logicModeDistance, + template.logicModeDistance + ); + this.logicMode.lineTo( + template.levelLampPostLength + + template.lampRadius + + template.logicModeDistance, + -template.logicModeDistance + ); + this.logicMode.moveTo( + template.levelLampPostLength + + template.lampRadius - + template.logicModeDistance, + -template.logicModeDistance + ); + this.logicMode.lineTo( + template.levelLampPostLength + + template.lampRadius + + template.logicModeDistance, + template.logicModeDistance + ); + this.logicMode.position.set(p.x, p.y); + codeGraph.text = '信号机Signal'; + + codeGraph.style.fill = template.codeColor; + codeGraph.setVectorFontSize(template.codeFontSize); + codeGraph.anchor.set(0.5); + codeGraph.style.fill = template.codeColor; + codeGraph.position.set(p.x, p.y + template.nameOffsetY); + } + prepareData(data: ISignalData): boolean { + const template = this.graphicTemplate; + data.point = this.point; + data.codeColor = template.codeColor; + data.codeFontSize = template.codeFontSize; + data.direction = template.direction; + return true; + } +} + +export class signalInteraction extends GraphicInteractionPlugin { + 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; + } + unbind(g: Signal): void { + g.eventMode = 'none'; + g.scalable = false; + g.rotatable = false; + } +} diff --git a/yarn.lock b/yarn.lock index c14e795..c5c9616 100644 --- a/yarn.lock +++ b/yarn.lock @@ -183,6 +183,11 @@ resolved "https://registry.npmmirror.com/@pixi/filter-noise/-/filter-noise-7.2.4.tgz#0586a00381ec0e63f6c00d49cd58b781eaf07f37" integrity sha512-QAU9Ybj2ZQrWM9ZEjTTC0iLnQcuyNoZNRinxSbg1G0yacpmsSb9wvV5ltIZ66+hfY+90+u2Nudt/v9g6pvOdGg== +"@pixi/graphics-extras@^7.2.4": + version "7.2.4" + resolved "https://registry.yarnpkg.com/@pixi/graphics-extras/-/graphics-extras-7.2.4.tgz#72ac967992f239d3671d6e680ac891471619fe07" + integrity sha512-0yT91yqF3KLiZI/iLRcfcYlTVpkVyWsfGtWEIorZs0eX+/zYx7um7EJ2h7tFORI/1FxA2maR4td5vpgCwOLJAQ== + "@pixi/graphics@7.2.4": version "7.2.4" resolved "https://registry.npmmirror.com/@pixi/graphics/-/graphics-7.2.4.tgz#8500b604c36184736926393cb0ca9b9de9afef86" From 21c1d974652ac2683ef24bc8be46f0061d8a8781 Mon Sep 17 00:00:00 2001 From: fan Date: Tue, 6 Jun 2023 16:03:47 +0800 Subject: [PATCH 17/44] =?UTF-8?q?=E4=BF=A1=E5=8F=B7=E6=9C=BA=E8=B0=83?= =?UTF-8?q?=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/draw-app/properties/SignalProperty.vue | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/draw-app/properties/SignalProperty.vue b/src/components/draw-app/properties/SignalProperty.vue index 3e3362e..1748aff 100644 --- a/src/components/draw-app/properties/SignalProperty.vue +++ b/src/components/draw-app/properties/SignalProperty.vue @@ -40,9 +40,9 @@ watch( ); onMounted(() => { - const platform = drawStore.selectedGraphic as Signal; - if (platform) { - signalModel.copyFrom(platform.saveData()); + const signal = drawStore.selectedGraphic as Signal; + if (signal) { + signalModel.copyFrom(signal.saveData()); signalDirection.value = (directionSelect as never)[signalModel.direction]; } }); From 2863a19b5c0cc24e7f780c220d3fd37f9d71696c Mon Sep 17 00:00:00 2001 From: fan Date: Tue, 6 Jun 2023 16:04:44 +0800 Subject: [PATCH 18/44] =?UTF-8?q?=E4=BF=A1=E5=8F=B7=E6=9C=BA=E8=B0=83?= =?UTF-8?q?=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/draw-app/properties/SignalProperty.vue | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/draw-app/properties/SignalProperty.vue b/src/components/draw-app/properties/SignalProperty.vue index 1748aff..f2688bd 100644 --- a/src/components/draw-app/properties/SignalProperty.vue +++ b/src/components/draw-app/properties/SignalProperty.vue @@ -49,9 +49,9 @@ onMounted(() => { function onUpdate() { signalModel.direction = (directionSelect as never)[signalDirection.value]; - const platform = drawStore.selectedGraphic as Signal; - if (platform) { - drawStore.getDrawApp().updateGraphicAndRecord(platform, signalModel); + const signal = drawStore.selectedGraphic as Signal; + if (signal) { + drawStore.getDrawApp().updateGraphicAndRecord(signal, signalModel); } } From 82ef7a1b8b743403dedef83f789516d593f5f243 Mon Sep 17 00:00:00 2001 From: joylink_zhaoerwei Date: Tue, 6 Jun 2023 16:10:17 +0800 Subject: [PATCH 19/44] =?UTF-8?q?bug=E8=B0=83=E6=95=B4--=E5=88=A0=E9=99=A4?= =?UTF-8?q?=E5=8F=B3=E9=94=AE=E4=BF=9D=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/graphics/platform/PlatformDrawAssistant.ts | 3 --- src/graphics/rect/RectDrawAssistant.ts | 3 --- src/graphics/station/StationDrawAssistant.ts | 3 --- src/graphics/train/TrainDrawAssistant.ts | 3 --- 4 files changed, 12 deletions(-) diff --git a/src/graphics/platform/PlatformDrawAssistant.ts b/src/graphics/platform/PlatformDrawAssistant.ts index fb6b17a..f7987a9 100644 --- a/src/graphics/platform/PlatformDrawAssistant.ts +++ b/src/graphics/platform/PlatformDrawAssistant.ts @@ -52,9 +52,6 @@ export class PlatformDraw extends GraphicDrawAssistant< this.platformGraphic.clear(); this.doorGraphic.clear(); } - onRightClick(): void { - this.createAndStore(true); - } onLeftDown(e: FederatedPointerEvent): void { const { x, y } = this.toCanvasCoordinates(e.global); const p = new Point(x, y); diff --git a/src/graphics/rect/RectDrawAssistant.ts b/src/graphics/rect/RectDrawAssistant.ts index a8ed20e..63a8156 100644 --- a/src/graphics/rect/RectDrawAssistant.ts +++ b/src/graphics/rect/RectDrawAssistant.ts @@ -59,9 +59,6 @@ export class RectDraw extends GraphicDrawAssistant { clearCache(): void { this.rectGraphic.clear(); } - onRightClick(): void { - this.createAndStore(true); - } onLeftDown(e: FederatedPointerEvent): void { const { x, y } = this.toCanvasCoordinates(e.global); const p = new Point(x, y); diff --git a/src/graphics/station/StationDrawAssistant.ts b/src/graphics/station/StationDrawAssistant.ts index 9776752..a29669d 100644 --- a/src/graphics/station/StationDrawAssistant.ts +++ b/src/graphics/station/StationDrawAssistant.ts @@ -36,9 +36,6 @@ export class StationDraw extends GraphicDrawAssistant< clearCache(): void { //this.codeGraph.clear(); } - onRightClick(): void { - this.createAndStore(true); - } onLeftDown(e: FederatedPointerEvent): void { const { x, y } = this.toCanvasCoordinates(e.global); const p = new Point(x, y); diff --git a/src/graphics/train/TrainDrawAssistant.ts b/src/graphics/train/TrainDrawAssistant.ts index bb4d479..767a383 100644 --- a/src/graphics/train/TrainDrawAssistant.ts +++ b/src/graphics/train/TrainDrawAssistant.ts @@ -40,9 +40,6 @@ export class TrainDraw extends GraphicDrawAssistant { this.pauseLeft.clear(); this.codeRact.clear(); } - onRightClick(): void { - this.createAndStore(true); - } onLeftDown(e: FederatedPointerEvent): void { const { x, y } = this.toCanvasCoordinates(e.global); const p = new Point(x, y); From fe0ba85437c2601451e3fed4769441907cf8addf Mon Sep 17 00:00:00 2001 From: joylink_zhaoerwei Date: Tue, 6 Jun 2023 16:49:12 +0800 Subject: [PATCH 20/44] =?UTF-8?q?=E7=9F=A9=E5=BD=A2=E7=A7=BB=E5=8A=A8bug?= =?UTF-8?q?=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/graphics/rect/RectDrawAssistant.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/graphics/rect/RectDrawAssistant.ts b/src/graphics/rect/RectDrawAssistant.ts index 63a8156..306b2f0 100644 --- a/src/graphics/rect/RectDrawAssistant.ts +++ b/src/graphics/rect/RectDrawAssistant.ts @@ -156,7 +156,9 @@ function buildAbsorbablePositions(rect: Rect): AbsorbablePosition[] { return; } other.linePoints.forEach((point) => { - const absorbablePoint = new AbsorbablePoint(point); + const absorbablePoint = new AbsorbablePoint( + other.localToCanvasPoint(point) + ); aps.push(absorbablePoint); }); }); From d7014486ded1b4741070a9b5bd92016622f0a267 Mon Sep 17 00:00:00 2001 From: walker Date: Thu, 8 Jun 2023 15:29:05 +0800 Subject: [PATCH 21/44] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=AD=90=E5=85=83?= =?UTF-8?q?=E7=B4=A0=E5=8F=98=E6=8D=A2=E6=97=A0=E6=95=88bug=20=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=E4=B8=8D=E8=83=BD=E5=8F=AA=E6=89=93=E5=BC=80=E6=97=8B?= =?UTF-8?q?=E8=BD=AC=E5=8F=98=E6=8D=A2bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/graphics/iscs-fan/IscsFanDrawAssistant.ts | 4 +-- .../plugins/GraphicTransformPlugin.ts | 32 +++++++++---------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/graphics/iscs-fan/IscsFanDrawAssistant.ts b/src/graphics/iscs-fan/IscsFanDrawAssistant.ts index 71ae98f..5853991 100644 --- a/src/graphics/iscs-fan/IscsFanDrawAssistant.ts +++ b/src/graphics/iscs-fan/IscsFanDrawAssistant.ts @@ -66,12 +66,12 @@ export class IscsFanInteraction extends GraphicInteractionPlugin { bind(g: IscsFan): void { g.eventMode = 'static'; g.cursor = 'pointer'; - g.scalable = true; + // g.scalable = true; g.rotatable = true; } unbind(g: IscsFan): void { g.eventMode = 'none'; - g.scalable = false; + // g.scalable = false; g.rotatable = false; } } diff --git a/src/jlgraphic/plugins/GraphicTransformPlugin.ts b/src/jlgraphic/plugins/GraphicTransformPlugin.ts index d277651..cbc3cbd 100644 --- a/src/jlgraphic/plugins/GraphicTransformPlugin.ts +++ b/src/jlgraphic/plugins/GraphicTransformPlugin.ts @@ -187,7 +187,7 @@ export class GraphicTransformPlugin extends InteractionPluginBase { this.app.on('graphicselectedchange', this.onGraphicSelectedChange, this); this.app.on( 'graphicchildselectedchange', - this.onGraphicChildSelectedChange, + this.onGraphicSelectedChange, this ); } @@ -198,7 +198,7 @@ export class GraphicTransformPlugin extends InteractionPluginBase { this.app.off('graphicselectedchange', this.onGraphicSelectedChange, this); this.app.off( 'graphicchildselectedchange', - this.onGraphicChildSelectedChange, + this.onGraphicSelectedChange, this ); } @@ -335,7 +335,7 @@ export class GraphicTransformPlugin extends InteractionPluginBase { br.visible = false; } } - if (g.scalable) { + if (g.scalable || g.rotatable) { // 缩放点 let sp = g.getAssistantAppend(TransformPoints.Name); if (!sp) { @@ -350,19 +350,19 @@ export class GraphicTransformPlugin extends InteractionPluginBase { } } - onGraphicChildSelectedChange(child: DisplayObject, selected: boolean) { - let br = child.getAssistantAppend(BoundsGraphic.Name); - if (!br) { - // 绘制辅助包围框 - br = new BoundsGraphic(child); - } - if (selected) { - br.redraw(); - br.visible = true; - } else { - br.visible = false; - } - } + // onGraphicChildSelectedChange(child: DisplayObject, selected: boolean) { + // let br = child.getAssistantAppend(BoundsGraphic.Name); + // if (!br) { + // // 绘制辅助包围框 + // br = new BoundsGraphic(child); + // } + // if (selected) { + // br.redraw(); + // br.visible = true; + // } else { + // br.visible = false; + // } + // } } /** From 65f8e53e6b27df23aa3c076e3abe4c8ea11019ee Mon Sep 17 00:00:00 2001 From: fan Date: Fri, 9 Jun 2023 17:44:01 +0800 Subject: [PATCH 22/44] =?UTF-8?q?=E7=A7=BB=E9=99=A4=E5=AE=B9=E5=99=A8?= =?UTF-8?q?=E5=89=8D=E5=88=A4=E6=96=AD=E7=88=B6=E5=85=83=E7=B4=A0=E6=98=AF?= =?UTF-8?q?=E5=90=A6=E5=AD=98=E5=9C=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/jlgraphic/app/JlDrawApp.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/jlgraphic/app/JlDrawApp.ts b/src/jlgraphic/app/JlDrawApp.ts index cf49b2e..22151c0 100644 --- a/src/jlgraphic/app/JlDrawApp.ts +++ b/src/jlgraphic/app/JlDrawApp.ts @@ -102,7 +102,9 @@ export abstract class GraphicDrawAssistant< unbind(): void { this.clearCache(); const canvas = this.canvas; - canvas.removeChild(this.container); + if (this.container?.parent) { + canvas.removeChild(this.container); + } canvas.off('mousedown', this.onLeftDown, this); canvas.off('mousemove', this.onMouseMove, this); canvas.off('mouseup', this.onLeftUp, this); From f3767eb72077342dbee7fdbecd82f75ddc368204 Mon Sep 17 00:00:00 2001 From: walker Date: Thu, 15 Jun 2023 14:09:23 +0800 Subject: [PATCH 23/44] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BD=8D=E7=A7=BB?= =?UTF-8?q?=E5=8F=98=E6=8D=A2bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 1 + quasar.config.js | 2 +- src/boot/@pixi/graphics-extras.ts | 7 + .../protos/draw_data_storage.proto | 4 - src/examples/app/graphics/GraphicDataBase.ts | 4 +- .../app/graphics/SignalInteraction.ts | 29 +-- src/examples/app/index.ts | 9 - src/examples/app/protos/draw_data_storage.ts | 95 ---------- src/graphics/CommonGraphics.ts | 51 +++++ src/graphics/signal/Lamp.ts | 52 +++++ src/graphics/signal/LampMainBody.ts | 51 +++++ src/graphics/signal/Signal.ts | 178 +++++------------- src/graphics/signal/SignalDrawAssistant.ts | 147 ++++----------- .../plugins/GraphicTransformPlugin.ts | 5 +- src/jlgraphic/plugins/InteractionPlugin.ts | 14 +- yarn.lock | 2 +- 16 files changed, 265 insertions(+), 386 deletions(-) create mode 100644 src/boot/@pixi/graphics-extras.ts create mode 100644 src/graphics/CommonGraphics.ts create mode 100644 src/graphics/signal/Lamp.ts create mode 100644 src/graphics/signal/LampMainBody.ts diff --git a/package.json b/package.json index 2ebe69b..80d4257 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "build": "quasar build" }, "dependencies": { + "@pixi/graphics-extras": "^7.2.4", "@quasar/extras": "^1.0.0", "@stomp/stompjs": "^7.0.0", "google-protobuf": "^3.21.2", diff --git a/quasar.config.js b/quasar.config.js index 6d7aa33..c8f1936 100644 --- a/quasar.config.js +++ b/quasar.config.js @@ -28,7 +28,7 @@ module.exports = configure(function (/* ctx */) { // app boot file (/src/boot) // --> boot files are part of "main.js" // https://v2.quasar.dev/quasar-cli-vite/boot-files - boot: [], + boot: ['@pixi/graphics-extras'], // https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#css css: ['app.scss'], diff --git a/src/boot/@pixi/graphics-extras.ts b/src/boot/@pixi/graphics-extras.ts new file mode 100644 index 0000000..4a70eb8 --- /dev/null +++ b/src/boot/@pixi/graphics-extras.ts @@ -0,0 +1,7 @@ +import { boot } from 'quasar/wrappers'; +import * as GraphicsExtras from '@pixi/graphics-extras'; +// "async" is optional; +// more info on params: https://v2.quasar.dev/quasar-cli/boot-files +export default boot(async (/* { app, router, ... } */) => { + GraphicsExtras; +}); diff --git a/src/examples/app/app_message/protos/draw_data_storage.proto b/src/examples/app/app_message/protos/draw_data_storage.proto index 9a55916..3ded330 100644 --- a/src/examples/app/app_message/protos/draw_data_storage.proto +++ b/src/examples/app/app_message/protos/draw_data_storage.proto @@ -131,8 +131,4 @@ message Turnout {} message Signal { CommonInfo common = 1; string code = 2; - string codeColor = 3; // 信号机字体颜色 - int32 codeFontSize = 4; // 信号机字体大小 - Point point = 5; // 位置坐标 - string direction = 6; //信号机朝向 } diff --git a/src/examples/app/graphics/GraphicDataBase.ts b/src/examples/app/graphics/GraphicDataBase.ts index e004380..26cd669 100644 --- a/src/examples/app/graphics/GraphicDataBase.ts +++ b/src/examples/app/graphics/GraphicDataBase.ts @@ -27,10 +27,10 @@ export abstract class GraphicDataBase implements GraphicData { this._data = data; } - static defaultCommonInfo(): graphicData.CommonInfo { + static defaultCommonInfo(graphicType: string): graphicData.CommonInfo { return new graphicData.CommonInfo({ id: '', - graphicType: '', + graphicType: graphicType, transform: new graphicData.Transform({ position: new graphicData.Point({ x: 0, y: 0 }), scale: new graphicData.Point({ x: 1, y: 1 }), diff --git a/src/examples/app/graphics/SignalInteraction.ts b/src/examples/app/graphics/SignalInteraction.ts index 6ff2540..78fb97f 100644 --- a/src/examples/app/graphics/SignalInteraction.ts +++ b/src/examples/app/graphics/SignalInteraction.ts @@ -1,6 +1,5 @@ import * as pb_1 from 'google-protobuf'; -import { IPointData } from 'pixi.js'; -import { ISignalData } from 'src/graphics/signal/Signal'; +import { ISignalData, Signal } from 'src/graphics/signal/Signal'; import { graphicData } from '../protos/draw_data_storage'; import { GraphicDataBase } from './GraphicDataBase'; @@ -9,7 +8,7 @@ export class SignalData extends GraphicDataBase implements ISignalData { let signal; if (!data) { signal = new graphicData.Signal({ - common: GraphicDataBase.defaultCommonInfo(), + common: GraphicDataBase.defaultCommonInfo(Signal.Type), }); } else { signal = data; @@ -26,30 +25,6 @@ export class SignalData extends GraphicDataBase implements ISignalData { set code(v: string) { this.data.code = v; } - get codeColor(): string { - return this.data.codeColor; - } - set codeColor(v: string) { - this.data.codeColor = v; - } - get codeFontSize(): number { - return this.data.codeFontSize; - } - set codeFontSize(v: number) { - this.data.codeFontSize = v; - } - get point(): IPointData { - return this.data.point; - } - set point(point: IPointData) { - this.data.point = new graphicData.Point({ x: point.x, y: point.y }); - } - get direction(): string { - return this.data.direction; - } - set direction(v: string) { - this.data.direction = v; - } clone(): SignalData { return new SignalData(this.data.cloneMessage()); } diff --git a/src/examples/app/index.ts b/src/examples/app/index.ts index 947e88d..4895b10 100644 --- a/src/examples/app/index.ts +++ b/src/examples/app/index.ts @@ -106,18 +106,9 @@ export function initDrawApp(dom: HTMLElement): JlDrawApp { new LinkDraw(app, () => { return new LinkData(); }), - new RectDraw(app, () => { - return new RectData(); - }), new IscsFanDraw(app, () => { return new IscsFanData(); }), - new PlatformDraw(app, () => { - return new PlatformData(); - }), - new StationDraw(app, () => { - return new StationData(); - }), new SignalDraw(app, () => { return new SignalData(); }), diff --git a/src/examples/app/protos/draw_data_storage.ts b/src/examples/app/protos/draw_data_storage.ts index 4ef1320..5467429 100644 --- a/src/examples/app/protos/draw_data_storage.ts +++ b/src/examples/app/protos/draw_data_storage.ts @@ -2334,10 +2334,6 @@ export namespace graphicData { constructor(data?: any[] | { common?: CommonInfo; code?: string; - codeColor?: string; - codeFontSize?: number; - point?: Point; - direction?: string; }) { super(); pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); @@ -2348,18 +2344,6 @@ export namespace graphicData { if ("code" in data && data.code != undefined) { this.code = data.code; } - if ("codeColor" in data && data.codeColor != undefined) { - this.codeColor = data.codeColor; - } - if ("codeFontSize" in data && data.codeFontSize != undefined) { - this.codeFontSize = data.codeFontSize; - } - if ("point" in data && data.point != undefined) { - this.point = data.point; - } - if ("direction" in data && data.direction != undefined) { - this.direction = data.direction; - } } } get common() { @@ -2377,40 +2361,9 @@ export namespace graphicData { set code(value: string) { pb_1.Message.setField(this, 2, value); } - get codeColor() { - return pb_1.Message.getFieldWithDefault(this, 3, "") as string; - } - set codeColor(value: string) { - pb_1.Message.setField(this, 3, value); - } - get codeFontSize() { - return pb_1.Message.getFieldWithDefault(this, 4, 0) as number; - } - set codeFontSize(value: number) { - pb_1.Message.setField(this, 4, value); - } - get point() { - return pb_1.Message.getWrapperField(this, Point, 5) as Point; - } - set point(value: Point) { - pb_1.Message.setWrapperField(this, 5, value); - } - get has_point() { - return pb_1.Message.getField(this, 5) != null; - } - get direction() { - return pb_1.Message.getFieldWithDefault(this, 6, "") as string; - } - set direction(value: string) { - pb_1.Message.setField(this, 6, value); - } static fromObject(data: { common?: ReturnType; code?: string; - codeColor?: string; - codeFontSize?: number; - point?: ReturnType; - direction?: string; }): Signal { const message = new Signal({}); if (data.common != null) { @@ -2419,28 +2372,12 @@ export namespace graphicData { if (data.code != null) { message.code = data.code; } - if (data.codeColor != null) { - message.codeColor = data.codeColor; - } - if (data.codeFontSize != null) { - message.codeFontSize = data.codeFontSize; - } - if (data.point != null) { - message.point = Point.fromObject(data.point); - } - if (data.direction != null) { - message.direction = data.direction; - } return message; } toObject() { const data: { common?: ReturnType; code?: string; - codeColor?: string; - codeFontSize?: number; - point?: ReturnType; - direction?: string; } = {}; if (this.common != null) { data.common = this.common.toObject(); @@ -2448,18 +2385,6 @@ export namespace graphicData { if (this.code != null) { data.code = this.code; } - if (this.codeColor != null) { - data.codeColor = this.codeColor; - } - if (this.codeFontSize != null) { - data.codeFontSize = this.codeFontSize; - } - if (this.point != null) { - data.point = this.point.toObject(); - } - if (this.direction != null) { - data.direction = this.direction; - } return data; } serialize(): Uint8Array; @@ -2470,14 +2395,6 @@ export namespace graphicData { writer.writeMessage(1, this.common, () => this.common.serialize(writer)); if (this.code.length) writer.writeString(2, this.code); - if (this.codeColor.length) - writer.writeString(3, this.codeColor); - if (this.codeFontSize != 0) - writer.writeInt32(4, this.codeFontSize); - if (this.has_point) - writer.writeMessage(5, this.point, () => this.point.serialize(writer)); - if (this.direction.length) - writer.writeString(6, this.direction); if (!w) return writer.getResultBuffer(); } @@ -2493,18 +2410,6 @@ export namespace graphicData { case 2: message.code = reader.readString(); break; - case 3: - message.codeColor = reader.readString(); - break; - case 4: - message.codeFontSize = reader.readInt32(); - break; - case 5: - reader.readMessage(message.point, () => message.point = Point.deserialize(reader)); - break; - case 6: - message.direction = reader.readString(); - break; default: reader.skipField(); } } diff --git a/src/graphics/CommonGraphics.ts b/src/graphics/CommonGraphics.ts new file mode 100644 index 0000000..60e935f --- /dev/null +++ b/src/graphics/CommonGraphics.ts @@ -0,0 +1,51 @@ +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 + ); +} diff --git a/src/graphics/signal/Lamp.ts b/src/graphics/signal/Lamp.ts new file mode 100644 index 0000000..1b0d564 --- /dev/null +++ b/src/graphics/signal/Lamp.ts @@ -0,0 +1,52 @@ +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 + ); + } +} diff --git a/src/graphics/signal/LampMainBody.ts b/src/graphics/signal/LampMainBody.ts new file mode 100644 index 0000000..7436303 --- /dev/null +++ b/src/graphics/signal/LampMainBody.ts @@ -0,0 +1,51 @@ +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() {} +} diff --git a/src/graphics/signal/Signal.ts b/src/graphics/signal/Signal.ts index edabfb3..4c0fa61 100644 --- a/src/graphics/signal/Signal.ts +++ b/src/graphics/signal/Signal.ts @@ -1,190 +1,98 @@ -import { IPointData, Graphics, Color } from 'pixi.js'; +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); - get codeColor(): string; - set codeColor(v: string); - get codeFontSize(): number; - set codeFontSize(v: number); - get point(): IPointData; - set point(point: IPointData); - get direction(): string; - set direction(v: string); clone(): ISignalData; copyFrom(data: ISignalData): void; eq(other: ISignalData): boolean; } -//站台颜色 export enum SignalColorEnum { - lampPostColor = '0xc0c0c0', - lampColor = '0xff0000', humanControlColor = '0xffff00', fleetModeColor = '0x00ff00', - logicModeColor = '0x000000', + codeColor = '0X000000', } const signalConsts = { - verticalLampPostLength: 20, - levelLampPostLength: 5, - lineWidth: 3, - lampRadius: 10, + lampNum: 1, + codeFontSize: 11, nameOffsetY: 20, - humanControlPath: [-2, 0, -17, 10, -17, -10], - logicModeLineWidth: 2, - logicModeDistance: 7, - fleetModePath: [2, -4, 22, -4, 22, -10, 35, 0, 22, 10, 22, 4, 2, 4], + fleetModeLength: 33, + fleetModeRadius: 10, + fleetModeLineWidth: 6, }; export class Signal extends JlGraphic { static Type = 'signal'; codeGraph: VectorText = new VectorText(''); - lampPost: Graphics = new Graphics(); - circularLamp: Graphics = new Graphics(); humanControl: Graphics = new Graphics(); fleetMode: Graphics = new Graphics(); - logicMode: Graphics = new Graphics(); + lampMainBody: LampMainBody = new LampMainBody(); constructor() { super(Signal.Type); + this.codeGraph.name = 'signalCode'; this.addChild(this.codeGraph); - this.addChild(this.lampPost); - this.addChild(this.circularLamp); this.addChild(this.humanControl); this.addChild(this.fleetMode); - this.addChild(this.logicMode); + this.addChild(this.lampMainBody); } get datas(): ISignalData { return this.getDatas(); } - doRepaint(): void { - console.log(this.datas, 'this.datas'); - const codeGraph = this.codeGraph; - this.lampPost.clear(); - this.lampPost.lineStyle( - signalConsts.lineWidth, - new Color(SignalColorEnum.lampPostColor) - ); - this.lampPost.moveTo(0, -signalConsts.verticalLampPostLength / 2); - this.lampPost.lineTo(0, signalConsts.verticalLampPostLength / 2); - this.lampPost.moveTo(0, 0); - this.lampPost.lineTo(signalConsts.levelLampPostLength, 0); - this.circularLamp.beginFill(SignalColorEnum.lampColor, 1); - this.circularLamp.drawCircle( - signalConsts.levelLampPostLength + signalConsts.lampRadius, - 0, - signalConsts.lampRadius - ); - this.circularLamp.endFill(); + + paint(): void { + this.lampMainBody.paint(signalConsts.lampNum); this.humanControl.beginFill(SignalColorEnum.humanControlColor, 1); - this.humanControl.drawPolygon(signalConsts.humanControlPath); + if (this.humanControl.drawRegularPolygon) { + this.humanControl.drawRegularPolygon(-10, 0, 10, 3, Math.PI / 2); + } this.humanControl.endFill(); this.fleetMode.beginFill(SignalColorEnum.fleetModeColor, 1); - const fleetModePath: number[] = []; - signalConsts.fleetModePath.forEach((item: number, index: number) => { - if (!(index % 2)) { - fleetModePath.push( - item + signalConsts.levelLampPostLength + signalConsts.lampRadius * 2 - ); - } else { - fleetModePath.push(item); - } - }); - this.fleetMode.drawPolygon(fleetModePath); + drawArrow( + this.fleetMode, + this.lampMainBody.width + signalConsts.fleetModeLength, + 0, + signalConsts.fleetModeLength, + signalConsts.fleetModeRadius, + signalConsts.fleetModeLineWidth + ); this.fleetMode.endFill(); - this.logicMode.lineStyle(2, new Color(SignalColorEnum.logicModeColor)); - this.logicMode.moveTo( - signalConsts.levelLampPostLength + - signalConsts.lampRadius - - signalConsts.logicModeDistance, - signalConsts.logicModeDistance + 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' ); - this.logicMode.lineTo( - signalConsts.levelLampPostLength + - signalConsts.lampRadius + - signalConsts.logicModeDistance, - -signalConsts.logicModeDistance - ); - this.logicMode.moveTo( - signalConsts.levelLampPostLength + - signalConsts.lampRadius - - signalConsts.logicModeDistance, - -signalConsts.logicModeDistance - ); - this.logicMode.lineTo( - signalConsts.levelLampPostLength + - signalConsts.lampRadius + - signalConsts.logicModeDistance, - signalConsts.logicModeDistance - ); - if (this.datas.code == '') { - codeGraph.text = '信号机Signal'; + 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 { - codeGraph.text = this.datas.code; + this.codeGraph.position.set(0, signalConsts.nameOffsetY); } - codeGraph.style.fill = this.datas.codeColor; - codeGraph.setVectorFontSize(this.datas.codeFontSize); - codeGraph.anchor.set(0.5); - codeGraph.style.fill = this.datas.codeColor; - codeGraph.position.set(0, signalConsts.nameOffsetY); - this.position.set(this.datas.point.x, this.datas.point.y); + } + + doRepaint(): void { + this.paint(); } } export class SignalTemplate extends JlGraphicTemplate { - codeColor: string; - codeFontSize: number; - direction: string; - verticalLampPostLength: number; - levelLampPostLength: number; - lineWidth: number; - lampRadius: number; - lampPostColor: string; - lampColor: string; - humanControlColor: string; - fleetModeColor: string; - logicModeColor: string; - humanControlPath: number[]; - logicModeLineWidth: number; - logicModeDistance: number; - fleetModePath: number[]; - nameOffsetY: number; constructor() { super(Signal.Type); - this.codeColor = '0xff0000'; - this.codeFontSize = 11; - this.direction = 'right'; - this.verticalLampPostLength = signalConsts.verticalLampPostLength; - this.levelLampPostLength = signalConsts.levelLampPostLength; - this.lineWidth = signalConsts.lineWidth; - this.lampRadius = signalConsts.lampRadius; - this.lampPostColor = SignalColorEnum.lampPostColor; - this.lampColor = SignalColorEnum.lampColor; - this.humanControlColor = SignalColorEnum.humanControlColor; - this.fleetModeColor = SignalColorEnum.fleetModeColor; - this.logicModeColor = SignalColorEnum.logicModeColor; - this.humanControlPath = signalConsts.humanControlPath; - this.logicModeLineWidth = signalConsts.logicModeLineWidth; - this.logicModeDistance = signalConsts.logicModeDistance; - this.nameOffsetY = signalConsts.nameOffsetY; - const fleetModePath: number[] = []; - signalConsts.fleetModePath.forEach((item: number, index: number) => { - if (!(index % 2)) { - fleetModePath.push( - item + signalConsts.levelLampPostLength + signalConsts.lampRadius * 2 - ); - } else { - fleetModePath.push(item); - } - }); - this.fleetModePath = fleetModePath; } new(): Signal { return new Signal(); diff --git a/src/graphics/signal/SignalDrawAssistant.ts b/src/graphics/signal/SignalDrawAssistant.ts index 0e3de06..52b84e8 100644 --- a/src/graphics/signal/SignalDrawAssistant.ts +++ b/src/graphics/signal/SignalDrawAssistant.ts @@ -1,13 +1,10 @@ -import { FederatedPointerEvent, Point, Graphics, Color } from 'pixi.js'; +import { FederatedPointerEvent, Point } from 'pixi.js'; import { GraphicDrawAssistant, GraphicInteractionPlugin, JlDrawApp, JlGraphic, - KeyListener, - VectorText, } from 'src/jlgraphic'; - import { ISignalData, Signal, SignalTemplate } from './Signal'; export interface ISignalDrawOptions { @@ -18,41 +15,27 @@ export class SignalDraw extends GraphicDrawAssistant< SignalTemplate, ISignalData > { - point: Point = new Point(0, 0); - codeGraph: VectorText = new VectorText(''); - lampPost: Graphics = new Graphics(); - circularLamp: Graphics = new Graphics(); - humanControl: Graphics = new Graphics(); - fleetMode: Graphics = new Graphics(); - logicMode: Graphics = new Graphics(); - - // 快捷绘制 - keypListener: KeyListener = new KeyListener({ - value: 'KeyH', - global: true, - onPress: () => { - //this.graphicTemplate.hasdoor = true; - }, - }); + _signal: Signal | null = null; constructor(app: JlDrawApp, createData: () => ISignalData) { - super(app, new SignalTemplate(), createData, Signal.Type, '信号机Signal'); - this.container.addChild(this.codeGraph); - this.container.addChild(this.lampPost); - this.container.addChild(this.circularLamp); - this.container.addChild(this.humanControl); - this.container.addChild(this.fleetMode); - this.container.addChild(this.logicMode); + super( + app, + new SignalTemplate(), + createData, + 'svguse: ../../drawIcon.svg#icon-signal', + '信号机Signal' + ); + signalInteraction.init(app); } - bind(): void { - super.bind(); - this.app.addKeyboardListener(this.keypListener); - } - unbind(): void { - super.unbind(); - this.app.removeKeyboardListener(this.keypListener); + public get signal(): Signal { + if (!this._signal) { + this._signal = this.graphicTemplate.new(); + this.signal.loadData(this.createGraphicData()); + this.container.addChild(this.signal); + } + return this._signal; } clearCache(): void { @@ -61,87 +44,17 @@ export class SignalDraw extends GraphicDrawAssistant< onRightClick(): void { this.createAndStore(true); } - onLeftDown(e: FederatedPointerEvent): void { - const { x, y } = this.toCanvasCoordinates(e.global); - const p = new Point(x, y); - this.point = p; + onLeftUp(e: FederatedPointerEvent): void { + this.container.position.copyFrom(this.toCanvasCoordinates(e.global)); this.createAndStore(true); } redraw(p: Point): void { - const codeGraph = this.codeGraph; - const template = this.graphicTemplate; - this.point.set(p.x, p.y); - this.lampPost.lineStyle( - template.lineWidth, - new Color(template.lampPostColor) - ); - this.lampPost.moveTo(0, -template.verticalLampPostLength / 2); - this.lampPost.lineTo(0, template.verticalLampPostLength / 2); - - this.lampPost.moveTo(0, 0); - this.lampPost.lineTo(template.levelLampPostLength, 0); - - this.lampPost.position.set(p.x, p.y); - this.circularLamp.beginFill(template.lampColor, 1); - this.circularLamp.drawCircle( - template.levelLampPostLength + template.lampRadius, - 0, - template.lampRadius - ); - this.circularLamp.endFill(); - this.circularLamp.position.set(p.x, p.y); - this.humanControl.beginFill(template.humanControlColor, 1); - this.humanControl.drawPolygon(template.humanControlPath); - this.humanControl.endFill(); - this.humanControl.position.set(p.x, p.y); - this.fleetMode.beginFill(template.fleetModeColor, 1); - this.fleetMode.drawPolygon(template.fleetModePath); - this.fleetMode.endFill(); - this.fleetMode.position.set(p.x, p.y); - this.logicMode.lineStyle( - template.logicModeLineWidth, - new Color(template.logicModeColor) - ); - this.logicMode.moveTo( - template.levelLampPostLength + - template.lampRadius - - template.logicModeDistance, - template.logicModeDistance - ); - this.logicMode.lineTo( - template.levelLampPostLength + - template.lampRadius + - template.logicModeDistance, - -template.logicModeDistance - ); - this.logicMode.moveTo( - template.levelLampPostLength + - template.lampRadius - - template.logicModeDistance, - -template.logicModeDistance - ); - this.logicMode.lineTo( - template.levelLampPostLength + - template.lampRadius + - template.logicModeDistance, - template.logicModeDistance - ); - this.logicMode.position.set(p.x, p.y); - codeGraph.text = '信号机Signal'; - - codeGraph.style.fill = template.codeColor; - codeGraph.setVectorFontSize(template.codeFontSize); - codeGraph.anchor.set(0.5); - codeGraph.style.fill = template.codeColor; - codeGraph.position.set(p.x, p.y + template.nameOffsetY); + this.signal.paint(); + this.container.position.set(p.x, p.y); } prepareData(data: ISignalData): boolean { - const template = this.graphicTemplate; - data.point = this.point; - data.codeColor = template.codeColor; - data.codeFontSize = template.codeFontSize; - data.direction = template.direction; + data.transform = this.container.saveTransform(); return true; } } @@ -164,10 +77,26 @@ export class signalInteraction extends GraphicInteractionPlugin { 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('transformend', this.onScaleDragEnd, this); } + // 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'; } } diff --git a/src/jlgraphic/plugins/GraphicTransformPlugin.ts b/src/jlgraphic/plugins/GraphicTransformPlugin.ts index cbc3cbd..46deec5 100644 --- a/src/jlgraphic/plugins/GraphicTransformPlugin.ts +++ b/src/jlgraphic/plugins/GraphicTransformPlugin.ts @@ -255,9 +255,10 @@ export class GraphicTransformPlugin extends InteractionPluginBase { targets.forEach((target) => { if (target.shiftStartPoint) { target.shiftLastPoint = target.position.clone(); + const { dx, dy } = e.toTargetShiftLen(target.parent); target.position.set( - target.shiftStartPoint.x + e.dsx, - target.shiftStartPoint.y + e.dsy + target.shiftStartPoint.x + dx, + target.shiftStartPoint.y + dy ); } }); diff --git a/src/jlgraphic/plugins/InteractionPlugin.ts b/src/jlgraphic/plugins/InteractionPlugin.ts index 34a5f5e..70226d6 100644 --- a/src/jlgraphic/plugins/InteractionPlugin.ts +++ b/src/jlgraphic/plugins/InteractionPlugin.ts @@ -99,7 +99,7 @@ export class AppDragEvent { type: 'start' | 'move' | 'end'; target: DisplayObject; original: FederatedPointerEvent; - start: Point; + start: Point; // 画布坐标 constructor( app: GraphicApp, type: 'start' | 'move' | 'end', @@ -146,6 +146,9 @@ export class AppDragEvent { return this.original.pointerType === 'touch'; } + /** + * 终点坐标(画布坐标) + */ public get end(): Point { return this.app.toCanvasCoordinates(this.original.global); } @@ -167,6 +170,15 @@ export class AppDragEvent { public get dsy(): number { return this.end.y - this.start.y; } + + /** + * 转换为目标对象的位移距离 + */ + toTargetShiftLen(target: DisplayObject): { dx: number; dy: number } { + const sl = target.canvasToLocalPoint(this.start); + const el = target.canvasToLocalPoint(this.end); + return { dx: el.x - sl.x, dy: el.y - sl.y }; + } } /** diff --git a/yarn.lock b/yarn.lock index c5c9616..72e29cc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -185,7 +185,7 @@ "@pixi/graphics-extras@^7.2.4": version "7.2.4" - resolved "https://registry.yarnpkg.com/@pixi/graphics-extras/-/graphics-extras-7.2.4.tgz#72ac967992f239d3671d6e680ac891471619fe07" + resolved "https://registry.npmmirror.com/@pixi/graphics-extras/-/graphics-extras-7.2.4.tgz#72ac967992f239d3671d6e680ac891471619fe07" integrity sha512-0yT91yqF3KLiZI/iLRcfcYlTVpkVyWsfGtWEIorZs0eX+/zYx7um7EJ2h7tFORI/1FxA2maR4td5vpgCwOLJAQ== "@pixi/graphics@7.2.4": From d27db83c3a0182286080dd26b4680861bcb8b41a Mon Sep 17 00:00:00 2001 From: walker Date: Thu, 15 Jun 2023 14:18:32 +0800 Subject: [PATCH 24/44] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=AD=90=E5=85=83?= =?UTF-8?q?=E7=B4=A0=E6=97=8B=E8=BD=ACbug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/examples/app/index.ts | 3 +++ src/jlgraphic/plugins/GraphicTransformPlugin.ts | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/examples/app/index.ts b/src/examples/app/index.ts index 4895b10..5dc415a 100644 --- a/src/examples/app/index.ts +++ b/src/examples/app/index.ts @@ -281,6 +281,9 @@ export function loadDrawDatas(app: GraphicApp) { storage.stations.forEach((station) => { datas.push(new StationData(station)); }); + storage.signals.forEach((data) => { + datas.push(new SignalData(data)); + }); storage.stations.forEach((signal) => { datas.push(new StationData(signal)); }); diff --git a/src/jlgraphic/plugins/GraphicTransformPlugin.ts b/src/jlgraphic/plugins/GraphicTransformPlugin.ts index 46deec5..2b70f95 100644 --- a/src/jlgraphic/plugins/GraphicTransformPlugin.ts +++ b/src/jlgraphic/plugins/GraphicTransformPlugin.ts @@ -530,7 +530,8 @@ export class TransformPoints extends Container { // 旋转角度计算逻辑:取锚点y负方向一点作为旋转点,求旋转点和锚点所形成的直线与x轴角度,此角度+90°即为最终旋转角度,再将旋转角度限制到(-180,180]之间 let angle = angleToAxisx(this.rotatePivot, de.target.position); angle = Math.floor(angle / this.angleStep) * this.angleStep; - angle = (angle + 90) % 360; + const parentAngle = this.obj.parent.worldAngle; + angle = (angle + 90 - parentAngle) % 360; if (angle > 180) { angle = angle - 360; } From 558fb22de37a6e63b9d91282ce9cbc75de4d6c76 Mon Sep 17 00:00:00 2001 From: walker Date: Thu, 15 Jun 2023 14:30:37 +0800 Subject: [PATCH 25/44] =?UTF-8?q?=E8=B0=83=E6=95=B4=E5=AD=90=E5=85=83?= =?UTF-8?q?=E7=B4=A0=E5=8F=98=E6=8D=A2=E6=97=B6=EF=BC=8C=E7=88=B6=E5=85=83?= =?UTF-8?q?=E7=B4=A0=E5=8F=98=E6=8D=A2=E8=BE=85=E5=8A=A9=E6=B2=A1=E6=9C=89?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/jlgraphic/plugins/GraphicTransformPlugin.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/jlgraphic/plugins/GraphicTransformPlugin.ts b/src/jlgraphic/plugins/GraphicTransformPlugin.ts index 2b70f95..369d55b 100644 --- a/src/jlgraphic/plugins/GraphicTransformPlugin.ts +++ b/src/jlgraphic/plugins/GraphicTransformPlugin.ts @@ -461,6 +461,14 @@ export class TransformPoints extends Container { this.addChild(this.lScalePoint); this.obj.on('transformstart', this.onObjTransformStart, this); this.obj.on('transformend', this.onObjTransformEnd, this); + + if (this.obj.children && this.obj.children.length > 0) { + recursiveChildren(this.obj as Container, (child) => { + child.on('transformstart', this.onObjTransformStart, this); + child.on('transformend', this.onObjTransformEnd, this); + }); + } + this.obj.on('repaint', this.onGraphicRepaint, this); this.children.forEach((dp) => { dp.on('transformstart', this.onScaleDragStart, this); @@ -791,6 +799,12 @@ export class BoundsGraphic extends Graphics { this.visible = false; this.obj.on('transformstart', this.onObjTransformStart, this); this.obj.on('transformend', this.onObjTransformEnd, this); + if (this.obj.children && this.obj.children.length > 0) { + recursiveChildren(this.obj as Container, (child) => { + child.on('transformstart', this.onObjTransformStart, this); + child.on('transformend', this.onObjTransformEnd, this); + }); + } this.obj.on('repaint', this.onGraphicRepaint, this); graphic.addAssistantAppend(this); } From 8762ced5f8592db84ed19490cdb6c0322df874d8 Mon Sep 17 00:00:00 2001 From: walker Date: Thu, 15 Jun 2023 14:55:01 +0800 Subject: [PATCH 26/44] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=AD=90=E5=85=83?= =?UTF-8?q?=E7=B4=A0=E5=8F=98=E6=8D=A2=E7=88=B6=E5=85=83=E7=B4=A0=E8=BE=85?= =?UTF-8?q?=E5=8A=A9=E6=98=BE=E7=A4=BA=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/jlgraphic/plugins/CommonMousePlugin.ts | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/jlgraphic/plugins/CommonMousePlugin.ts b/src/jlgraphic/plugins/CommonMousePlugin.ts index 5160f41..bdd8747 100644 --- a/src/jlgraphic/plugins/CommonMousePlugin.ts +++ b/src/jlgraphic/plugins/CommonMousePlugin.ts @@ -194,18 +194,17 @@ 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); graphic.childEdit = false; this.graphicSelect = true; - } else if ( - !e.ctrlKey && - graphic.selected && - graphic.childEdit && - this.leftDownTarget.isGraphicChild() - ) { - if (this.leftDownTarget.selectable) { + } else if (!e.ctrlKey && graphic.selected && graphic.childEdit) { + if ( + this.leftDownTarget.isGraphicChild() && + this.leftDownTarget.selectable + ) { graphic.setChildSelected(this.leftDownTarget); } else { graphic.exitChildEdit(); From ff5ed78027861c0af12c5bcfb8c073e362d282b0 Mon Sep 17 00:00:00 2001 From: fan Date: Fri, 16 Jun 2023 10:27:59 +0800 Subject: [PATCH 27/44] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=B7=A5=E5=85=B7?= =?UTF-8?q?=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/jlgraphic/utils/GraphicUtils.ts | 65 +++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/src/jlgraphic/utils/GraphicUtils.ts b/src/jlgraphic/utils/GraphicUtils.ts index 9cd3ff8..254e4bf 100644 --- a/src/jlgraphic/utils/GraphicUtils.ts +++ b/src/jlgraphic/utils/GraphicUtils.ts @@ -542,3 +542,68 @@ export function angleOfIncludedAngle( } return angle; } + +/** + * 计算两点连线的法向量 + * @param point1 + * @param point2 + * @returns 单位法向量 + */ +export function getNormalVector( + point1: IPointData, + point2: IPointData +): number[] { + const x1 = point1.x, + y1 = point1.y; + const x2 = point2.x, + y2 = point2.y; + const length = Math.sqrt((y2 - y1) ** 2 + (x2 - x1) ** 2); + return [(y2 - y1) / length, (x1 - x2) / length]; +} + +/** + * 点延向量方向移动 + * @param point + * @param normal 单位向量 + * @param length 平移长度 + * @returns 移动后的点 + */ +export function movePointAlongNormal( + point: IPointData, + normal: number[], + length: number +): Point { + const newPoint = new Point( + point.x + length * normal[0], + point.y + length * normal[1] + ); + return newPoint; +} + +/** + * 计算两组点各自组成直线的相交点(若两线平行 返回第一组坐标第一个点) + * @param line1 两点坐标列表 + * @param line2 两点坐标列表 + * @returns 相交点 + */ +export function getIntersectionPoint(line1: number[], line2: number[]) { + const a1 = line1[0], + b1 = line1[1]; + const a2 = line1[2], + b2 = line1[3]; + const a3 = line2[0], + b3 = line2[1]; + const a4 = line2[2], + b4 = line2[3]; + const denominator = (a3 - a4) * (b1 - b2) - (a1 - a2) * (b3 - b4); + if (denominator === 0) { + return new Point(a1, b1); + } + const x = + ((a3 - a4) * (a2 * b1 - a1 * b2) - (a1 - a2) * (a4 * b3 - a3 * b4)) / + denominator; + const y = + ((b3 - b4) * (b2 * a1 - b1 * a2) - (b1 - b2) * (b4 * a3 - b3 * a4)) / + -denominator; + return new Point(x, y); +} From b7efe81e4c1a7dd8e686b5be4464b5347c3bc1d8 Mon Sep 17 00:00:00 2001 From: walker Date: Mon, 19 Jun 2023 09:43:35 +0800 Subject: [PATCH 28/44] =?UTF-8?q?=E6=B7=BB=E5=8A=A0websocket=E7=A4=BA?= =?UTF-8?q?=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 1 + quasar.config.js | 2 +- src/boot/axios.ts | 111 ++++++++++++++++++++++++ src/examples/app/configs/TokenManage.ts | 13 +++ src/examples/app/configs/UrlManage.ts | 13 +++ src/jlgraphic/message/WsMsgBroker.ts | 55 ++++++------ src/layouts/DrawLayout.vue | 13 +++ yarn.lock | 47 +++++++++- 8 files changed, 224 insertions(+), 31 deletions(-) create mode 100644 src/boot/axios.ts create mode 100644 src/examples/app/configs/TokenManage.ts create mode 100644 src/examples/app/configs/UrlManage.ts diff --git a/package.json b/package.json index 80d4257..2d5aa6c 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "@pixi/graphics-extras": "^7.2.4", "@quasar/extras": "^1.0.0", "@stomp/stompjs": "^7.0.0", + "axios": "^1.4.0", "google-protobuf": "^3.21.2", "js-base64": "^3.7.5", "pinia": "^2.0.11", diff --git a/quasar.config.js b/quasar.config.js index c8f1936..c5be092 100644 --- a/quasar.config.js +++ b/quasar.config.js @@ -28,7 +28,7 @@ module.exports = configure(function (/* ctx */) { // app boot file (/src/boot) // --> boot files are part of "main.js" // https://v2.quasar.dev/quasar-cli-vite/boot-files - boot: ['@pixi/graphics-extras'], + boot: ['axios', '@pixi/graphics-extras'], // https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#css css: ['app.scss'], diff --git a/src/boot/axios.ts b/src/boot/axios.ts new file mode 100644 index 0000000..d9a9d34 --- /dev/null +++ b/src/boot/axios.ts @@ -0,0 +1,111 @@ +import axios, { AxiosInstance } from 'axios'; +import { AxiosError } from 'axios'; +import { Dialog } from 'quasar'; +import { boot } from 'quasar/wrappers'; +import { getJwtToken } from 'src/examples/app/configs/TokenManage'; +import { getHttpBase } from 'src/examples/app/configs/UrlManage'; + +declare module '@vue/runtime-core' { + interface ComponentCustomProperties { + $axios: AxiosInstance; + } +} + +interface ErrorData { + status: number; + title: string; + detail: string; + code: number; +} + +export class ApiError { + origin: AxiosError; + /** + * 业务错误代码 + */ + code: number; + /** + * 错误信息 + */ + title: string; + /** + * 相关问题描述 + */ + detail?: string; + constructor(origin: AxiosError) { + this.origin = origin; + const response = origin.response; + if (response) { + const err = response.data as ErrorData; + this.code = err.code; + this.title = err.title; + this.detail = err.detail; + } else { + this.code = origin.status || -1; + this.title = origin.message; + } + } + + static from(err: AxiosError): ApiError { + return new ApiError(err); + } + + /** + * 是否认证失败(登录过期) + * @returns + */ + isAuthError(): boolean { + return this.origin.response?.status === 401; + } +} + +// Be careful when using SSR for cross-request state pollution +// due to creating a Singleton instance here; +// If any client changes this (global) instance, it might be a +// good idea to move this instance creation inside of the +// "export default () => {}" function below (which runs individually +// for each client) +const api = axios.create({ baseURL: getHttpBase() }); + +export default boot(({ app, router }) => { + // for use inside Vue files (Options API) through this.$axios and this.$api + + // 拦截请求,添加 + api.interceptors.request.use( + (config) => { + config.headers.Authorization = getJwtToken(); + return config; + }, + (err: AxiosError) => { + return Promise.reject(ApiError.from(err)); + } + ); + + api.interceptors.response.use( + (response) => { + return response; + }, + (err) => { + if (err.response && err.response.status === 401) { + Dialog.create({ + title: '认证失败', + message: '认证失败或登录超时,请重新登录', + persistent: true, + }).onOk(() => { + router.push({ name: 'login' }); + }); + } + return Promise.reject(ApiError.from(err)); + } + ); + + app.config.globalProperties.$axios = axios; + // ^ ^ ^ this will allow you to use this.$axios (for Vue Options API form) + // so you won't necessarily have to import axios in each vue file + + app.config.globalProperties.$api = api; + // ^ ^ ^ this will allow you to use this.$api (for Vue Options API form) + // so you can easily perform requests against your app's API +}); + +export { api }; diff --git a/src/examples/app/configs/TokenManage.ts b/src/examples/app/configs/TokenManage.ts new file mode 100644 index 0000000..11dddf9 --- /dev/null +++ b/src/examples/app/configs/TokenManage.ts @@ -0,0 +1,13 @@ +const JwtTokenKey = 'jwttoken'; + +export function saveJwtToken(token: string) { + sessionStorage.setItem(JwtTokenKey, `Bearer ${token}`); +} + +export function getJwtToken(): string | null { + return sessionStorage.getItem(JwtTokenKey); +} + +export function clearJwtToken(): void { + sessionStorage.removeItem(JwtTokenKey); +} diff --git a/src/examples/app/configs/UrlManage.ts b/src/examples/app/configs/UrlManage.ts new file mode 100644 index 0000000..6b4280b --- /dev/null +++ b/src/examples/app/configs/UrlManage.ts @@ -0,0 +1,13 @@ +function getHost(): string { + // return '192.168.3.7:9081'; + // return '192.168.3.47:9081'; + return '192.168.3.7:9081'; +} + +export function getHttpBase() { + return `http://${getHost()}`; +} + +export function getWebsocketUrl() { + return `ws://${getHost()}/ws-default`; +} diff --git a/src/jlgraphic/message/WsMsgBroker.ts b/src/jlgraphic/message/WsMsgBroker.ts index dc172f8..8b8cd53 100644 --- a/src/jlgraphic/message/WsMsgBroker.ts +++ b/src/jlgraphic/message/WsMsgBroker.ts @@ -9,8 +9,19 @@ import type { GraphicApp } from '../app/JlGraphicApp'; import { GraphicState } from '../core/JlGraphic'; export interface StompCliOption { - wsUrl: string; // websocket url - token: string; // 认证token + /** + * websocket url地址 + */ + wsUrl: string; + /** + * 认证token + */ + token?: string; + /** + * 认证失败处理 + * @returns + */ + onAuthenticationFailed?: () => void; reconnectDelay?: number; // 重连延时,默认3秒 heartbeatIncoming?: number; // 服务端过来的心跳间隔,默认30秒 heartbeatOutgoing?: number; // 到服务端的心跳间隔,默认30秒 @@ -32,7 +43,7 @@ export class StompCli { private static connected = false; static new(options: StompCliOption) { if (StompCli.enabled) { - // 以及启用 + // 已经启用 return; // throw new Error('websocket 已连接,若确实需要重新连接,请先断开StompCli.close再重新StompCli.new') } @@ -41,12 +52,8 @@ export class StompCli { StompCli.client = new StompClient({ brokerURL: StompCli.options.wsUrl, connectHeaders: { - Authorization: StompCli.options.token, - // Authorization: '' + Authorization: StompCli.options.token ? StompCli.options.token : '', }, - // debug: (str) => { - // console.log(str) - // } reconnectDelay: StompCli.options.reconnectDelay, heartbeatIncoming: StompCli.options.heartbeatIncoming, heartbeatOutgoing: StompCli.options.heartbeatOutgoing, @@ -61,19 +68,21 @@ export class StompCli { }; StompCli.client.onStompError = (frame: Frame) => { - console.error( - 'Stomp收到error消息,可能是认证失败(暂时没有判断具体错误类型,后需添加判断),关闭Stomp客户端', - frame - ); - StompCli.close(); + const errMsg = frame.headers['message']; + if (errMsg === '401') { + console.warn('认证失败,断开WebSocket连接'); + StompCli.close(); + if (StompCli.options.onAuthenticationFailed) { + StompCli.options.onAuthenticationFailed(); + } + } else { + console.error('收到Stomp错误消息', frame); + } }; StompCli.client.onDisconnect = (frame: Frame) => { console.log('Stomp 断开连接', frame); StompCli.connected = false; - // StompCli.appMsgBroker.forEach(broker => { - // broker.close(); - // }); }; StompCli.client.onWebSocketClose = (evt: CloseEvent) => { console.log('websocket 关闭', evt); @@ -82,9 +91,6 @@ export class StompCli { // websocket错误处理 StompCli.client.onWebSocketError = (err: Event) => { console.log('websocket错误', err); - // StompCli.appMsgBroker.forEach(broker => { - // broker.unsbuscribeAll(); - // }); }; StompCli.client.activate(); @@ -140,19 +146,10 @@ export class StompCli { // 状态订阅消息转换器 export type MessageConverter = (message: Uint8Array) => GraphicState[]; // 图形app状态订阅 -export class AppStateSubscription { +export interface AppStateSubscription { destination: string; messageConverter: MessageConverter; subscription?: StompSubscription; // 订阅成功对象,用于取消订阅 - constructor( - destination: string, - messageConverter: MessageConverter, - subscription?: StompSubscription - ) { - this.destination = destination; - this.messageConverter = messageConverter; - this.subscription = subscription; - } } /** diff --git a/src/layouts/DrawLayout.vue b/src/layouts/DrawLayout.vue index 8d23ae4..b6bc4a4 100644 --- a/src/layouts/DrawLayout.vue +++ b/src/layouts/DrawLayout.vue @@ -109,6 +109,8 @@ + + diff --git a/src/pages/UserRegister.vue b/src/pages/UserRegister.vue new file mode 100644 index 0000000..211a173 --- /dev/null +++ b/src/pages/UserRegister.vue @@ -0,0 +1,97 @@ + + + + + diff --git a/src/router/routes.ts b/src/router/routes.ts index 57f61e2..8997b3e 100644 --- a/src/router/routes.ts +++ b/src/router/routes.ts @@ -3,9 +3,22 @@ import { RouteRecordRaw } from 'vue-router'; const routes: RouteRecordRaw[] = [ { path: '/', + name: 'home', component: () => import('layouts/DrawLayout.vue'), }, + { + path: '/login', + name: 'login', + component: () => import('pages/UserLogin.vue'), + }, + + { + path: '/register', + name: 'register', + component: () => import('pages/UserRegister.vue'), + }, + // Always leave this as last one, // but you can also remove it { diff --git a/yarn.lock b/yarn.lock index bdd93a6..d43e0b2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -734,6 +734,11 @@ ajv@^8.0.1: require-from-string "^2.0.2" uri-js "^4.2.2" +alova@^2.7.1: + version "2.7.1" + resolved "https://registry.npmmirror.com/alova/-/alova-2.7.1.tgz#b91b7c80137a44b57792badda9e7ab09acf93f55" + integrity sha512-/+lbPt+u/c4rBx4fq83795Xuh8Ohj5ZB4tJ7pxL2BxLgRlLNCT9/I1yGrgJEz/jXTqIZHMI2EeBAIb/B0u76tw== + ansi-escapes@^4.2.1: version "4.3.2" resolved "https://registry.npmmirror.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" @@ -3156,6 +3161,11 @@ toidentifier@1.0.1: resolved "https://registry.npmmirror.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== +ts-md5@^1.3.1: + version "1.3.1" + resolved "https://registry.npmmirror.com/ts-md5/-/ts-md5-1.3.1.tgz#f5b860c0d5241dd9bb4e909dd73991166403f511" + integrity sha512-DiwiXfwvcTeZ5wCE0z+2A9EseZsztaiZtGrtSaY5JOD7ekPnR/GoIVD5gXZAlK9Na9Kvpo9Waz5rW64WKAWApg== + tslib@^1.8.1: version "1.14.1" resolved "https://registry.npmmirror.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" From a03cbbd3708f5cd4a09179f6ba6720bb32f7362f Mon Sep 17 00:00:00 2001 From: Yuan Date: Mon, 3 Jul 2023 17:00:13 +0800 Subject: [PATCH 38/44] =?UTF-8?q?=E5=88=A0=E9=99=A4=E5=B1=9E=E6=80=A7?= =?UTF-8?q?=E9=9D=A2=E6=9D=BF=E7=9A=84console.log?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/draw-app/properties/CanvasProperty.vue | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/components/draw-app/properties/CanvasProperty.vue b/src/components/draw-app/properties/CanvasProperty.vue index e5d4f11..f0540ba 100644 --- a/src/components/draw-app/properties/CanvasProperty.vue +++ b/src/components/draw-app/properties/CanvasProperty.vue @@ -58,19 +58,15 @@ const canvas = reactive({ }); onMounted(() => { - console.log('画布属性表单mounted'); const jc = drawStore.getJlCanvas(); canvas.width = jc.properties.width; canvas.height = jc.properties.height; canvas.backgroundColor = jc.properties.backgroundColor; }); -onUnmounted(() => { - console.log('画布属性表单unmounted'); -}); +onUnmounted(() => {}); function onUpdate() { - console.log('画布属性更新'); const app = drawStore.getDrawApp(); app.updateCanvasAndRecord({ ...canvas, From 1f302648b5a71a82b798b77fe238c5fc6e3081b4 Mon Sep 17 00:00:00 2001 From: Yuan Date: Mon, 3 Jul 2023 18:44:45 +0800 Subject: [PATCH 39/44] =?UTF-8?q?=E4=BA=A4=E4=BA=92=E6=8F=92=E4=BB=B6?= =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/jlgraphic/plugins/GraphicEditPlugin.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/jlgraphic/plugins/GraphicEditPlugin.ts b/src/jlgraphic/plugins/GraphicEditPlugin.ts index 9b1cc5b..c93631a 100644 --- a/src/jlgraphic/plugins/GraphicEditPlugin.ts +++ b/src/jlgraphic/plugins/GraphicEditPlugin.ts @@ -32,13 +32,13 @@ export abstract class GraphicEditPlugin< this.sortableChildren = true; this.graphic.on('transformstart', this.hideAll, this); this.graphic.on('transformend', this.showAll, this); - this.graphic.on('repaint', this.showAll, this); + this.graphic.on('repaint', this.updateEditedPointsPosition, this); } destroy(options?: boolean | IDestroyOptions | undefined): void { this.graphic.off('transformstart', this.hideAll, this); this.graphic.off('transformend', this.showAll, this); - this.graphic.off('repaint', this.showAll, this); + this.graphic.off('repaint', this.updateEditedPointsPosition, this); super.destroy(options); } From a7debf165e24e6200d7c986555f31c721792af38 Mon Sep 17 00:00:00 2001 From: walker Date: Thu, 6 Jul 2023 11:21:49 +0800 Subject: [PATCH 40/44] =?UTF-8?q?=E4=BF=AE=E6=94=B9websocket=E7=8A=B6?= =?UTF-8?q?=E6=80=81=E6=B6=88=E6=81=AF=E5=A4=84=E7=90=86=E6=9F=A5=E8=AF=A2?= =?UTF-8?q?=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/jlgraphic/app/JlGraphicApp.ts | 5 ++++- src/jlgraphic/core/GraphicStore.ts | 16 ++++++++++++++++ src/layouts/DrawLayout.vue | 4 ++++ 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/jlgraphic/app/JlGraphicApp.ts b/src/jlgraphic/app/JlGraphicApp.ts index c2b0af8..e073582 100644 --- a/src/jlgraphic/app/JlGraphicApp.ts +++ b/src/jlgraphic/app/JlGraphicApp.ts @@ -528,7 +528,10 @@ export class GraphicApp extends EventEmitter { */ handleGraphicStates(graphicStates: GraphicState[]) { graphicStates.forEach((state) => { - const list = this.queryStore.queryByIdOrCode(state.code); + const list = this.queryStore.queryByIdOrCodeAndType( + state.code, + state.graphicType + ); if (list.length == 0) { const template = this.getGraphicTemplatesByType(state.graphicType); const g = template.new(); diff --git a/src/jlgraphic/core/GraphicStore.ts b/src/jlgraphic/core/GraphicStore.ts index 979bd20..23e8889 100644 --- a/src/jlgraphic/core/GraphicStore.ts +++ b/src/jlgraphic/core/GraphicStore.ts @@ -37,6 +37,12 @@ export interface GraphicQueryStore { * @param v */ queryByIdOrCode(v: string): JlGraphic[]; + /** + * 根据id或code及类型查询图形 + * @param v + * @param type + */ + queryByIdOrCodeAndType(v: string, type: string): JlGraphic[]; /** * 根据code和类型获取图形 * @param code @@ -69,6 +75,7 @@ export class GraphicStore implements GraphicQueryStore { this.store = new Map(); this.relationManage = new RelationManage(app); } + /** * 获取所有图形对象 */ @@ -125,6 +132,15 @@ export class GraphicStore implements GraphicQueryStore { }); return list; } + queryByIdOrCodeAndType(s: string, type: string): JlGraphic[] { + const list: JlGraphic[] = []; + this.store.forEach((g) => { + if (g.isIdOrCode(s) && g.type === type) { + list.push(g); + } + }); + return list; + } queryByCodeAndType( code: string, type: string diff --git a/src/layouts/DrawLayout.vue b/src/layouts/DrawLayout.vue index a7f642f..fa1c35a 100644 --- a/src/layouts/DrawLayout.vue +++ b/src/layouts/DrawLayout.vue @@ -120,6 +120,7 @@