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] =?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; + } +}