增加公共的绘制文字

This commit is contained in:
joylink_zhaoerwei 2024-09-13 19:02:43 +08:00
parent ba2ea93312
commit 9bb97141e1
9 changed files with 526 additions and 6 deletions

View File

@ -0,0 +1,27 @@
import { type GraphicDataBase } from 'src/drawApp/graphics/GraphicDataBase';
import { IDrawApp } from 'jl-graphic';
import { onMounted, onUnmounted, reactive, toRaw } from 'vue';
export function useFormData<T extends GraphicDataBase>(
source: T,
app: IDrawApp
) {
const data = reactive<T>(source);
onMounted(() => {
app.bindFormData(data);
});
onUnmounted(() => {
app.unbindFormData(data);
});
function onUpdate() {
const graphic = app.queryStore.queryById(data.id);
if (graphic) {
app.updateGraphicAndRecord(graphic, toRaw(data));
}
}
return { data, onUpdate };
}

View File

@ -22,7 +22,11 @@
</q-card-section>
</template>
<template v-else-if="drawStore.selectedGraphics.length === 1">
<q-card-section> </q-card-section>
<q-card-section>
<iscs-text-property
v-if="drawStore.selectedGraphicType === TextContent.Type"
/>
</q-card-section>
</template>
<template v-else-if="drawStore.selectedGraphics.length > 1">
<multiple-select-property></multiple-select-property>
@ -34,6 +38,8 @@
<script setup lang="ts">
import { useDrawStore } from 'src/stores/draw-store';
import CanvasProperty from './properties/CanvasProperty.vue';
import IscsTextProperty from './properties/IscsTextProperty.vue';
import { TextContent } from 'src/graphics/textContent/TextContent';
const drawStore = useDrawStore();
</script>

View File

@ -0,0 +1,50 @@
<template>
<q-form class="q-gutter-sm">
<q-input outlined readonly v-model="textContentModel.id" label="id" />
<q-input
outlined
v-model="textContentModel.content"
@update:model-value="onUpdate"
label="Iscs文字内容"
lazy-rules
/>
<q-input
outlined
v-model="textContentModel.color"
@blur="onUpdate"
label="Iscs文字颜色"
lazy-rules
>
<template v-slot:append>
<q-icon name="colorize" class="cursor-pointer">
<q-popup-proxy cover transition-show="scale" transition-hide="scale">
<q-color
@update:model-value="onUpdate"
v-model="textContentModel.color"
/>
</q-popup-proxy>
</q-icon>
</template>
</q-input>
<q-input
v-model.number="textContentModel.fontSize"
type="number"
outlined
@blur="onUpdate"
label="Iscs文字大小"
lazy-rules
/>
</q-form>
</template>
<script setup lang="ts">
import { useDrawStore } from 'src/stores/draw-store';
import { useFormData } from 'src/components/DrawAppFormUtils';
import { IscsTextData } from 'src/drawApp/graphics/IscsTextContentInteraction';
const tccDrawStore = useDrawStore();
const { data: textContentModel, onUpdate } = useFormData(
new IscsTextData(),
tccDrawStore.getDrawApp()
);
</script>

View File

