@zhangqingcq/vgce 0.0.14 → 0.0.15

Sign up to get free protection for your applications and to get access to all the features.
Files changed (134) hide show
  1. package/README.md +3 -1
  2. package/dist/vgce.js +5 -12
  3. package/dist/vgce.umd.cjs +2 -2
  4. package/package.json +3 -2
  5. package/src/App.vue +11 -0
  6. package/src/assets/base.less +49 -0
  7. package/src/assets/icons/add.svg +1 -0
  8. package/src/assets/icons/delete.svg +12 -0
  9. package/src/assets/icons/export.svg +1 -0
  10. package/src/assets/icons/group.svg +13 -0
  11. package/src/assets/icons/import.svg +1 -0
  12. package/src/assets/icons/lock.svg +7 -0
  13. package/src/assets/icons/menu-fold.svg +9 -0
  14. package/src/assets/icons/menu-unfold.svg +9 -0
  15. package/src/assets/icons/preview.svg +6 -0
  16. package/src/assets/icons/redo.svg +8 -0
  17. package/src/assets/icons/return.svg +8 -0
  18. package/src/assets/icons/rotate.svg +1 -0
  19. package/src/assets/icons/save.svg +9 -0
  20. package/src/assets/icons/setting.svg +6 -0
  21. package/src/assets/icons/undo.svg +7 -0
  22. package/src/assets/icons/ungroup.svg +16 -0
  23. package/src/assets/icons/unlock.svg +7 -0
  24. package/src/assets/main.less +6 -0
  25. package/src/assets/svgs/alternator.svg +8 -0
  26. package/src/assets/svgs/bot-12.svg +1 -0
  27. package/src/assets/svgs/bot-2.svg +1 -0
  28. package/src/assets/svgs/bot-3.svg +1 -0
  29. package/src/assets/svgs/bot-7.svg +1 -0
  30. package/src/assets/svgs/bot-9.svg +94 -0
  31. package/src/assets/svgs/car.svg +1 -0
  32. package/src/assets/svgs/circuit-breaker.svg +11 -0
  33. package/src/assets/svgs/clock-a.svg +23 -0
  34. package/src/assets/svgs/common-table.svg +7 -0
  35. package/src/assets/svgs/el-button.svg +10 -0
  36. package/src/assets/svgs/el-tag.svg +13 -0
  37. package/src/assets/svgs/hospital.svg +1 -0
  38. package/src/assets/svgs/house.svg +1 -0
  39. package/src/assets/svgs/light.svg +24 -0
  40. package/src/assets/svgs/now-time.svg +9 -0
  41. package/src/assets/svgs/package.svg +1 -0
  42. package/src/assets/svgs/pie-charts.svg +10 -0
  43. package/src/assets/svgs/progress-a.svg +1 -0
  44. package/src/assets/svgs/reservoir.svg +10 -0
  45. package/src/assets/svgs/svg-text.svg +5 -0
  46. package/src/assets/svgs/switch-a.svg +5 -0
  47. package/src/assets/svgs/traction-transformer.svg +11 -0
  48. package/src/components/ace-edit/index.ts +27 -0
  49. package/src/components/config/index.ts +450 -0
  50. package/src/components/config/types.ts +25 -0
  51. package/src/components/svg-analysis/index.vue +11 -0
  52. package/src/components/svg-editor/center-panel/index.vue +867 -0
  53. package/src/components/svg-editor/center-panel/types.ts +11 -0
  54. package/src/components/svg-editor/component-tree/index.vue +33 -0
  55. package/src/components/svg-editor/connection-line/index.vue +125 -0
  56. package/src/components/svg-editor/connection-panel/index.vue +198 -0
  57. package/src/components/svg-editor/export-json/index.vue +37 -0
  58. package/src/components/svg-editor/handle-panel/index.vue +342 -0
  59. package/src/components/svg-editor/import-json/index.vue +37 -0
  60. package/src/components/svg-editor/index.vue +280 -0
  61. package/src/components/svg-editor/left-panel/index.vue +83 -0
  62. package/src/components/svg-editor/right-panel/code-edit-modal.vue +50 -0
  63. package/src/components/svg-editor/right-panel/common-animate.vue +96 -0
  64. package/src/components/svg-editor/right-panel/condition.vue +101 -0
  65. package/src/components/svg-editor/right-panel/dynamic-el-form-item.vue +97 -0
  66. package/src/components/svg-editor/right-panel/index.vue +304 -0
  67. package/src/components/svg-editor/right-panel/list.vue +86 -0
  68. package/src/components/svg-editor/top-panel/index.vue +139 -0
  69. package/src/components/svg-editor/types.ts +22 -0
  70. package/src/components/svg-viewer/index.vue +340 -0
  71. package/src/components/vue3-ruler-tool/index.vue +506 -0
  72. package/src/config/files/clock-a.vue +66 -0
  73. package/src/config/files/common-table.vue +49 -0
  74. package/src/config/files/light-a.vue +72 -0
  75. package/src/config/files/now-time.vue +53 -0
  76. package/src/config/files/pie-charts.vue +72 -0
  77. package/src/config/files/progress.vue +40 -0
  78. package/src/config/files/svg-text.vue +39 -0
  79. package/src/config/files/switch-a.vue +45 -0
  80. package/src/config/index.ts +28 -0
  81. package/src/config/svg/animation/index.ts +8 -0
  82. package/src/config/svg/animation/reservoir.ts +32 -0
  83. package/src/config/svg/custom/clock-a.ts +23 -0
  84. package/src/config/svg/custom/index.ts +11 -0
  85. package/src/config/svg/custom/light.ts +29 -0
  86. package/src/config/svg/custom/svg-text.ts +54 -0
  87. package/src/config/svg/custom/switch-a.ts +29 -0
  88. package/src/config/svg/index.ts +12 -0
  89. package/src/config/svg/stateful/circuit-breaker.ts +38 -0
  90. package/src/config/svg/stateful/index.ts +8 -0
  91. package/src/config/svg/stateless/alternator.ts +28 -0
  92. package/src/config/svg/stateless/bot-12.ts +22 -0
  93. package/src/config/svg/stateless/bot-2.ts +22 -0
  94. package/src/config/svg/stateless/bot-3.ts +22 -0
  95. package/src/config/svg/stateless/bot-7.ts +22 -0
  96. package/src/config/svg/stateless/bot-9.ts +22 -0
  97. package/src/config/svg/stateless/car.ts +22 -0
  98. package/src/config/svg/stateless/hospital.ts +22 -0
  99. package/src/config/svg/stateless/house.ts +22 -0
  100. package/src/config/svg/stateless/index.ts +30 -0
  101. package/src/config/svg/stateless/package.ts +22 -0
  102. package/src/config/svg/stateless/traction-transformer.ts +28 -0
  103. package/src/config/types.ts +126 -0
  104. package/src/config/vue/component/button.ts +57 -0
  105. package/src/config/vue/component/common-table.ts +124 -0
  106. package/src/config/vue/component/index.ts +13 -0
  107. package/src/config/vue/component/now-time.ts +29 -0
  108. package/src/config/vue/component/progress.ts +29 -0
  109. package/src/config/vue/component/tag.ts +46 -0
  110. package/src/config/vue/echarts/index.ts +8 -0
  111. package/src/config/vue/echarts/pie-charts.ts +60 -0
  112. package/src/config/vue/index.ts +5 -0
  113. package/src/hooks.ts +47 -0
  114. package/src/index.ts +14 -0
  115. package/src/main.ts +15 -0
  116. package/src/router.ts +24 -0
  117. package/src/stores/config/index.ts +44 -0
  118. package/src/stores/config/types.ts +27 -0
  119. package/src/stores/global/index.ts +109 -0
  120. package/src/stores/global/types.ts +115 -0
  121. package/src/stores/main.ts +10 -0
  122. package/src/stores/svg-edit-layout/index.ts +17 -0
  123. package/src/stores/svg-edit-layout/types.ts +8 -0
  124. package/src/stores/system/index.ts +174 -0
  125. package/src/stores/system/types.ts +43 -0
  126. package/src/utils/fetch.ts +351 -0
  127. package/src/utils/file-read-write.ts +26 -0
  128. package/src/utils/index.ts +397 -0
  129. package/src/utils/mqtt-net.ts +48 -0
  130. package/src/utils/proxy.ts +7 -0
  131. package/src/utils/scale-core.ts +214 -0
  132. package/src/utils/types.ts +13 -0
  133. package/src/views/EditorS.vue +18 -0
  134. package/src/views/Preview.vue +12 -0
