实现图形模板表单、画布表单、link表单及drawStore相关功能
This commit is contained in:
parent
7ece0182b9
commit
39d68c8fe0
@ -1,21 +1,45 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-if="drawStore.drawMode" class="q-pa-md">
|
<!-- 绘制图形模板属性 -->
|
||||||
<template v-if="drawStore.drawGraphicType === Link.Type">
|
<div v-if="drawStore.drawMode">
|
||||||
<link-template></link-template>
|
<q-card flat>
|
||||||
</template>
|
<q-card-section>
|
||||||
|
<div class="text-h6">{{ drawStore.drawGraphicName + ' 模板' }}</div>
|
||||||
|
</q-card-section>
|
||||||
|
<q-separator inset></q-separator>
|
||||||
|
<q-card-section>
|
||||||
|
<template v-if="drawStore.drawGraphicType === Link.Type">
|
||||||
|
<link-template></link-template>
|
||||||
|
</template>
|
||||||
|
</q-card-section>
|
||||||
|
</q-card>
|
||||||
|
</div>
|
||||||
|
<!-- 画布或图形对象属性 -->
|
||||||
|
<div v-else-if="drawStore.selectedGraphics !== null">
|
||||||
|
<q-card flat>
|
||||||
|
<q-card-section>
|
||||||
|
<div class="text-h6">{{ drawStore.selectedObjName + ' 属性' }}</div>
|
||||||
|
</q-card-section>
|
||||||
|
<q-separator inset></q-separator>
|
||||||
|
<template v-if="drawStore.selectedGraphics.length === 0">
|
||||||
|
<q-card-section>
|
||||||
|
<canvas-property></canvas-property>
|
||||||
|
</q-card-section>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="drawStore.selectedGraphics.length === 1">
|
||||||
|
<q-card-section v-if="drawStore.selectedGraphicType === Link.Type">
|
||||||
|
<link-property></link-property>
|
||||||
|
</q-card-section>
|
||||||
|
</template>
|
||||||
|
</q-card>
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="q-pa-md"></div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import LinkTemplate from './templates/LinkTemplate.vue';
|
import LinkTemplate from './templates/LinkTemplate.vue';
|
||||||
|
import CanvasProperty from './properties/CanvasProperty.vue';
|
||||||
|
import LinkProperty from './properties/LinkProperty.vue';
|
||||||
import { Link } from 'src/graphics/link/Link';
|
import { Link } from 'src/graphics/link/Link';
|
||||||
import { useDrawStore } from 'src/stores/draw-store';
|
import { useDrawStore } from 'src/stores/draw-store';
|
||||||
import { onMounted, ref } from 'vue';
|
|
||||||
|
|
||||||
const drawStore = useDrawStore();
|
const drawStore = useDrawStore();
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
console.log('绘制属性组件mounted');
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
80
src/components/draw-app/properties/CanvasProperty.vue
Normal file
80
src/components/draw-app/properties/CanvasProperty.vue
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
<template>
|
||||||
|
<q-form>
|
||||||
|
<q-input
|
||||||
|
outlined
|
||||||
|
v-model.number="canvas.width"
|
||||||
|
@blur="onUpdate"
|
||||||
|
label="画布宽 *"
|
||||||
|
lazy-rules
|
||||||
|
:rules="[(val) => (val && val > 0) || '画布宽必须大于0']"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<q-input
|
||||||
|
outlined
|
||||||
|
type="number"
|
||||||
|
v-model.number="canvas.height"
|
||||||
|
@blur="onUpdate"
|
||||||
|
label="画布高 *"
|
||||||
|
lazy-rules
|
||||||
|
:rules="[(val) => val > 0 || '画布高必须大于0']"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<q-input
|
||||||
|
outlined
|
||||||
|
v-model="canvas.backgroundColor"
|
||||||
|
@blur="onUpdate"
|
||||||
|
label="画布背景色 *"
|
||||||
|
lazy-rules
|
||||||
|
:rules="[(val) => (val && val.length > 0) || '画布背景色必须设置']"
|
||||||
|
>
|
||||||
|
<template v-slot:append>
|
||||||
|
<q-icon name="colorize" class="cursor-pointer">
|
||||||
|
<q-popup-proxy cover transition-show="scale" transition-hide="scale">
|
||||||
|
<q-color
|
||||||
|
:model-value="canvas.backgroundColor"
|
||||||
|
@change="
|
||||||
|
(val) => {
|
||||||
|
canvas.backgroundColor = val;
|
||||||
|
onUpdate();
|
||||||
|
}
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
</q-popup-proxy>
|
||||||
|
</q-icon>
|
||||||
|
</template>
|
||||||
|
</q-input>
|
||||||
|
</q-form>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { useDrawStore } from 'src/stores/draw-store';
|
||||||
|
import { onMounted, onUnmounted, reactive } from 'vue';
|
||||||
|
const drawStore = useDrawStore();
|
||||||
|
|
||||||
|
const canvas = reactive({
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
backgroundColor: '#ffffff',
|
||||||
|
});
|
||||||
|
|
||||||
|
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');
|
||||||
|
});
|
||||||
|
|
||||||
|
function onUpdate() {
|
||||||
|
console.log('画布属性更新');
|
||||||
|
const app = drawStore.getDrawApp();
|
||||||
|
app.updateCanvasAndRecord({
|
||||||
|
...canvas,
|
||||||
|
viewportTransform: app.canvas.properties.viewportTransform,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
@ -1,65 +1,96 @@
|
|||||||
<template>
|
<template>
|
||||||
<q-form @submit="onSubmit" @reset="onReset" class="q-gutter-md">
|
<q-form>
|
||||||
|
<q-input outlined readonly v-model="linkModel.id" label="id" :rules="[]" />
|
||||||
<q-input
|
<q-input
|
||||||
filled
|
outlined
|
||||||
v-model="name"
|
v-model.number="linkModel.lineWidth"
|
||||||
label="Your name *"
|
|
||||||
hint="Name and surname"
|
|
||||||
lazy-rules
|
|
||||||
:rules="[(val) => (val && val.length > 0) || 'Please type something']"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<q-input
|
|
||||||
filled
|
|
||||||
type="number"
|
type="number"
|
||||||
v-model="age"
|
@blur="onUpdate"
|
||||||
label="Your age *"
|
label="线宽"
|
||||||
lazy-rules
|
lazy-rules
|
||||||
:rules="[
|
:rules="[(val) => (val && val > 0) || '画布宽必须大于0']"
|
||||||
(val) => (val !== null && val !== '') || 'Please type your age',
|
|
||||||
(val) => (val > 0 && val < 100) || 'Please type a real age',
|
|
||||||
]"
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<q-toggle v-model="accept" label="I accept the license and terms" />
|
<q-input
|
||||||
|
outlined
|
||||||
|
v-model="linkModel.lineColor"
|
||||||
|
@blur="onUpdate"
|
||||||
|
label="线色"
|
||||||
|
lazy-rules
|
||||||
|
:rules="[(val) => (val && val.length > 0) || '线色不能为空']"
|
||||||
|
>
|
||||||
|
<template v-slot:append>
|
||||||
|
<q-icon name="colorize" class="cursor-pointer">
|
||||||
|
<q-popup-proxy cover transition-show="scale" transition-hide="scale">
|
||||||
|
<q-color
|
||||||
|
v-model="linkModel.lineColor"
|
||||||
|
@change="
|
||||||
|
(val) => {
|
||||||
|
linkModel.lineColor = val;
|
||||||
|
onUpdate();
|
||||||
|
}
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
</q-popup-proxy>
|
||||||
|
</q-icon>
|
||||||
|
</template>
|
||||||
|
</q-input>
|
||||||
|
|
||||||
<div>
|
<!-- <q-btn-toggle
|
||||||
<q-btn label="Submit" type="submit" color="primary" />
|
disable
|
||||||
<q-btn label="Reset" type="reset" color="primary" flat class="q-ml-sm" />
|
v-model="linkModel.curve"
|
||||||
</div>
|
:options="[
|
||||||
|
{ label: '直线', value: false },
|
||||||
|
{ label: '曲线', value: true },
|
||||||
|
]"
|
||||||
|
/> -->
|
||||||
|
|
||||||
|
<q-input
|
||||||
|
v-if="linkModel.curve"
|
||||||
|
outlined
|
||||||
|
v-model.number="linkModel.segmentsCount"
|
||||||
|
type="number"
|
||||||
|
@blur="onUpdate"
|
||||||
|
label="曲线分段数量"
|
||||||
|
lazy-rules
|
||||||
|
:rules="[(val) => (val && val > 0) || '曲线分段数量必须大于0']"
|
||||||
|
/>
|
||||||
</q-form>
|
</q-form>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useQuasar } from 'quasar';
|
import { LinkData } from 'src/examples/app/graphics/LinkInteraction';
|
||||||
import { ref } from 'vue';
|
import { Link } from 'src/graphics/link/Link';
|
||||||
const $q = useQuasar();
|
import { useDrawStore } from 'src/stores/draw-store';
|
||||||
|
import { onMounted, reactive, watch } from 'vue';
|
||||||
|
|
||||||
const name = ref(null);
|
const drawStore = useDrawStore();
|
||||||
const age = ref(null);
|
const linkModel = reactive(new LinkData());
|
||||||
const accept = ref(false);
|
|
||||||
|
|
||||||
function onSubmit() {
|
drawStore.$subscribe;
|
||||||
if (accept.value !== true) {
|
watch(
|
||||||
$q.notify({
|
() => drawStore.selectedGraphic,
|
||||||
color: 'red-5',
|
(val) => {
|
||||||
textColor: 'white',
|
if (val && val.type == Link.Type) {
|
||||||
icon: 'warning',
|
// console.log('link变更');
|
||||||
message: 'You need to accept the license and terms first',
|
linkModel.copyFrom(val.saveData() as LinkData);
|
||||||
});
|
}
|
||||||
} else {
|
}
|
||||||
$q.notify({
|
);
|
||||||
color: 'green-4',
|
|
||||||
textColor: 'white',
|
onMounted(() => {
|
||||||
icon: 'cloud_done',
|
// console.log('link 属性表单 mounted');
|
||||||
message: 'Submitted',
|
const link = drawStore.selectedGraphic as Link;
|
||||||
});
|
if (link) {
|
||||||
|
linkModel.copyFrom(link.saveData());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function onUpdate() {
|
||||||
|
console.log('link 属性更新');
|
||||||
|
const link = drawStore.selectedGraphic as Link;
|
||||||
|
if (link) {
|
||||||
|
drawStore.getDrawApp().updateGraphicAndRecord(link, linkModel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function onReset() {
|
|
||||||
name.value = null;
|
|
||||||
age.value = null;
|
|
||||||
accept.value = false;
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,57 +1,96 @@
|
|||||||
<template>
|
<template>
|
||||||
<q-form class="q-gutter-md">
|
<q-form>
|
||||||
<q-input
|
<q-input
|
||||||
filled
|
outlined
|
||||||
v-model.number="template.lineWidth"
|
v-model.number="template.lineWidth"
|
||||||
type="number"
|
type="number"
|
||||||
|
@blur="onUpdate"
|
||||||
label="线宽 *"
|
label="线宽 *"
|
||||||
lazy-rules
|
lazy-rules
|
||||||
:rules="[(val) => (val && val.length > 0) || '线宽必须大于0']"
|
:rules="[(val) => (val && val > 0) || '线宽必须大于0']"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<q-input
|
<q-input
|
||||||
filled
|
outlined
|
||||||
v-model="template.lineColor"
|
v-model="template.lineColor"
|
||||||
|
@blur="onUpdate"
|
||||||
label="线色 *"
|
label="线色 *"
|
||||||
lazy-rules
|
lazy-rules
|
||||||
:rules="[(val) => (val && val.length > 0) || '线色必须设置']"
|
:rules="[(val) => (val && val.length > 0) || '线色不能为空']"
|
||||||
>
|
>
|
||||||
<template v-slot:append>
|
<template v-slot:append>
|
||||||
<q-icon name="colorize" class="cursor-pointer">
|
<q-icon name="colorize" class="cursor-pointer">
|
||||||
<q-popup-proxy cover transition-show="scale" transition-hide="scale">
|
<q-popup-proxy cover transition-show="scale" transition-hide="scale">
|
||||||
<q-color v-model="template.lineColor" />
|
<q-color
|
||||||
|
v-model="template.lineColor"
|
||||||
|
@change="
|
||||||
|
(val) => {
|
||||||
|
template.lineColor = val;
|
||||||
|
onUpdate();
|
||||||
|
}
|
||||||
|
"
|
||||||
|
/>
|
||||||
</q-popup-proxy>
|
</q-popup-proxy>
|
||||||
</q-icon>
|
</q-icon>
|
||||||
</template>
|
</template>
|
||||||
</q-input>
|
</q-input>
|
||||||
|
|
||||||
|
<q-btn-toggle
|
||||||
|
v-model="template.curve"
|
||||||
|
@update:model-value="onUpdate"
|
||||||
|
:options="[
|
||||||
|
{ label: '直线', value: false },
|
||||||
|
{ label: '曲线', value: true },
|
||||||
|
]"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<q-input
|
||||||
|
v-if="template.curve"
|
||||||
|
outlined
|
||||||
|
v-model.number="template.segmentsCount"
|
||||||
|
type="number"
|
||||||
|
@blur="onUpdate"
|
||||||
|
label="曲线分段数量 *"
|
||||||
|
lazy-rules
|
||||||
|
:rules="[(val) => (val && val > 0) || '曲线分段数量必须大于0']"
|
||||||
|
/>
|
||||||
</q-form>
|
</q-form>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useQuasar } from 'quasar';
|
import { LinkTemplate } from 'src/graphics/link/Link';
|
||||||
import { LinkDraw } from 'src/graphics/link/LinkDrawAssistant';
|
|
||||||
import { useDrawStore } from 'src/stores/draw-store';
|
import { useDrawStore } from 'src/stores/draw-store';
|
||||||
import { onMounted, reactive, ref } from 'vue';
|
import { onMounted, reactive } from 'vue';
|
||||||
const $q = useQuasar();
|
|
||||||
|
|
||||||
const drawStore = useDrawStore();
|
const drawStore = useDrawStore();
|
||||||
const template = reactive({
|
const template = reactive({
|
||||||
lineWidth: 1,
|
lineWidth: 1,
|
||||||
lineColor: '#0000ff',
|
lineColor: '#0000ff',
|
||||||
curve: 0,
|
curve: false,
|
||||||
segmentsCount: 10,
|
segmentsCount: 10,
|
||||||
});
|
});
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
const type = drawStore.drawGraphicType;
|
const type = drawStore.drawGraphicType;
|
||||||
if (type) {
|
if (type) {
|
||||||
const app = drawStore.getDrawApp();
|
const gt = drawStore.drawGraphicTemplate;
|
||||||
const plugin = app.interactionPlugin<LinkDraw>(type);
|
if (gt) {
|
||||||
const gt = plugin.graphicTemplate;
|
const lt = gt as LinkTemplate;
|
||||||
template.lineWidth = gt.lineWidth;
|
template.lineWidth = lt.lineWidth;
|
||||||
template.lineColor = gt.lineColor;
|
template.lineColor = lt.lineColor;
|
||||||
template.curve = gt.curve ? 1 : 0;
|
template.curve = lt.curve;
|
||||||
template.segmentsCount = gt.segmentsCount;
|
template.segmentsCount = lt.segmentsCount;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function onUpdate() {
|
||||||
|
const gt = drawStore.drawGraphicTemplate as LinkTemplate;
|
||||||
|
if (gt) {
|
||||||
|
gt.lineWidth = template.lineWidth;
|
||||||
|
gt.lineColor = template.lineColor;
|
||||||
|
gt.curve = template.curve;
|
||||||
|
gt.segmentsCount = template.segmentsCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -33,6 +33,12 @@ export class LinkData extends GraphicDataBase implements ILinkData {
|
|||||||
set curve(v: boolean) {
|
set curve(v: boolean) {
|
||||||
this.data.curve = v;
|
this.data.curve = v;
|
||||||
}
|
}
|
||||||
|
get curveNumber(): number {
|
||||||
|
return this.data.curve ? 1 : 0;
|
||||||
|
}
|
||||||
|
set curveNumber(v: number) {
|
||||||
|
this.data.curve = v === 0 ? false : true;
|
||||||
|
}
|
||||||
get segmentsCount(): number {
|
get segmentsCount(): number {
|
||||||
return this.data.segmentsCount;
|
return this.data.segmentsCount;
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ export class IscsFanDraw extends GraphicDrawAssistant<
|
|||||||
|
|
||||||
constructor(app: JlDrawApp, createData: () => IIscsFanData) {
|
constructor(app: JlDrawApp, createData: () => IIscsFanData) {
|
||||||
const template = new IscsFanTemplate();
|
const template = new IscsFanTemplate();
|
||||||
super(app, template, createData, IscsFan.Type, '');
|
super(app, template, createData, IscsFan.Type, '风机');
|
||||||
IscsFanInteraction.init(app);
|
IscsFanInteraction.init(app);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,9 +41,6 @@ export class IscsFanDraw extends GraphicDrawAssistant<
|
|||||||
this.iscsFan.position.copyFrom(this.toCanvasCoordinates(e.global));
|
this.iscsFan.position.copyFrom(this.toCanvasCoordinates(e.global));
|
||||||
this.createAndStore(false);
|
this.createAndStore(false);
|
||||||
}
|
}
|
||||||
onRightUp(): void {
|
|
||||||
this.finish();
|
|
||||||
}
|
|
||||||
prepareData(data: IIscsFanData): boolean {
|
prepareData(data: IIscsFanData): boolean {
|
||||||
data.transform = this.iscsFan.saveTransform();
|
data.transform = this.iscsFan.saveTransform();
|
||||||
return true;
|
return true;
|
||||||
|
@ -88,7 +88,7 @@ export class LinkDraw extends GraphicDrawAssistant<LinkTemplate, ILinkData> {
|
|||||||
this.points = [];
|
this.points = [];
|
||||||
this.graphic.clear();
|
this.graphic.clear();
|
||||||
}
|
}
|
||||||
onRightUp(): void {
|
onRightClick(): void {
|
||||||
this.createAndStore(true);
|
this.createAndStore(true);
|
||||||
}
|
}
|
||||||
onLeftDown(e: FederatedPointerEvent): void {
|
onLeftDown(e: FederatedPointerEvent): void {
|
||||||
|
@ -20,13 +20,11 @@ import {
|
|||||||
InteractionPlugin,
|
InteractionPlugin,
|
||||||
KeyListener,
|
KeyListener,
|
||||||
ShiftData,
|
ShiftData,
|
||||||
ViewportMovePlugin,
|
|
||||||
} from '../plugins';
|
} from '../plugins';
|
||||||
import { CommonMouseTool } from '../plugins/CommonMousePlugin';
|
import { CommonMouseTool } from '../plugins/CommonMousePlugin';
|
||||||
import { MenuItemOptions } from '../ui/Menu';
|
import { MenuItemOptions } from '../ui/Menu';
|
||||||
import { DOWN, LEFT, RIGHT, UP, recursiveChildren } from '../utils';
|
import { DOWN, LEFT, RIGHT, UP, recursiveChildren } from '../utils';
|
||||||
import {
|
import {
|
||||||
CanvasData,
|
|
||||||
GraphicApp,
|
GraphicApp,
|
||||||
GraphicAppOptions,
|
GraphicAppOptions,
|
||||||
ICanvasProperties,
|
ICanvasProperties,
|
||||||
@ -40,9 +38,10 @@ export abstract class GraphicDrawAssistant<
|
|||||||
GT extends GraphicTemplate,
|
GT extends GraphicTemplate,
|
||||||
GD extends GraphicData
|
GD extends GraphicData
|
||||||
> extends AppInteractionPlugin {
|
> extends AppInteractionPlugin {
|
||||||
|
readonly __GraphicDrawAssistant = true;
|
||||||
app: JlDrawApp;
|
app: JlDrawApp;
|
||||||
type: string; // 图形对象类型
|
type: string; // 图形对象类型
|
||||||
description?: string; // 描述
|
description: string; // 描述
|
||||||
icon: string; // 界面显示的图标
|
icon: string; // 界面显示的图标
|
||||||
container: Container = new Container();
|
container: Container = new Container();
|
||||||
graphicTemplate: GT;
|
graphicTemplate: GT;
|
||||||
@ -64,7 +63,7 @@ export abstract class GraphicDrawAssistant<
|
|||||||
graphicTemplate: GT,
|
graphicTemplate: GT,
|
||||||
createGraphicData: () => GD,
|
createGraphicData: () => GD,
|
||||||
icon: string,
|
icon: string,
|
||||||
description?: string
|
description: string
|
||||||
) {
|
) {
|
||||||
super(graphicTemplate.type, graphicApp);
|
super(graphicTemplate.type, graphicApp);
|
||||||
this.app = graphicApp;
|
this.app = graphicApp;
|
||||||
@ -88,14 +87,16 @@ export abstract class GraphicDrawAssistant<
|
|||||||
canvas.on('mouseup', this.onLeftUp, this);
|
canvas.on('mouseup', this.onLeftUp, this);
|
||||||
canvas.on('rightdown', this.onRightDown, this);
|
canvas.on('rightdown', this.onRightDown, this);
|
||||||
canvas.on('rightup', this.onRightUp, this);
|
canvas.on('rightup', this.onRightUp, this);
|
||||||
|
canvas.on('_rightclick', this.onRightClick, this);
|
||||||
|
|
||||||
this.app.viewport.wheel({
|
this.app.viewport.wheel({
|
||||||
percent: 0.01,
|
percent: 0.01,
|
||||||
});
|
});
|
||||||
this.app.addKeyboardListener(this.escListener);
|
this.app.addKeyboardListener(this.escListener);
|
||||||
|
|
||||||
this.app
|
this.app.viewport.drag({
|
||||||
.interactionPlugin<ViewportMovePlugin>(ViewportMovePlugin.Name)
|
mouseButtons: 'right',
|
||||||
.resume();
|
});
|
||||||
}
|
}
|
||||||
unbind(): void {
|
unbind(): void {
|
||||||
this.clearCache();
|
this.clearCache();
|
||||||
@ -111,9 +112,7 @@ export abstract class GraphicDrawAssistant<
|
|||||||
|
|
||||||
this.app.removeKeyboardListener(this.escListener);
|
this.app.removeKeyboardListener(this.escListener);
|
||||||
|
|
||||||
this.app
|
this.app.viewport.plugins.remove('drag');
|
||||||
.interactionPlugin<ViewportMovePlugin>(ViewportMovePlugin.Name)
|
|
||||||
.pause();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onLeftDown(e: FederatedMouseEvent) {}
|
onLeftDown(e: FederatedMouseEvent) {}
|
||||||
@ -125,6 +124,9 @@ export abstract class GraphicDrawAssistant<
|
|||||||
onLeftUp(e: FederatedMouseEvent) {}
|
onLeftUp(e: FederatedMouseEvent) {}
|
||||||
onRightDown(e: FederatedMouseEvent) {}
|
onRightDown(e: FederatedMouseEvent) {}
|
||||||
onRightUp(e: FederatedMouseEvent) {}
|
onRightUp(e: FederatedMouseEvent) {}
|
||||||
|
onRightClick(e: FederatedMouseEvent) {
|
||||||
|
this.finish();
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* 获取下一个id
|
* 获取下一个id
|
||||||
*/
|
*/
|
||||||
@ -186,13 +188,6 @@ export abstract class GraphicDrawAssistant<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 图形App事件
|
|
||||||
*/
|
|
||||||
export enum DrawAppEvent {
|
|
||||||
propertiesupdate = 'propertiesupdate', // 图形对象数据变更
|
|
||||||
}
|
|
||||||
|
|
||||||
export type DrawAssistant = GraphicDrawAssistant<GraphicTemplate, GraphicData>;
|
export type DrawAssistant = GraphicDrawAssistant<GraphicTemplate, GraphicData>;
|
||||||
|
|
||||||
export interface IDrawAppOptions {
|
export interface IDrawAppOptions {
|
||||||
@ -226,16 +221,11 @@ export class JlDrawApp extends GraphicApp {
|
|||||||
|
|
||||||
drawAssistants: DrawAssistant[] = [];
|
drawAssistants: DrawAssistant[] = [];
|
||||||
|
|
||||||
selectedData: GraphicData | ICanvasProperties | null;
|
|
||||||
|
|
||||||
constructor(dom: HTMLElement) {
|
constructor(dom: HTMLElement) {
|
||||||
super(dom);
|
super(dom);
|
||||||
|
|
||||||
this.appendDrawStatesDisplay();
|
this.appendDrawStatesDisplay();
|
||||||
|
|
||||||
// 数据更新表单缓存处理
|
|
||||||
this.selectedData = null;
|
|
||||||
this.initSelectedDataUpdateListen();
|
|
||||||
// 拖拽操作记录
|
// 拖拽操作记录
|
||||||
this.appOperationRecord();
|
this.appOperationRecord();
|
||||||
// 绑定通用键盘操作
|
// 绑定通用键盘操作
|
||||||
@ -314,49 +304,6 @@ export class JlDrawApp extends GraphicApp {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 因图形数据更新和表单数据更新存在Vue代理及记录需求,额外处理数据的缓存
|
|
||||||
*/
|
|
||||||
private initSelectedDataUpdateListen() {
|
|
||||||
// 画布数据更新
|
|
||||||
this.selectedData = new CanvasData(this.canvas.properties);
|
|
||||||
this.canvas.on('dataupdate', () => {
|
|
||||||
if (this.selectedGraphics.length === 0) {
|
|
||||||
this.selectedData = this.canvas.saveData();
|
|
||||||
this.emit('propertiesupdate', this.selectedData);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.viewport.on('moved-end', () => {
|
|
||||||
if (this.selectedGraphics.length === 0) {
|
|
||||||
this.selectedData = this.canvas.saveData();
|
|
||||||
this.emit('propertiesupdate', this.selectedData);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// 图形对象数据更新
|
|
||||||
const graphicPropertiesUpdate = (g: DisplayObject) => {
|
|
||||||
if (this.selectedGraphics.length === 1) {
|
|
||||||
this.selectedData = (g as JlGraphic).saveData();
|
|
||||||
this.emit(DrawAppEvent.propertiesupdate, this.selectedData);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
this.on('graphicselectedchange', (g: DisplayObject, selected) => {
|
|
||||||
if (selected) {
|
|
||||||
g.on('repaint', graphicPropertiesUpdate, this);
|
|
||||||
} else {
|
|
||||||
g.off('repaint', graphicPropertiesUpdate, this);
|
|
||||||
}
|
|
||||||
if (this.selectedGraphics.length === 0) {
|
|
||||||
this.selectedData = this.canvas.properties.clone();
|
|
||||||
} else if (this.selectedGraphics.length === 1) {
|
|
||||||
const g = this.selectedGraphics[0];
|
|
||||||
this.selectedData = g.saveData();
|
|
||||||
} else {
|
|
||||||
this.selectedData = null;
|
|
||||||
}
|
|
||||||
this.emit(DrawAppEvent.propertiesupdate, this.selectedData);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 绘制状态信息显示
|
* 绘制状态信息显示
|
||||||
*/
|
*/
|
||||||
@ -516,34 +463,22 @@ export class JlDrawApp extends GraphicApp {
|
|||||||
this.opRecord.record(new GraphicDeleteOperation(this, deletes));
|
this.opRecord.record(new GraphicDeleteOperation(this, deletes));
|
||||||
}
|
}
|
||||||
|
|
||||||
onSubmit(): void {
|
updateCanvasAndRecord(data: ICanvasProperties) {
|
||||||
if (this.selectedData == null) return;
|
const old = this.canvas.properties.clone();
|
||||||
if (this.selectedGraphics.length === 0) {
|
this.canvas.update(data);
|
||||||
const cp = this.selectedData as ICanvasProperties;
|
const newVal = this.canvas.properties.clone();
|
||||||
this.opRecord.record(
|
this.opRecord.record(
|
||||||
new UpdateCanvasOperation(
|
new UpdateCanvasOperation(this, this.canvas, old, newVal)
|
||||||
this,
|
);
|
||||||
this.canvas,
|
}
|
||||||
cp,
|
|
||||||
this.canvas.properties.clone()
|
updateGraphicAndRecord(g: JlGraphic, data: GraphicData) {
|
||||||
)
|
const old = g.saveData();
|
||||||
);
|
g.updateData(data);
|
||||||
this.canvas.update(this.selectedData as ICanvasProperties);
|
const newVal = g.saveData();
|
||||||
} else if (this.selectedGraphics.length === 1) {
|
this.opRecord.record(
|
||||||
const g = this.selectedGraphics[0];
|
new GraphicDataUpdateOperation(this, [g], [old], [newVal])
|
||||||
if (this.selectedData != null) {
|
);
|
||||||
const data = g.saveData();
|
|
||||||
g.updateData(this.selectedData as GraphicData);
|
|
||||||
this.opRecord.record(
|
|
||||||
new GraphicDataUpdateOperation(
|
|
||||||
this,
|
|
||||||
[g],
|
|
||||||
[data],
|
|
||||||
[this.selectedData as GraphicData]
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -561,21 +496,10 @@ function handleArrowKeyMoveGraphics(
|
|||||||
if (child.selected && child.draggable) {
|
if (child.selected && child.draggable) {
|
||||||
handler(child);
|
handler(child);
|
||||||
}
|
}
|
||||||
// if (child.selected && child.draggable) {
|
|
||||||
// child.emit(
|
|
||||||
// 'transformstart',
|
|
||||||
// GraphicTransformEvent.init(child, 'shift')
|
|
||||||
// );
|
|
||||||
// child.position.x += dp.x;
|
|
||||||
// child.position.y += dp.y;
|
|
||||||
// }
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
app.selectedGraphics.forEach((g) => {
|
app.selectedGraphics.forEach((g) => {
|
||||||
handler(g);
|
handler(g);
|
||||||
// g.emit('transformstart', GraphicTransformEvent.init(g, 'shift'));
|
|
||||||
// g.position.x += dp.x;
|
|
||||||
// g.position.y += dp.y;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -380,8 +380,8 @@ export class GraphicApp extends EventEmitter<GraphicAppEvents> {
|
|||||||
this.interactiveTypeOptions = { interactiveGraphicTypeIncludes: [] };
|
this.interactiveTypeOptions = { interactiveGraphicTypeIncludes: [] };
|
||||||
// 创建pixi渲染app
|
// 创建pixi渲染app
|
||||||
this.app = new Application({
|
this.app = new Application({
|
||||||
// width: dom.clientWidth,
|
width: dom.clientWidth,
|
||||||
// height: dom.clientHeight,
|
height: dom.clientHeight,
|
||||||
antialias: true,
|
antialias: true,
|
||||||
resizeTo: dom,
|
resizeTo: dom,
|
||||||
});
|
});
|
||||||
@ -829,6 +829,7 @@ export class GraphicApp extends EventEmitter<GraphicAppEvents> {
|
|||||||
}
|
}
|
||||||
const worldWidth = this.canvas._properties.width;
|
const worldWidth = this.canvas._properties.width;
|
||||||
const worldHeight = this.canvas._properties.height;
|
const worldHeight = this.canvas._properties.height;
|
||||||
|
this.app.resize();
|
||||||
this.viewport.resize(screenWidth, screenHeight, worldWidth, worldHeight);
|
this.viewport.resize(screenWidth, screenHeight, worldWidth, worldHeight);
|
||||||
if (this.viewport.OOB().right) {
|
if (this.viewport.OOB().right) {
|
||||||
this.viewport.right = this.viewport.right + 1;
|
this.viewport.right = this.viewport.right + 1;
|
||||||
|
2
src/jlgraphic/global.d.ts
vendored
2
src/jlgraphic/global.d.ts
vendored
@ -33,7 +33,7 @@ declare namespace GlobalMixins {
|
|||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
||||||
interface GraphicAppEvents {
|
interface GraphicAppEvents {
|
||||||
propertiesupdate: [selectedData: GraphicData | CanvasProperties | null];
|
// propertiesupdate: [selectedData: GraphicData | CanvasProperties | null];
|
||||||
}
|
}
|
||||||
|
|
||||||
interface DisplayObject {
|
interface DisplayObject {
|
||||||
|
@ -133,6 +133,7 @@ onMounted(() => {
|
|||||||
if (dom) {
|
if (dom) {
|
||||||
const drawApp = drawStore.initDrawApp(dom);
|
const drawApp = drawStore.initDrawApp(dom);
|
||||||
loadDrawDatas(drawApp);
|
loadDrawDatas(drawApp);
|
||||||
|
onResize();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,13 +1,44 @@
|
|||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
import { destroyDrawApp, getDrawApp, initDrawApp } from 'src/examples/app';
|
import { destroyDrawApp, getDrawApp, initDrawApp } from 'src/examples/app';
|
||||||
import { GraphicDrawAssistant, JlDrawApp } from 'src/jlgraphic';
|
import { DrawAssistant, JlCanvas, JlDrawApp, JlGraphic } from 'src/jlgraphic';
|
||||||
|
|
||||||
export const useDrawStore = defineStore('draw', {
|
export const useDrawStore = defineStore('draw', {
|
||||||
state: () => ({
|
state: () => ({
|
||||||
drawGraphicType: null as string | null,
|
drawAssistant: null as DrawAssistant | null,
|
||||||
|
selectedGraphics: null as JlGraphic[] | null,
|
||||||
}),
|
}),
|
||||||
getters: {
|
getters: {
|
||||||
drawMode: (state) => state.drawGraphicType != null,
|
drawMode: (state) => state.drawAssistant != null,
|
||||||
|
drawGraphicType: (state) => state.drawAssistant?.type,
|
||||||
|
drawGraphicName: (state) => state.drawAssistant?.description,
|
||||||
|
drawGraphicTemplate: (state) => state.drawAssistant?.graphicTemplate,
|
||||||
|
|
||||||
|
selectedGraphicType: (state) => {
|
||||||
|
if (state.selectedGraphics) {
|
||||||
|
if (state.selectedGraphics.length === 1) {
|
||||||
|
return state.selectedGraphics[0].type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
selectedObjName: (state) => {
|
||||||
|
if (state.selectedGraphics) {
|
||||||
|
if (state.selectedGraphics.length == 0) {
|
||||||
|
return '画布';
|
||||||
|
} else if (state.selectedGraphics.length == 1) {
|
||||||
|
return state.selectedGraphics[0].type;
|
||||||
|
}
|
||||||
|
return '多选';
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
},
|
||||||
|
selectedGraphic: (state) => {
|
||||||
|
if (state.selectedGraphics) {
|
||||||
|
if (state.selectedGraphics.length === 1) {
|
||||||
|
return state.selectedGraphics[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
getDrawApp(): JlDrawApp {
|
getDrawApp(): JlDrawApp {
|
||||||
@ -17,21 +48,30 @@ export const useDrawStore = defineStore('draw', {
|
|||||||
}
|
}
|
||||||
return app;
|
return app;
|
||||||
},
|
},
|
||||||
|
getJlCanvas(): JlCanvas {
|
||||||
|
return this.getDrawApp().canvas;
|
||||||
|
},
|
||||||
initDrawApp(dom: HTMLElement) {
|
initDrawApp(dom: HTMLElement) {
|
||||||
const app = initDrawApp(dom);
|
const app = initDrawApp(dom);
|
||||||
app.on('interaction-plugin-resume', (plugin) => {
|
app.on('interaction-plugin-resume', (plugin) => {
|
||||||
if (plugin.isAppPlugin()) {
|
if (plugin.isAppPlugin()) {
|
||||||
if (plugin instanceof GraphicDrawAssistant) {
|
if (Object.hasOwn(plugin, '__GraphicDrawAssistant')) {
|
||||||
this.drawGraphicType = plugin.name;
|
this.drawAssistant = plugin as DrawAssistant;
|
||||||
} else {
|
} else {
|
||||||
this.drawGraphicType = null;
|
this.drawAssistant = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
app.on('graphicselectedchange', () => {
|
||||||
|
this.selectedGraphics = app.selectedGraphics;
|
||||||
|
});
|
||||||
|
this.selectedGraphics = [];
|
||||||
return app;
|
return app;
|
||||||
},
|
},
|
||||||
destroy() {
|
destroy() {
|
||||||
this.drawGraphicType = null;
|
// console.log('绘制状态清空,绘制应用销毁');
|
||||||
|
this.drawAssistant = null;
|
||||||
|
this.selectedGraphics = null;
|
||||||
destroyDrawApp();
|
destroyDrawApp();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user