@ -10,6 +10,12 @@ import { toStorageTransform } from './graphics/GraphicDataBase';
import { Arrow, ArrowTemplate } from 'src/graphics/arrow/Arrow';
import { ArrowData } from './graphics/ArrowInteraction';
import { ArrowDraw } from 'src/graphics/arrow/ArrowDrawAssistant';
import {
TextContent,
TextContentTemplate,
} from 'src/graphics/textContent/TextContent';
import { TextContentDraw } from 'src/graphics/textContent/TextContentDrawAssistant';
import { IscsTextData } from './graphics/IscsTextContentInteraction';
const UndoOptions: MenuItemOptions = {
name: '撤销',
@ -35,6 +41,7 @@ export const DefaultCanvasMenu = new ContextMenu({
export function initCommonDrawApp(app: IDrawApp) {
new ArrowDraw(app, new ArrowTemplate(new ArrowData()));
new TextContentDraw(app, new TextContentTemplate(new IscsTextData()));
// 画布右键菜单
app.registerMenu(DefaultCanvasMenu);
@ -65,6 +72,9 @@ export function loadCommonDrawDatas(
storage.arrows.forEach((arrow) => {
datas.push(new ArrowData(arrow));
});
storage.iscsTexts.forEach((iscsText) => {
datas.push(new IscsTextData(iscsText));
});
return datas;
}
@ -79,9 +89,12 @@ export function saveCommonDrawDatas(app: IDrawApp) {
});
const graphics = app.queryStore.getAllGraphics();
graphics.forEach((g) => {
if (Arrow.Type === g.type) {
const arrowData = (g as Arrow).saveData();
if (g instanceof Arrow) {
const arrowData = g.saveData();
storage.arrows.push((arrowData as ArrowData).data);
} else if (g instanceof TextContent) {
const textContentData = g.saveData();
storage.iscsTexts.push((textContentData as IscsTextData).data);
}
});

View File

@ -0,0 +1,59 @@
import * as pb_1 from 'google-protobuf';
import {
ITextContentData,
TextContent,
} from 'src/graphics/textContent/TextContent';
import { iscsGraphicData } from 'src/protos/iscs_graphic_data';
import { GraphicDataBase } from './GraphicDataBase';
export class IscsTextData extends GraphicDataBase implements ITextContentData {
constructor(data?: iscsGraphicData.IscsText) {
let pslText;
if (data) {
pslText = data;
} else {
pslText = new iscsGraphicData.IscsText({
common: GraphicDataBase.defaultCommonInfo(TextContent.Type),
});
}
super(pslText);
}
public get data(): iscsGraphicData.IscsText {
return this.getData<iscsGraphicData.IscsText>();
}
get code(): string {
return this.data.code;
}
set code(v: string) {
this.data.code = v;
}
get content(): string {
return this.data.content;
}
set content(v: string) {
this.data.content = v;
}
get color(): string {
return this.data.color;
}
set color(v: string) {
this.data.color = v;
}
get fontSize(): number {
return this.data.fontSize;
}
set fontSize(v: number) {
this.data.fontSize = v;
}
clone(): IscsTextData {
return new IscsTextData(this.data.cloneMessage());
}
copyFrom(data: IscsTextData): void {
pb_1.Message.copyInto(data.data, this.data);
}
eq(other: IscsTextData): boolean {
return pb_1.Message.equals(this.data, other.data);
}
}

View File

@ -0,0 +1,71 @@
import {
GraphicData,
JlGraphic,
JlGraphicTemplate,
VectorText,
} from 'jl-graphic';
export interface ITextContentData extends GraphicData {
get code(): string; // 编号
set code(v: string);
get content(): string;
set content(v: string);
get color(): string;
set color(v: string);
get fontSize(): number;
set fontSize(v: number);
clone(): ITextContentData;
copyFrom(data: ITextContentData): void;
eq(other: ITextContentData): boolean;
}
const textContentConsts = {
defaultContent: '请填写内容',
defaultColor: '0xcccccc',
defaultFontSize: 14,
};
export class TextContent extends JlGraphic {
static Type = 'textContent';
contentGraph: VectorText = new VectorText('');
constructor() {
super(TextContent.Type);
this.addChild(this.contentGraph);
}
get datas(): ITextContentData {
return this.getDatas<ITextContentData>();
}
get states(): ITextContentData {
return this.getStates<ITextContentData>();
}
doRepaint(): void {
const contentGraph = this.contentGraph;
contentGraph.text = this.datas?.content || textContentConsts.defaultContent;
let color = textContentConsts.defaultColor;
if (this.datas?.color) {
color = this.datas.color.replace('#', '0x');
}
contentGraph.style.fill = color;
contentGraph.setVectorFontSize(
this.datas?.fontSize || textContentConsts.defaultFontSize
);
contentGraph.anchor.set(0.5);
}
}
export class TextContentTemplate extends JlGraphicTemplate<TextContent> {
color: string;
fontSize: number;
constructor(dataTemplate: ITextContentData) {
super(TextContent.Type, {
dataTemplate,
});
this.color = '#cccccc';
this.fontSize = 14;
}
new(): TextContent {
const textContent = new TextContent();
textContent.loadData(this.datas);
return textContent;
}
}

View File

@ -0,0 +1,108 @@
import { FederatedPointerEvent, Point } from 'pixi.js';
import {
AbsorbableLine,
AbsorbablePosition,
GraphicDrawAssistant,
GraphicInteractionPlugin,
IDrawApp,
JlGraphic,
} from 'jl-graphic';
import {
ITextContentData,
TextContent,
TextContentTemplate,
} from './TextContent';
export interface ITextContentDrawOptions {
newData: () => ITextContentData;
}
export class TextContentDraw extends GraphicDrawAssistant<
TextContentTemplate,
ITextContentData
> {
codeGraph: TextContent;
constructor(app: IDrawApp, template: TextContentTemplate) {
super(app, template, 'translate', '文字TextContent');
this.codeGraph = this.graphicTemplate.new();
this.container.addChild(this.codeGraph);
textContentInteraction.init(app);
}
bind(): void {
super.bind();
this.codeGraph.loadData(this.graphicTemplate.datas);
this.codeGraph.doRepaint();
}
clearCache(): void {
//this.codeGraph.destroy();
}
onLeftDown(e: FederatedPointerEvent): void {
this.container.position.copyFrom(this.toCanvasCoordinates(e.global));
this.createAndStore(true);
}
redraw(p: Point): void {
this.container.position.copyFrom(p);
}
prepareData(data: ITextContentData): boolean {
const template = this.graphicTemplate;
data.color = template.color;
data.fontSize = template.fontSize;
data.transform = this.container.saveTransform();
return true;
}
}
function buildAbsorbablePositions(station: TextContent): AbsorbablePosition[] {
const aps: AbsorbablePosition[] = [];
const stations = station.queryStore.queryByType<TextContent>(
TextContent.Type
);
const { width } = station.getGraphicApp().canvas;
stations.forEach((other) => {
if (other.id == station.id) {
return;
}
const ps = other.datas.transform.position;
const xs = new AbsorbableLine({ x: 0, y: ps.y }, { x: width, y: ps.y });
aps.push(xs);
});
return aps;
}
export class textContentInteraction extends GraphicInteractionPlugin<TextContent> {
static Name = 'textContent_transform';
constructor(app: IDrawApp) {
super(textContentInteraction.Name, app);
}
static init(app: IDrawApp) {
return new textContentInteraction(app);
}
filter(...grahpics: JlGraphic[]): TextContent[] | undefined {
return grahpics
.filter((g) => g.type === TextContent.Type)
.map((g) => g as TextContent);
}
bind(g: TextContent): void {
g.eventMode = 'static';
g.cursor = 'pointer';
g.scalable = true;
g.rotatable = true;
g.on('selected', this.onSelected, this);
}
unbind(g: TextContent): void {
g.eventMode = 'none';
g.scalable = false;
g.rotatable = false;
g.off('selected', this.onSelected, this);
}
onSelected(): void {
const textContent = this.app.selectedGraphics[0] as TextContent;
this.app.setOptions({
absorbablePositions: buildAbsorbablePositions(textContent),
});
}
}

View File

@ -112,6 +112,7 @@ import { successNotify } from 'src/utils/CommonNotify';
import { useQuasar } from 'quasar';
import { useDrawStore } from 'src/stores/draw-store';
import { Arrow } from 'src/graphics/arrow/Arrow';
import { TextContent } from 'src/graphics/textContent/TextContent';
const $q = useQuasar();
const route = useRoute();
@ -196,7 +197,7 @@ onMounted(() => {
} else {
drawStore.setDraftId(null);
}
const drawAssistantsTypes = [Arrow.Type];
const drawAssistantsTypes = [Arrow.Type,TextContent.Type];
drawAssistantsTypes.forEach((type) => {
const drawAssistant = drawStore.getDrawApp().getDrawAssistant(type);
if (drawAssistant) {

View File

@ -1,6 +1,6 @@
/**
* Generated by the protoc-gen-ts. DO NOT EDIT!
* compiler version: 4.22.0
* compiler version: 5.27.4
* source: iscs_graphic_data.proto
* git: https://github.com/thesayyn/protoc-gen-ts */
import * as pb_1 from "google-protobuf";
@ -11,9 +11,10 @@ export namespace iscsGraphicData {
canvas?: Canvas;
UniqueIdPrefix?: UniqueIdOfStationLayout;
arrows?: Arrow[];
iscsTexts?: IscsText[];
}) {
super();
pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [3], this.#one_of_decls);
pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [3, 4], this.#one_of_decls);
if (!Array.isArray(data) && typeof data == "object") {
if ("canvas" in data && data.canvas != undefined) {
this.canvas = data.canvas;
@ -24,6 +25,9 @@ export namespace iscsGraphicData {
if ("arrows" in data && data.arrows != undefined) {
this.arrows = data.arrows;
}
if ("iscsTexts" in data && data.iscsTexts != undefined) {
this.iscsTexts = data.iscsTexts;
}
}
}
get canvas() {
@ -50,10 +54,17 @@ export namespace iscsGraphicData {
set arrows(value: Arrow[]) {
pb_1.Message.setRepeatedWrapperField(this, 3, value);
}
get iscsTexts() {
return pb_1.Message.getRepeatedWrapperField(this, IscsText, 4) as IscsText[];
}
set iscsTexts(value: IscsText[]) {
pb_1.Message.setRepeatedWrapperField(this, 4, value);
}
static fromObject(data: {
canvas?: ReturnType<typeof Canvas.prototype.toObject>;
UniqueIdPrefix?: ReturnType<typeof UniqueIdOfStationLayout.prototype.toObject>;
arrows?: ReturnType<typeof Arrow.prototype.toObject>[];
iscsTexts?: ReturnType<typeof IscsText.prototype.toObject>[];
}): IscsGraphicStorage {
const message = new IscsGraphicStorage({});
if (data.canvas != null) {
@ -65,6 +76,9 @@ export namespace iscsGraphicData {
if (data.arrows != null) {
message.arrows = data.arrows.map(item => Arrow.fromObject(item));
}
if (data.iscsTexts != null) {
message.iscsTexts = data.iscsTexts.map(item => IscsText.fromObject(item));
}
return message;
}
toObject() {
@ -72,6 +86,7 @@ export namespace iscsGraphicData {
canvas?: ReturnType<typeof Canvas.prototype.toObject>;
UniqueIdPrefix?: ReturnType<typeof UniqueIdOfStationLayout.prototype.toObject>;
arrows?: ReturnType<typeof Arrow.prototype.toObject>[];
iscsTexts?: ReturnType<typeof IscsText.prototype.toObject>[];
} = {};
if (this.canvas != null) {
data.canvas = this.canvas.toObject();
@ -82,6 +97,9 @@ export namespace iscsGraphicData {
if (this.arrows != null) {
data.arrows = this.arrows.map((item: Arrow) => item.toObject());
}
if (this.iscsTexts != null) {
data.iscsTexts = this.iscsTexts.map((item: IscsText) => item.toObject());
}
return data;
}
serialize(): Uint8Array;
@ -94,6 +112,8 @@ export namespace iscsGraphicData {
writer.writeMessage(2, this.UniqueIdPrefix, () => this.UniqueIdPrefix.serialize(writer));
if (this.arrows.length)
writer.writeRepeatedMessage(3, this.arrows, (item: Arrow) => item.serialize(writer));
if (this.iscsTexts.length)
writer.writeRepeatedMessage(4, this.iscsTexts, (item: IscsText) => item.serialize(writer));
if (!w)
return writer.getResultBuffer();
}
@ -112,6 +132,9 @@ export namespace iscsGraphicData {
case 3:
reader.readMessage(message.arrows, () => pb_1.Message.addToRepeatedWrapperField(message, 3, Arrow.deserialize(reader), Arrow));
break;
case 4:
reader.readMessage(message.iscsTexts, () => pb_1.Message.addToRepeatedWrapperField(message, 4, IscsText.deserialize(reader), IscsText));
break;
default: reader.skipField();
}
}
@ -1098,4 +1121,166 @@ export namespace iscsGraphicData {
return Arrow.deserialize(bytes);
}
}
export class IscsText extends pb_1.Message {
#one_of_decls: number[][] = [];
constructor(data?: any[] | {
common?: CommonInfo;
code?: string;
content?: string;
color?: string;
fontSize?: number;
}) {
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 ("content" in data && data.content != undefined) {
this.content = data.content;
}
if ("color" in data && data.color != undefined) {
this.color = data.color;
}
if ("fontSize" in data && data.fontSize != undefined) {
this.fontSize = data.fontSize;
}
}
}
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 content() {
return pb_1.Message.getFieldWithDefault(this, 3, "") as string;
}
set content(value: string) {
pb_1.Message.setField(this, 3, value);
}
get color() {
return pb_1.Message.getFieldWithDefault(this, 4, "") as string;
}
set color(value: string) {
pb_1.Message.setField(this, 4, value);
}
get fontSize() {
return pb_1.Message.getFieldWithDefault(this, 5, 0) as number;
}
set fontSize(value: number) {
pb_1.Message.setField(this, 5, value);
}
static fromObject(data: {
common?: ReturnType<typeof CommonInfo.prototype.toObject>;
code?: string;
content?: string;
color?: string;
fontSize?: number;
}): IscsText {
const message = new IscsText({});
if (data.common != null) {
message.common = CommonInfo.fromObject(data.common);
}
if (data.code != null) {
message.code = data.code;
}
if (data.content != null) {
message.content = data.content;
}
if (data.color != null) {
message.color = data.color;
}
if (data.fontSize != null) {
message.fontSize = data.fontSize;
}
return message;
}
toObject() {
const data: {
common?: ReturnType<typeof CommonInfo.prototype.toObject>;
code?: string;
content?: string;
color?: string;
fontSize?: number;
} = {};
if (this.common != null) {
data.common = this.common.toObject();
}
if (this.code != null) {
data.code = this.code;
}
if (this.content != null) {
data.content = this.content;
}
if (this.color != null) {
data.color = this.color;
}
if (this.fontSize != null) {
data.fontSize = this.fontSize;
}
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.content.length)
writer.writeString(3, this.content);
if (this.color.length)
writer.writeString(4, this.color);
if (this.fontSize != 0)
writer.writeInt32(5, this.fontSize);
if (!w)
return writer.getResultBuffer();
}
static deserialize(bytes: Uint8Array | pb_1.BinaryReader): IscsText {
const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new IscsText();
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.content = reader.readString();
break;
case 4:
message.color = reader.readString();
break;
case 5:
message.fontSize = reader.readInt32();
break;
default: reader.skipField();
}
}
return message;
}
serializeBinary(): Uint8Array {
return this.serialize();
}
static deserializeBinary(bytes: Uint8Array): IscsText {
return IscsText.deserialize(bytes);
}
}
}