@@ -0,0 +1,867 @@
1
+ <script setup lang="ts">
2
+ import { computed, getCurrentInstance, onMounted, reactive, ref } from 'vue'
3
+ import { pinia } from '@/hooks'
4
+ import { useConfigStore } from '@/stores/config'
5
+ import { useGlobalStore } from '@/stores/global'
6
+ import { EGlobalStoreIntention, EMouseInfoState, EScaleInfoType } from '@/stores/global/types'
7
+ import type { IDoneJson } from '@/stores/global/types'
8
+ import { useSvgEditLayoutStore } from '@/stores/svg-edit-layout'
9
+ import {
10
+ getCenterPoint,
11
+ randomString,
12
+ getSvgNowPosition,
13
+ setSvgActualInfo,
14
+ prosToVBind,
15
+ objectDeepClone,
16
+ getCommonClass
17
+ } from '@/utils'
18
+ import {
19
+ calculateBottom,
20
+ calculateLeft,
21
+ calculateLeftBottom,
22
+ calculateLeftTop,
23
+ calculateRight,
24
+ calculateRightBottom,
25
+ calculateRightTop,
26
+ calculateTop
27
+ } from '@/utils/scale-core'
28
+ import HandlePanel from '@/components/svg-editor/handle-panel/index.vue'
29
+ import ConnectionPanel from '@/components/svg-editor/connection-panel/index.vue'
30
+ import { EDoneJsonType } from '@/config/types'
31
+ import type { IConfigItem } from '@/config/types'
32
+ import ConnectionLine from '@/components/svg-editor/connection-line/index.vue'
33
+ import type { IVisibleInfo } from './types'
34
+ import { vueComp } from '@/config'
35
+ import { useContextMenuStore, useEditPrivateStore } from '@/stores/system'
36
+ import { EContextMenuInfoType } from '@/stores/system/types'
37
+ import { useHistoryRecord } from '@/hooks'
38
+
39
+ //注册所有组件
40
+ const instance = getCurrentInstance()
41
+ Object.keys(vueComp).forEach((key) => {
42
+ if (!Object.keys(instance?.appContext?.components as any).includes(key)) {
43
+ // @ts-ignore
44
+ instance?.appContext.app.component(key, vueComp[key])
45
+ }
46
+ })
47
+ const globalStore = useGlobalStore(pinia)
48
+ const configStore = useConfigStore(pinia)
49
+ const svgEditLayoutStore = useSvgEditLayoutStore(pinia)
50
+ const editPrivateStore = useEditPrivateStore(pinia)
51
+ const contextMenuStore = useContextMenuStore(pinia)
52
+ const contextMenuRef = ref<HTMLElement>()
53
+ const canvasRef = ref<HTMLElement>()
54
+ const cursor_style = computed(() =>
55
+ globalStore.intention == EGlobalStoreIntention.MoveCanvas
56
+ ? 'grab'
57
+ : globalStore.intention == EGlobalStoreIntention.Rotate
58
+ ? "url('/src/assets/icons/rotate.svg') 12 12, auto"
59
+ : 'default'
60
+ )
61
+ const visible_info: IVisibleInfo = reactive({
62
+ handle_panel: computed(
63
+ () =>
64
+ globalStore.intention === EGlobalStoreIntention.Select ||
65
+ globalStore.intention === EGlobalStoreIntention.Zoom ||
66
+ globalStore.intention === EGlobalStoreIntention.Rotate
67
+ ),
68
+ connection_panel: false,
69
+ connection_line: false,
70
+ select_item: {
71
+ info: null,
72
+ index: -1
73
+ }
74
+ })
75
+ const dropEvent = (e: DragEvent) => {
76
+ if (globalStore.intention == EGlobalStoreIntention.None) {
77
+ return
78
+ } else if (globalStore.intention == EGlobalStoreIntention.Create) {
79
+ if (!globalStore.create_svg_info) {
80
+ console.error('要创建的数据获取失败')
81
+ return
82
+ }
83
+
84
+ const _x = Math.floor(e.clientX - svgEditLayoutStore.center_offset.x)
85
+ const _y = Math.floor(e.clientY - svgEditLayoutStore.center_offset.y)
86
+
87
+ const done_item_json: IDoneJson = {
88
+ id: randomString(),
89
+ x: _x,
90
+ y: _y,
91
+ client: {
92
+ x: _x,
93
+ y: _y
94
+ },
95
+ scale_x: 1,
96
+ scale_y: 1,
97
+ rotate: 0,
98
+ actual_bound: {
99
+ x: 0,
100
+ y: 0,
101
+ width: 0,
102
+ height: 0
103
+ },
104
+ point_coordinate: {
105
+ tl: {
106
+ x: 0,
107
+ y: 0
108
+ },
109
+ tc: {
110
+ x: 0,
111
+ y: 0
112
+ },
113
+ tr: {
114
+ x: 0,
115
+ y: 0
116
+ },
117
+ l: {
118
+ x: 0,
119
+ y: 0
120
+ },
121
+ r: {
122
+ x: 0,
123
+ y: 0
124
+ },
125
+ bl: {
126
+ x: 0,
127
+ y: 0
128
+ },
129
+ bc: {
130
+ x: 0,
131
+ y: 0
132
+ },
133
+ br: {
134
+ x: 0,
135
+ y: 0
136
+ }
137
+ },
138
+ ...objectDeepClone<IConfigItem>(globalStore.create_svg_info)
139
+ }
140
+ globalStore.setHandleSvgInfo(done_item_json, globalStore.done_json.length)
141
+ globalStore.setDoneJson(done_item_json)
142
+ globalStore.intention = EGlobalStoreIntention.None
143
+ }
144
+ canvasRef.value?.focus()
145
+ }
146
+ const dragEnterEvent = (e: DragEvent) => {
147
+ //dragenter和dragover一定要阻止浏览器默认行为 不然不会触发drop
148
+ e.preventDefault()
149
+ }
150
+ const dragOverEvent = (e: DragEvent) => {
151
+ //dragenter和dragover一定要阻止浏览器默认行为 不然不会触发drop
152
+ e.preventDefault()
153
+ }
154
+ const onSvgMouseDown = (select_item: IDoneJson, index: number, e: MouseEvent) => {
155
+ canvasRef.value?.focus()
156
+ if (globalStore.intention === EGlobalStoreIntention.Connection) {
157
+ return
158
+ }
159
+ e.preventDefault()
160
+ e.stopPropagation()
161
+ //鼠标在画布上的组件按下记录选中的组件信息和鼠标位置信息等
162
+ globalStore.intention = EGlobalStoreIntention.Select
163
+ globalStore.setHandleSvgInfo(select_item, index)
164
+ globalStore.setMouseInfo({
165
+ state: EMouseInfoState.Down,
166
+ position_x: e.clientX,
167
+ position_y: e.clientY,
168
+ now_position_x: select_item.x,
169
+ now_position_y: select_item.y,
170
+ new_position_x: select_item.x,
171
+ new_position_y: select_item.y
172
+ })
173
+ }
174
+ const onSvgMouseEnter = (select_item: IDoneJson, index: number, e: MouseEvent) => {
175
+ e.preventDefault()
176
+ e.stopPropagation()
177
+ visible_info.connection_panel = true
178
+ visible_info.connection_line = true
179
+ if (
180
+ (globalStore.intention === EGlobalStoreIntention.Connection ||
181
+ globalStore.intention === EGlobalStoreIntention.SetConnectionLineNode) &&
182
+ select_item.type === EDoneJsonType.ConnectionLine
183
+ ) {
184
+ return
185
+ }
186
+ visible_info.select_item.info = select_item
187
+ visible_info.select_item.index = index
188
+ }
189
+ const onSvgMouseLeave = (select_item: IDoneJson, index: number, e: MouseEvent) => {
190
+ e.preventDefault()
191
+ e.stopPropagation()
192
+ if (
193
+ (globalStore.intention === EGlobalStoreIntention.Connection ||
194
+ globalStore.intention === EGlobalStoreIntention.SetConnectionLineNode) &&
195
+ select_item.type === EDoneJsonType.ConnectionLine
196
+ ) {
197
+ return
198
+ }
199
+ visible_info.connection_panel = false
200
+ visible_info.connection_line = false
201
+ visible_info.select_item.info = null
202
+ visible_info.select_item.index = -1
203
+ }
204
+ const onCanvasMouseMove = (e: MouseEvent) => {
205
+ //如果鼠标不是按下状态 连线除外
206
+ if (
207
+ globalStore.mouse_info.state != EMouseInfoState.Down &&
208
+ globalStore.intention !== EGlobalStoreIntention.Connection
209
+ ) {
210
+ return
211
+ }
212
+ const { clientX, clientY } = e
213
+ globalStore.mouse_info.new_position_x =
214
+ globalStore.mouse_info.now_position_x + clientX - globalStore.mouse_info.position_x
215
+ globalStore.mouse_info.new_position_y =
216
+ globalStore.mouse_info.now_position_y + clientY - globalStore.mouse_info.position_y
217
+ if (
218
+ globalStore.handle_svg_info?.info &&
219
+ (globalStore.intention == EGlobalStoreIntention.Select || globalStore.intention == EGlobalStoreIntention.Move)
220
+ ) {
221
+ //有选中组件 移动组件
222
+ globalStore.handle_svg_info.info.x = globalStore.mouse_info.new_position_x
223
+ globalStore.handle_svg_info.info.y = globalStore.mouse_info.new_position_y
224
+ globalStore.handle_svg_info.info.client = {
225
+ x: globalStore.mouse_info.new_position_x,
226
+ y: globalStore.mouse_info.new_position_y
227
+ }
228
+ globalStore.intention = EGlobalStoreIntention.Move
229
+ } else if (globalStore.intention == EGlobalStoreIntention.MoveCanvas) {
230
+ //移动画布
231
+ svgEditLayoutStore.center_offset.x = globalStore.mouse_info.new_position_x
232
+ svgEditLayoutStore.center_offset.y = globalStore.mouse_info.new_position_y
233
+ } else if (globalStore.intention === EGlobalStoreIntention.Zoom) {
234
+ if (!globalStore.handle_svg_info) {
235
+ return
236
+ }
237
+ //当前鼠标坐标
238
+ const curPosition = {
239
+ x: e.clientX - svgEditLayoutStore.center_offset.x,
240
+ y: e.clientY - svgEditLayoutStore.center_offset.y
241
+ }
242
+ let new_length = {
243
+ width: 0,
244
+ height: 0,
245
+ is_old_width: false,
246
+ is_old_height: false
247
+ }
248
+ if (globalStore.scale_info.type === EScaleInfoType.TopLeft) {
249
+ new_length = calculateLeftTop(
250
+ curPosition,
251
+ globalStore.scale_info.symmetric_point,
252
+ globalStore.handle_svg_info.info.rotate
253
+ )
254
+ } else if (globalStore.scale_info.type === EScaleInfoType.TopRight) {
255
+ new_length = calculateRightTop(
256
+ curPosition,
257
+ globalStore.scale_info.symmetric_point,
258
+ globalStore.handle_svg_info.info.rotate
259
+ )
260
+ } else if (globalStore.scale_info.type === EScaleInfoType.BottomRight) {
261
+ new_length = calculateRightBottom(
262
+ curPosition,
263
+ globalStore.scale_info.symmetric_point,
264
+ globalStore.handle_svg_info.info.rotate
265
+ )
266
+ } else if (globalStore.scale_info.type === EScaleInfoType.BottomLeft) {
267
+ new_length = calculateLeftBottom(
268
+ curPosition,
269
+ globalStore.scale_info.symmetric_point,
270
+ globalStore.handle_svg_info.info.rotate
271
+ )
272
+ } else if (globalStore.scale_info.type === EScaleInfoType.TopCenter) {
273
+ new_length = calculateTop(
274
+ curPosition,
275
+ globalStore.scale_info.symmetric_point,
276
+ globalStore.handle_svg_info.info.rotate,
277
+ globalStore.handle_svg_info.info.client
278
+ )
279
+ } else if (globalStore.scale_info.type === EScaleInfoType.Right) {
280
+ new_length = calculateRight(
281
+ curPosition,
282
+ globalStore.scale_info.symmetric_point,
283
+ globalStore.handle_svg_info.info.rotate,
284
+ globalStore.handle_svg_info.info.client
285
+ )
286
+ } else if (globalStore.scale_info.type === EScaleInfoType.BottomCenter) {
287
+ new_length = calculateBottom(
288
+ curPosition,
289
+ globalStore.scale_info.symmetric_point,
290
+ globalStore.handle_svg_info.info.rotate,
291
+ globalStore.handle_svg_info.info.client
292
+ )
293
+ } else if (globalStore.scale_info.type === EScaleInfoType.Left) {
294
+ new_length = calculateLeft(
295
+ curPosition,
296
+ globalStore.scale_info.symmetric_point,
297
+ globalStore.handle_svg_info.info.rotate,
298
+ globalStore.handle_svg_info.info.client
299
+ )
300
+ }
301
+
302
+ //缩放
303
+ // const move_length_x =
304
+ // globalStore.scale_info.type === EScaleInfoType.TopLeft ||
305
+ // globalStore.scale_info.type === EScaleInfoType.Left ||
306
+ // globalStore.scale_info.type === EScaleInfoType.BottomLeft
307
+ // ? -(newTopLeftPoint.x - globalStore.mouse_info.now_position_x)
308
+ // : globalStore.scale_info.type === EScaleInfoType.TopRight ||
309
+ // globalStore.scale_info.type === EScaleInfoType.Right ||
310
+ // globalStore.scale_info.type === EScaleInfoType.BottomRight
311
+ // ? globalStore.mouse_info.now_position_x - newTopLeftPoint.x
312
+ // : 0;
313
+ // const move_length_y =
314
+ // globalStore.scale_info.type === EScaleInfoType.TopLeft ||
315
+ // globalStore.scale_info.type === EScaleInfoType.TopCenter ||
316
+ // globalStore.scale_info.type === EScaleInfoType.TopRight
317
+ // ? newTopLeftPoint.y - globalStore.mouse_info.now_position_y
318
+ // : globalStore.scale_info.type === EScaleInfoType.BottomLeft ||
319
+ // globalStore.scale_info.type === EScaleInfoType.BottomCenter ||
320
+ // globalStore.scale_info.type === EScaleInfoType.BottomRight
321
+ // ? globalStore.mouse_info.now_position_y - newTopLeftPoint.y
322
+ // : 0;
323
+
324
+ //算出缩放倍数
325
+ if (globalStore.handle_svg_info && new_length.width > 0 && new_length.height > 0) {
326
+ const scale_x = !new_length.is_old_width
327
+ ? new_length.width / globalStore.handle_svg_info.info.actual_bound.width
328
+ : 1
329
+ const scale_y = !new_length.is_old_height
330
+ ? new_length.height / globalStore.handle_svg_info.info.actual_bound.height
331
+ : 1
332
+ const newCenterPoint = getCenterPoint(curPosition, globalStore.scale_info.symmetric_point)
333
+ if (
334
+ scale_x > 0 &&
335
+ globalStore.scale_info.type !== EScaleInfoType.TopCenter &&
336
+ globalStore.scale_info.type !== EScaleInfoType.BottomCenter
337
+ ) {
338
+ globalStore.handle_svg_info.info.scale_x = scale_x
339
+ globalStore.handle_svg_info.info.x = getSvgNowPosition(
340
+ globalStore.handle_svg_info.info.client.x,
341
+ newCenterPoint.x,
342
+ globalStore.scale_info.scale_item_info.x
343
+ )
344
+ }
345
+ if (
346
+ scale_y > 0 &&
347
+ globalStore.scale_info.type !== EScaleInfoType.Left &&
348
+ globalStore.scale_info.type !== EScaleInfoType.Right
349
+ ) {
350
+ globalStore.handle_svg_info.info.scale_y = scale_y
351
+ globalStore.handle_svg_info.info.y = getSvgNowPosition(
352
+ globalStore.handle_svg_info.info.client.y,
353
+ newCenterPoint.y,
354
+ globalStore.scale_info.scale_item_info.y
355
+ )
356
+ }
357
+ }
358
+ } else if (globalStore.intention === EGlobalStoreIntention.Rotate) {
359
+ if (!globalStore.handle_svg_info) {
360
+ return
361
+ }
362
+ const rotateDegreeBefore =
363
+ Math.atan2(
364
+ globalStore.mouse_info.position_y - globalStore.handle_svg_info.info.client.y,
365
+ globalStore.mouse_info.position_x - globalStore.handle_svg_info.info.client.x
366
+ ) /
367
+ (Math.PI / 180)
368
+ const rotateDegreeAfter =
369
+ Math.atan2(
370
+ clientY - svgEditLayoutStore.center_offset.y - globalStore.handle_svg_info.info.client.y,
371
+ clientX - svgEditLayoutStore.center_offset.x - globalStore.handle_svg_info.info.client.x
372
+ ) /
373
+ (Math.PI / 180)
374
+ globalStore.handle_svg_info.info.rotate = globalStore.rotate_info.angle + rotateDegreeAfter - rotateDegreeBefore
375
+ } else if (globalStore.intention === EGlobalStoreIntention.Connection && globalStore.handle_svg_info) {
376
+ globalStore.handle_svg_info.info.props.point_position.val[
377
+ globalStore.handle_svg_info?.info.props.point_position.val.length - 1
378
+ ] = {
379
+ x: getSvgNowPosition(
380
+ globalStore.mouse_info.position_x,
381
+ clientX,
382
+ globalStore.handle_svg_info?.info.props.point_position.val[0].x
383
+ ),
384
+ y: getSvgNowPosition(
385
+ globalStore.mouse_info.position_y,
386
+ clientY,
387
+ globalStore.handle_svg_info?.info.props.point_position.val[0].y
388
+ )
389
+ }
390
+ // console.log('连线', start_x, start_y, end_x, end_y, clientX, clientY);
391
+ } else if (globalStore.intention === EGlobalStoreIntention.SetConnectionLineNode && globalStore.handle_svg_info) {
392
+ globalStore.handle_svg_info.info.props.point_position.val[globalStore.connection_line_node_info.point_index] = {
393
+ x: getSvgNowPosition(
394
+ globalStore.mouse_info.position_x,
395
+ clientX,
396
+ globalStore.connection_line_node_info.init_pos.x
397
+ ),
398
+ y: getSvgNowPosition(
399
+ globalStore.mouse_info.position_y,
400
+ clientY,
401
+ globalStore.connection_line_node_info.init_pos.y
402
+ )
403
+ }
404
+ }
405
+ }
406
+ const onCanvasMouseUp = () => {
407
+ //如果鼠标不是按下状态
408
+ if (globalStore.mouse_info.state != EMouseInfoState.Down) {
409
+ return
410
+ }
411
+ if (globalStore.handle_svg_info?.info && globalStore.intention == EGlobalStoreIntention.Move) {
412
+ globalStore.done_json[globalStore.handle_svg_info.index].x = globalStore.mouse_info.new_position_x
413
+ globalStore.done_json[globalStore.handle_svg_info.index].y = globalStore.mouse_info.new_position_y
414
+ // globalStore.setDoneJson(globalStore.done_json);
415
+ setSvgActualInfo(globalStore.done_json[globalStore.handle_svg_info.index])
416
+ globalStore.intention = EGlobalStoreIntention.None
417
+ //记录历史记录
418
+ globalStore.setDoneJson(globalStore.done_json)
419
+ // globalStore.setHandleSvgInfo(undefined, 0);
420
+ } else if (globalStore.handle_svg_info?.info && globalStore.intention == EGlobalStoreIntention.Zoom) {
421
+ //缩放完成后重置中点 新版本中点就是组件坐标
422
+ // const newCenterPoint = getCenterPoint(
423
+ // { x: e.clientX, y: e.clientY },
424
+ // globalStore.scale_info.symmetric_point
425
+ // );
426
+ globalStore.handle_svg_info.info.client = {
427
+ x: globalStore.handle_svg_info.info.x,
428
+ y: globalStore.handle_svg_info.info.y
429
+ }
430
+ globalStore.intention = EGlobalStoreIntention.None
431
+ setSvgActualInfo(globalStore.done_json[globalStore.handle_svg_info.index])
432
+ //记录历史记录
433
+ globalStore.setDoneJson(globalStore.done_json)
434
+ } else if (globalStore.intention === EGlobalStoreIntention.Rotate && globalStore.handle_svg_info?.info) {
435
+ setSvgActualInfo(globalStore.done_json[globalStore.handle_svg_info.index])
436
+ //记录历史记录
437
+ globalStore.setDoneJson(globalStore.done_json)
438
+ } else if (globalStore.intention === EGlobalStoreIntention.Connection) {
439
+ return
440
+ } else if (globalStore.intention != EGlobalStoreIntention.Select) {
441
+ globalStore.intention = EGlobalStoreIntention.None
442
+ }
443
+ globalStore.setMouseInfo({
444
+ state: EMouseInfoState.Up,
445
+ position_x: 0,
446
+ position_y: 0,
447
+ now_position_x: 0,
448
+ now_position_y: 0,
449
+ new_position_x: 0,
450
+ new_position_y: 0
451
+ })
452
+ contextMenuStore.display = false
453
+ }
454
+ const onCanvasMouseDown = (e: MouseEvent) => {
455
+ const { clientX, clientY } = e
456
+ if (globalStore.intention === EGlobalStoreIntention.Connection && globalStore.handle_svg_info) {
457
+ if (e.button === 0) {
458
+ //鼠标左键创建新线段
459
+ globalStore.handle_svg_info.info.props.point_position.val.push({
460
+ x: getSvgNowPosition(
461
+ globalStore.mouse_info.position_x,
462
+ clientX,
463
+ globalStore.handle_svg_info?.info.props.point_position.val[0].x
464
+ ),
465
+ y: getSvgNowPosition(
466
+ globalStore.mouse_info.position_y,
467
+ clientY,
468
+ globalStore.handle_svg_info?.info.props.point_position.val[0].y
469
+ )
470
+ })
471
+ }
472
+ if (e.button === 2) {
473
+ //鼠标右键结束线段绘制
474
+ globalStore.intention = EGlobalStoreIntention.None
475
+ setSvgActualInfo(globalStore.done_json[globalStore.handle_svg_info.index])
476
+ }
477
+ return
478
+ }
479
+ //点击画布 未选中组件 拖动画布
480
+ globalStore.intention = EGlobalStoreIntention.MoveCanvas
481
+ globalStore.setMouseInfo({
482
+ state: EMouseInfoState.Down,
483
+ position_x: clientX,
484
+ position_y: clientY,
485
+ now_position_x: svgEditLayoutStore.center_offset.x,
486
+ now_position_y: svgEditLayoutStore.center_offset.y,
487
+ new_position_x: svgEditLayoutStore.center_offset.x,
488
+ new_position_y: svgEditLayoutStore.center_offset.y
489
+ })
490
+ }
491
+ /**
492
+ * 鼠标右键事件
493
+ * @param e
494
+ * @returns
495
+ */
496
+ const onCanvasContextMenuEvent = (e: MouseEvent) => {
497
+ e.stopPropagation()
498
+ e.preventDefault() //禁用浏览器右键
499
+ }
500
+ const onSvgContextMenuEvent = (select_item: IDoneJson, index: number, e: MouseEvent) => {
501
+ console.log(globalStore.intention)
502
+ if (globalStore.intention === EGlobalStoreIntention.Connection) {
503
+ return
504
+ }
505
+
506
+ if (contextMenuRef.value) {
507
+ globalStore.intention = EGlobalStoreIntention.ContextMenu
508
+ globalStore.setHandleSvgInfo(select_item, index)
509
+ contextMenuRef.value!.style.left = e.pageX + 'px'
510
+ contextMenuRef.value!.style.top = e.pageY + 'px'
511
+ contextMenuStore.info.MoveUpOneLevel.enable =
512
+ contextMenuStore.info.MoveUpTopLevel.enable =
513
+ contextMenuStore.info.MoveDownOneLevel.enable =
514
+ contextMenuStore.info.MoveDownTopLevel.enable =
515
+ true
516
+ if (index === globalStore.done_json.length - 1) {
517
+ contextMenuStore.info.MoveUpOneLevel.enable = contextMenuStore.info.MoveUpTopLevel.enable = false
518
+ }
519
+ if (index === 0) {
520
+ contextMenuStore.info.MoveDownOneLevel.enable = contextMenuStore.info.MoveDownTopLevel.enable = false
521
+ }
522
+ contextMenuStore.display = true
523
+ }
524
+ }
525
+ const getActualBoundScale = (
526
+ actual_bound: {
527
+ x: number
528
+ y: number
529
+ width: number
530
+ height: number
531
+ },
532
+ scale_x: number,
533
+ scale_y: number
534
+ ) => {
535
+ return {
536
+ x: actual_bound.x - (actual_bound.width / 2) * scale_x + actual_bound.width / 2,
537
+ y: actual_bound.y - (actual_bound.height / 2) * scale_y + actual_bound.height / 2,
538
+ width: actual_bound.width * scale_x,
539
+ height: actual_bound.height * scale_y
540
+ }
541
+ }
542
+ const onHandleKeyDown = (e: KeyboardEvent) => {
543
+ console.log(e, 733)
544
+ e.preventDefault()
545
+ if (globalStore.handle_svg_info && !e.ctrlKey && e.key == 'ArrowUp') {
546
+ globalStore.done_json[globalStore.handle_svg_info.index].y -= 1
547
+ useHistoryRecord(globalStore.done_json)
548
+ } else if (globalStore.handle_svg_info && !e.ctrlKey && e.key == 'ArrowDown') {
549
+ globalStore.handle_svg_info.info.y += 1
550
+ useHistoryRecord(globalStore.done_json)
551
+ } else if (globalStore.handle_svg_info && !e.ctrlKey && e.key == 'ArrowLeft') {
552
+ globalStore.handle_svg_info.info.x -= 1
553
+ useHistoryRecord(globalStore.done_json)
554
+ } else if (globalStore.handle_svg_info && !e.ctrlKey && e.key == 'ArrowRight') {
555
+ globalStore.handle_svg_info.info.x += 1
556
+ useHistoryRecord(globalStore.done_json)
557
+ }
558
+ //ctrl c
559
+ else if (e.ctrlKey && e.key.toLowerCase() == 'c') {
560
+ contextMenuStore.onContextMenuClick(EContextMenuInfoType.Copy)
561
+ }
562
+ //deleted
563
+ else if (!e.ctrlKey && e.key == 'Delete') {
564
+ contextMenuStore.onContextMenuClick(EContextMenuInfoType.Delete)
565
+ }
566
+ //上移一层
567
+ else if (e.ctrlKey && e.key == 'ArrowUp') {
568
+ contextMenuStore.onContextMenuClick(EContextMenuInfoType.MoveUpOneLevel)
569
+ }
570
+ //下移一层
571
+ else if (e.ctrlKey && e.key == 'ArrowDown') {
572
+ contextMenuStore.onContextMenuClick(EContextMenuInfoType.MoveDownOneLevel)
573
+ }
574
+ //置于底层
575
+ else if (e.ctrlKey && e.key == 'ArrowLeft') {
576
+ contextMenuStore.onContextMenuClick(EContextMenuInfoType.MoveDownTopLevel)
577
+ }
578
+ //置于顶层
579
+ else if (e.ctrlKey && e.key == 'ArrowRight') {
580
+ contextMenuStore.onContextMenuClick(EContextMenuInfoType.MoveUpTopLevel)
581
+ }
582
+ //ctrl+shift+z
583
+ else if (e.ctrlKey && e.shiftKey && e.key.toLowerCase() == 'z') {
584
+ editPrivateStore.topRedoBtnClick()
585
+ }
586
+ //ctrl+z
587
+ else if (e.ctrlKey && e.key.toLowerCase() == 'z') {
588
+ editPrivateStore.topUndoBtnClick()
589
+ }
590
+ //ctrl+delete
591
+ else if (e.ctrlKey && e.key.toLowerCase() == 'delete') {
592
+ globalStore.done_json.length <= 0 || globalStore.setDoneJson([])
593
+ }
594
+ }
595
+
596
+ const resizeBox = () => {
597
+ setSvgActualInfo(globalStore.done_json[globalStore.handle_svg_info!.index], true)
598
+ }
599
+
600
+ onMounted(() => {
601
+ canvasRef.value?.focus()
602
+ })
603
+ </script>
604
+
605
+ <template>
606
+ <div
607
+ class="canvas"
608
+ tabindex="0"
609
+ ref="canvasRef"
610
+ @drop="dropEvent"
611
+ @dragenter="dragEnterEvent"
612
+ @dragover="dragOverEvent"
613
+ @mousedown="onCanvasMouseDown"
614
+ @mousemove="onCanvasMouseMove"
615
+ @mouseup="onCanvasMouseUp"
616
+ @contextmenu="onCanvasContextMenuEvent"
617
+ @keydown="onHandleKeyDown"
618
+ >
619
+ <svg
620
+ xmlns="http://www.w3.org/2000/svg"
621
+ :style="{ backgroundColor: configStore.svg.background_color }"
622
+ width="100%"
623
+ height="100%"
624
+ >
625
+ <defs>
626
+ <pattern id="pattern_grid" patternUnits="userSpaceOnUse" x="0" y="0" width="10" height="10">
627
+ <rect width="1" height="1" rx="1" ry="1" fill="#aaaaaa" />
628
+ </pattern>
629
+ </defs>
630
+ <rect v-if="configStore.svg.grid" width="100%" height="100%" fill="url(#pattern_grid)" />
631
+ <g
632
+ :transform="`translate(${configStore.svg.position_center.x + svgEditLayoutStore.center_offset.x},${
633
+ configStore.svg.position_center.y + svgEditLayoutStore.center_offset.y
634
+ })rotate(${0})scale(${configStore.svg.scale})`"
635
+ >
636
+ <g
637
+ v-for="(item, index) in globalStore.done_json"
638
+ :key="item.id"
639
+ :transform="`translate(${item.x},${item.y})rotate(0)scale(1)`"
640
+ v-show="item.display"
641
+ >
642
+ <g :class="`${getCommonClass(item)}`">
643
+ <g
644
+ :transform="`translate(${item.actual_bound.x + item.actual_bound.width / 2},${
645
+ item.actual_bound.y + item.actual_bound.height / 2
646
+ })rotate(${item.rotate}) scale(1) translate(${-(item.actual_bound.x + item.actual_bound.width / 2)},${-(
647
+ item.actual_bound.y +
648
+ item.actual_bound.height / 2
649
+ )})`"
650
+ @mousedown="onSvgMouseDown(item, index, $event)"
651
+ @mouseenter="onSvgMouseEnter(item, index, $event)"
652
+ @mouseleave="onSvgMouseLeave(item, index, $event)"
653
+ @contextmenu="onSvgContextMenuEvent(item, index, $event)"
654
+ >
655
+ <connection-line
656
+ v-if="item.type === EDoneJsonType.ConnectionLine"
657
+ :item-info="item"
658
+ :point-visible="visible_info.connection_line && visible_info.select_item.info?.id == item.id"
659
+ />
660
+ <use
661
+ v-else-if="item.type === EDoneJsonType.File"
662
+ :xlink:href="`#svg-${item.name}`"
663
+ v-bind="prosToVBind(item)"
664
+ width="100"
665
+ height="100"
666
+ :id="item.id"
667
+ :transform="`translate(${item.actual_bound.x + item.actual_bound.width / 2},${
668
+ item.actual_bound.y + item.actual_bound.height / 2
669
+ }) scale(${item.scale_x},${item.scale_y}) translate(${-(
670
+ item.actual_bound.x +
671
+ item.actual_bound.width / 2
672
+ )},${-(item.actual_bound.y + item.actual_bound.height / 2)})`"
673
+ ></use>
674
+ <component
675
+ v-else-if="item.type === EDoneJsonType.CustomSvg"
676
+ :is="item.tag"
677
+ v-bind="prosToVBind(item)"
678
+ width="100"
679
+ height="100"
680
+ :id="item.id"
681
+ @resize="resizeBox"
682
+ :transform="`translate(${item.actual_bound.x + item.actual_bound.width / 2},${
683
+ item.actual_bound.y + item.actual_bound.height / 2
684
+ }) scale(${item.scale_x},${item.scale_y}) translate(${-(
685
+ item.actual_bound.x +
686
+ item.actual_bound.width / 2
687
+ )},${-(item.actual_bound.y + item.actual_bound.height / 2)})`"
688
+ />
689
+ <foreignObject
690
+ v-else-if="item.type === EDoneJsonType.Vue"
691
+ v-bind="getActualBoundScale(item.actual_bound, item.scale_x, item.scale_y)"
692
+ :id="`foreign-object${item.id}`"
693
+ >
694
+ <component
695
+ :is="item.tag"
696
+ v-bind="prosToVBind(item)"
697
+ :id="item.id"
698
+ :transform="`translate(${item.actual_bound.x + item.actual_bound.width / 2},${
699
+ item.actual_bound.y + item.actual_bound.height / 2
700
+ }) scale(${item.scale_x},${item.scale_y}) translate(${-(
701
+ item.actual_bound.x +
702
+ item.actual_bound.width / 2
703
+ )},${-(item.actual_bound.y + item.actual_bound.height / 2)})`"
704
+ >{{ item.tag_slot }}
705
+ </component>
706
+ </foreignObject>
707
+
708
+ <line
709
+ v-else-if="item.type === EDoneJsonType.StraightLine"
710
+ :id="item.id"
711
+ :x1="item.props.start_x.val"
712
+ :y1="item.props.start_y.val"
713
+ :x2="item.props.end_x.val"
714
+ :y2="item.props.end_y.val"
715
+ fill="#FF0000"
716
+ stroke="#FF0000"
717
+ stroke-width="2"
718
+ />
719
+ <rect
720
+ v-if="item.config.actual_rect"
721
+ :id="`rect${item.id}`"
722
+ fill="black"
723
+ fill-opacity="0"
724
+ v-bind="getActualBoundScale(item.actual_bound, item.scale_x, item.scale_y)"
725
+ style="stroke: none; stroke-width: 2; stroke-miterlimit: 10"
726
+ :class="`${
727
+ globalStore.intention == EGlobalStoreIntention.None ||
728
+ globalStore.intention == EGlobalStoreIntention.Select
729
+ ? 'svg-item-none'
730
+ : ''
731
+ }
732
+ ${
733
+ globalStore.intention == EGlobalStoreIntention.Move &&
734
+ globalStore.handle_svg_info?.info.id == item.id
735
+ ? 'svg-item-move'
736
+ : ''
737
+ } ${
738
+ globalStore.intention == EGlobalStoreIntention.Select &&
739
+ globalStore.handle_svg_info?.info.id == item.id
740
+ ? 'svg-item-select'
741
+ : ''
742
+ }`"
743
+ />
744
+ <handle-panel
745
+ v-if="
746
+ globalStore.handle_svg_info?.info.id === item.id && visible_info.handle_panel && item.config.can_zoom
747
+ "
748
+ :item-info="item"
749
+ />
750
+ <connection-panel
751
+ v-if="
752
+ visible_info.select_item.info?.id == item.id &&
753
+ visible_info.connection_panel &&
754
+ item.config.have_anchor &&
755
+ (globalStore.intention === EGlobalStoreIntention.Select
756
+ ? item.id !== globalStore.handle_svg_info?.info.id
757
+ : true)
758
+ "
759
+ :item-info="item"
760
+ />
761
+ </g>
762
+ </g>
763
+ </g>
764
+ </g>
765
+ </svg>
766
+ <!-- 右键菜单 -->
767
+ <ul ref="contextMenuRef" class="contextMenu" v-show="contextMenuStore.display">
768
+ <li
769
+ v-for="(item, key) in contextMenuStore.info"
770
+ :key="item.title"
771
+ @click="contextMenuStore.onContextMenuClick(key)"
772
+ >
773
+ <p :class="item.enable ? '' : 'disabled'">
774
+ {{ item.title }}
775
+ <span class="shortcut">{{ item.hot_key }}</span>
776
+ </p>
777
+ </li>
778
+ </ul>
779
+ </div>
780
+ </template>
781
+
782
+ <style lang="less" scoped>
783
+ .canvas {
784
+ width: 100%;
785
+ height: 100%;
786
+ cursor: v-bind('cursor_style');
787
+
788
+ &:focus-visible {
789
+ outline: 0;
790
+ }
791
+ }
792
+
793
+ .svg-item-none {
794
+ cursor: move;
795
+
796
+ &:hover {
797
+ outline: 1px solid #0cf;
798
+ }
799
+ }
800
+
801
+ .svg-item-move {
802
+ cursor: move;
803
+ outline: 1px dashed rgb(23, 222, 30);
804
+ }
805
+
806
+ .svg-item-select {
807
+ cursor: move;
808
+ outline: 1px solid rgb(23, 222, 30);
809
+ }
810
+
811
+ .contextMenu {
812
+ position: fixed;
813
+ z-index: 99999;
814
+ background: #ffffff;
815
+ padding: 5px 0;
816
+ margin: 0;
817
+ display: block;
818
+ border-radius: 5px;
819
+ box-shadow: 2px 5px 10px rgba(0, 0, 0, 0.3);
820
+
821
+ li {
822
+ list-style: none;
823
+ padding: 0;
824
+ margin: 0;
825
+ }
826
+
827
+ .shortcut {
828
+ width: 115px;
829
+ text-align: right;
830
+ float: right;
831
+ }
832
+
833
+ p {
834
+ text-decoration: none;
835
+ display: block;
836
+ padding: 0 15px 1px 20px;
837
+ margin: 0;
838
+ user-select: none;
839
+ -webkit-user-select: none;
840
+ }
841
+
842
+ p:hover {
843
+ background-color: #0cf;
844
+ color: #ffffff;
845
+ cursor: default;
846
+ }
847
+
848
+ .disabled {
849
+ color: #999;
850
+ }
851
+
852
+ .disabled:hover {
853
+ color: #999;
854
+ background-color: transparent;
855
+ }
856
+
857
+ li.separator {
858
+ border-top: solid 1px #e3e3e3;
859
+ padding-top: 5px;
860
+ margin-top: 5px;
861
+ }
862
+ }
863
+
864
+ .common-ani {
865
+ transform-box: fill-box;
866
+ }
867
+ </style>