@zhangqingcq/vgce 0.0.14 → 0.0.16

Sign up to get free protection for your applications and to get access to all the features.
Files changed (119) hide show
  1. package/README.md +38 -3
  2. package/dist/vgce.js +5040 -5305
  3. package/dist/vgce.umd.cjs +43 -143
  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-2.svg +1 -0
  27. package/src/assets/svgs/circuit-breaker.svg +11 -0
  28. package/src/assets/svgs/clock-a.svg +23 -0
  29. package/src/assets/svgs/common-table.svg +7 -0
  30. package/src/assets/svgs/el-button.svg +10 -0
  31. package/src/assets/svgs/el-tag.svg +13 -0
  32. package/src/assets/svgs/house.svg +1 -0
  33. package/src/assets/svgs/light.svg +24 -0
  34. package/src/assets/svgs/now-time.svg +9 -0
  35. package/src/assets/svgs/package.svg +1 -0
  36. package/src/assets/svgs/pie-charts.svg +10 -0
  37. package/src/assets/svgs/progress-a.svg +1 -0
  38. package/src/assets/svgs/reservoir.svg +10 -0
  39. package/src/assets/svgs/svg-text.svg +5 -0
  40. package/src/assets/svgs/switch-a.svg +5 -0
  41. package/src/components/ace-edit/index.ts +27 -0
  42. package/src/components/config/index.ts +450 -0
  43. package/src/components/config/types.ts +25 -0
  44. package/src/components/svg-analysis/index.vue +11 -0
  45. package/src/components/svg-editor/center-panel/index.vue +867 -0
  46. package/src/components/svg-editor/center-panel/types.ts +11 -0
  47. package/src/components/svg-editor/component-tree/index.vue +33 -0
  48. package/src/components/svg-editor/connection-line/index.vue +125 -0
  49. package/src/components/svg-editor/connection-panel/index.vue +198 -0
  50. package/src/components/svg-editor/export-json/index.vue +37 -0
  51. package/src/components/svg-editor/handle-panel/index.vue +342 -0
  52. package/src/components/svg-editor/import-json/index.vue +37 -0
  53. package/src/components/svg-editor/index.vue +280 -0
  54. package/src/components/svg-editor/left-panel/index.vue +83 -0
  55. package/src/components/svg-editor/right-panel/code-edit-modal.vue +50 -0
  56. package/src/components/svg-editor/right-panel/common-animate.vue +96 -0
  57. package/src/components/svg-editor/right-panel/condition.vue +101 -0
  58. package/src/components/svg-editor/right-panel/dynamic-el-form-item.vue +97 -0
  59. package/src/components/svg-editor/right-panel/index.vue +304 -0
  60. package/src/components/svg-editor/right-panel/list.vue +86 -0
  61. package/src/components/svg-editor/top-panel/index.vue +139 -0
  62. package/src/components/svg-editor/types.ts +22 -0
  63. package/src/components/svg-viewer/index.vue +340 -0
  64. package/src/components/vue3-ruler-tool/index.vue +506 -0
  65. package/src/config/files/clock-a.vue +66 -0
  66. package/src/config/files/common-table.vue +49 -0
  67. package/src/config/files/light-a.vue +72 -0
  68. package/src/config/files/now-time.vue +53 -0
  69. package/src/config/files/pie-charts.vue +72 -0
  70. package/src/config/files/progress.vue +40 -0
  71. package/src/config/files/svg-text.vue +39 -0
  72. package/src/config/files/switch-a.vue +45 -0
  73. package/src/config/index.ts +28 -0
  74. package/src/config/svg/animation/index.ts +8 -0
  75. package/src/config/svg/animation/reservoir.ts +32 -0
  76. package/src/config/svg/custom/clock-a.ts +23 -0
  77. package/src/config/svg/custom/index.ts +11 -0
  78. package/src/config/svg/custom/light.ts +29 -0
  79. package/src/config/svg/custom/svg-text.ts +54 -0
  80. package/src/config/svg/custom/switch-a.ts +29 -0
  81. package/src/config/svg/index.ts +12 -0
  82. package/src/config/svg/stateful/circuit-breaker.ts +38 -0
  83. package/src/config/svg/stateful/index.ts +8 -0
  84. package/src/config/svg/stateless/alternator.ts +28 -0
  85. package/src/config/svg/stateless/bot-2.ts +22 -0
  86. package/src/config/svg/stateless/house.ts +22 -0
  87. package/src/config/svg/stateless/index.ts +14 -0
  88. package/src/config/types.ts +126 -0
  89. package/src/config/vue/component/button.ts +57 -0
  90. package/src/config/vue/component/common-table.ts +124 -0
  91. package/src/config/vue/component/index.ts +13 -0
  92. package/src/config/vue/component/now-time.ts +29 -0
  93. package/src/config/vue/component/progress.ts +29 -0
  94. package/src/config/vue/component/tag.ts +46 -0
  95. package/src/config/vue/echarts/index.ts +8 -0
  96. package/src/config/vue/echarts/pie-charts.ts +60 -0
  97. package/src/config/vue/index.ts +5 -0
  98. package/src/hooks.ts +47 -0
  99. package/src/index.ts +14 -0
  100. package/src/main.ts +15 -0
  101. package/src/router.ts +24 -0
  102. package/src/stores/config/index.ts +44 -0
  103. package/src/stores/config/types.ts +27 -0
  104. package/src/stores/global/index.ts +109 -0
  105. package/src/stores/global/types.ts +115 -0
  106. package/src/stores/main.ts +10 -0
  107. package/src/stores/svg-edit-layout/index.ts +17 -0
  108. package/src/stores/svg-edit-layout/types.ts +8 -0
  109. package/src/stores/system/index.ts +174 -0
  110. package/src/stores/system/types.ts +43 -0
  111. package/src/utils/fetch.ts +351 -0
  112. package/src/utils/file-read-write.ts +26 -0
  113. package/src/utils/index.ts +397 -0
  114. package/src/utils/mqtt-net.ts +48 -0
  115. package/src/utils/proxy.ts +7 -0
  116. package/src/utils/scale-core.ts +214 -0
  117. package/src/utils/types.ts +13 -0
  118. package/src/views/EditorS.vue +18 -0
  119. package/src/views/Preview.vue +12 -0
@@ -0,0 +1,397 @@
1
+ import { ELineBindAnchors } from '@/components/config/types'
2
+ import { EDoneJsonType } from '@/config/types'
3
+ import type { IConfigItem } from '@/config/types'
4
+ import type { IDoneJson } from '@/stores/global/types'
5
+
6
+ /**
7
+ * 生成随机字符串
8
+ * @param len 生成个数
9
+ */
10
+ export const randomString = (len?: number) => {
11
+ len = len || 10
12
+ const str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
13
+ const maxPos = str.length
14
+ let random_str = ''
15
+ for (let i = 0; i < len; i++) {
16
+ let t = maxPos
17
+ if (i === 0) {
18
+ t = maxPos - 10
19
+ }
20
+ random_str += str.charAt(Math.floor(Math.random() * t))
21
+ }
22
+ return random_str
23
+ }
24
+
25
+ // 通过泛型定义通用类型保护函数
26
+ export const isOfType = <T>(target: unknown, prop: keyof T): target is T => {
27
+ return (target as T)[prop] !== undefined
28
+ }
29
+ /**
30
+ * 获取坐标偏移量
31
+ * @param length 真实宽/高
32
+ * @param scale 缩放倍数
33
+ * @returns 坐标偏移量
34
+ */
35
+ export const getCoordinateOffset = (length: number, scale: number) => {
36
+ return (length / 2) * (scale - 1)
37
+ }
38
+ // 角度转弧度
39
+ // Math.PI = 180 度
40
+ export const angleToRadian = (angle: number) => {
41
+ return (angle * Math.PI) / 180
42
+ }
43
+ /**
44
+ * 计算根据圆心旋转后的点的坐标
45
+ * @param {Object} point 旋转前的点坐标
46
+ * @param {Object} center 旋转中心
47
+ * @param {Number} rotate 旋转的角度
48
+ * @return {Object} 旋转后的坐标
49
+ * https://www.zhihu.com/question/67425734/answer/252724399 旋转矩阵公式
50
+ */
51
+ export const calculateRotatedPointCoordinate = (
52
+ point: { x: number; y: number },
53
+ center: { x: number; y: number },
54
+ rotate: number
55
+ ) => {
56
+ /**
57
+ * 旋转公式:
58
+ * 点a(x, y)
59
+ * 旋转中心c(x, y)
60
+ * 旋转后点n(x, y)
61
+ * 旋转角度θ tan ??
62
+ * nx = cosθ * (ax - cx) - sinθ * (ay - cy) + cx
63
+ * ny = sinθ * (ax - cx) + cosθ * (ay - cy) + cy
64
+ */
65
+
66
+ return {
67
+ x:
68
+ (point.x - center.x) * Math.cos(angleToRadian(rotate)) -
69
+ (point.y - center.y) * Math.sin(angleToRadian(rotate)) +
70
+ center.x,
71
+ y:
72
+ (point.x - center.x) * Math.sin(angleToRadian(rotate)) +
73
+ (point.y - center.y) * Math.cos(angleToRadian(rotate)) +
74
+ center.y
75
+ }
76
+ }
77
+ // 求两点之间的中点坐标
78
+ export const getCenterPoint = (p1: { x: number; y: number }, p2: { x: number; y: number }) => {
79
+ return {
80
+ x: p1.x + (p2.x - p1.x) / 2,
81
+ y: p1.y + (p2.y - p1.y) / 2
82
+ }
83
+ }
84
+ /**
85
+ * 坐标数组转换成path路径
86
+ * @param position_arr
87
+ * @returns
88
+ */
89
+ export const positionArrToPath = (position_arr: { x: number; y: number }[]) => {
90
+ let path_str = ''
91
+ for (let index = 0; index < position_arr.length; index++) {
92
+ if (index === 0) {
93
+ path_str += `M ${position_arr[index].x} ${position_arr[index].y}`
94
+ } else {
95
+ path_str += ` L ${position_arr[index].x} ${position_arr[index].y}`
96
+ }
97
+ }
98
+ return path_str
99
+ }
100
+ /**
101
+ * 获取相对于svg最新的坐标
102
+ * @param init_pos 相对于页面的初始坐标
103
+ * @param finally_pos 相对于页面的最终坐标
104
+ * @param svg_init_pos 相对于svg的初始坐标
105
+ * @returns svg最新的坐标
106
+ */
107
+ export const getSvgNowPosition = (init_pos: number, finally_pos: number, svg_init_pos: number) => {
108
+ return svg_init_pos + (finally_pos - init_pos)
109
+ }
110
+ /**
111
+ * 对象深拷贝
112
+ * @param object
113
+ * @param default_val
114
+ * @returns
115
+ */
116
+ export const objectDeepClone = <T>(object: object, default_val: any = {}) => {
117
+ if (!object) {
118
+ return default_val as T
119
+ }
120
+ return JSON.parse(JSON.stringify(object)) as T
121
+ }
122
+ /**
123
+ * 设置实际的属性
124
+ * @param done_json
125
+ * @param resize
126
+ */
127
+ export const setSvgActualInfo = (done_json: IDoneJson, resize?: boolean) => {
128
+ const queryBbox = document.querySelector(`#${done_json.id}`)
129
+ const rectBBox = document.querySelector(`#rect${done_json.id}`)
130
+ if (queryBbox) {
131
+ let x = 0,
132
+ y = 0,
133
+ width = 0,
134
+ height = 0
135
+ if (done_json.type !== EDoneJsonType.Vue) {
136
+ const BBox = (queryBbox as SVGGraphicsElement).getBBox()
137
+ console.log(BBox)
138
+ x = BBox.x
139
+ y = BBox.y
140
+ width = BBox.width
141
+ height = BBox.height
142
+ } else {
143
+ width = (queryBbox as HTMLElement).offsetWidth
144
+ height = (queryBbox as HTMLElement).offsetHeight
145
+ width = width === 0 ? 100 : width
146
+ height = height === 0 ? 100 : height
147
+ x = 50 - width / 2
148
+ y = 50 - height / 2
149
+ const foreignObjectBox = document.querySelector(`#foreign-object${done_json.id}`)
150
+ if (
151
+ foreignObjectBox &&
152
+ foreignObjectBox.getAttribute('x') === '0' &&
153
+ foreignObjectBox.getAttribute('y') === '0' &&
154
+ foreignObjectBox.getAttribute('width') === '0' &&
155
+ foreignObjectBox.getAttribute('height') === '0'
156
+ ) {
157
+ foreignObjectBox.setAttribute('x', x.toString())
158
+ foreignObjectBox.setAttribute('y', y.toString())
159
+ foreignObjectBox.setAttribute('width', width.toString())
160
+ foreignObjectBox.setAttribute('height', height.toString())
161
+ }
162
+ }
163
+ if (
164
+ rectBBox &&
165
+ rectBBox.getAttribute('x') === '0' &&
166
+ rectBBox.getAttribute('y') === '0' &&
167
+ rectBBox.getAttribute('width') === '0' &&
168
+ rectBBox.getAttribute('height') === '0'
169
+ ) {
170
+ rectBBox.setAttribute('x', x.toString())
171
+ rectBBox.setAttribute('y', y.toString())
172
+ rectBBox.setAttribute('width', width.toString())
173
+ rectBBox.setAttribute('height', height.toString())
174
+ }
175
+ //实际大小和坐标理论上不会变 但是如果子组件设置了100% 还是会变 所以要做下判断
176
+ if (
177
+ (done_json.actual_bound.x === 0 &&
178
+ done_json.actual_bound.y === 0 &&
179
+ done_json.actual_bound.width === 0 &&
180
+ done_json.actual_bound.height === 0) ||
181
+ resize
182
+ ) {
183
+ done_json.actual_bound = {
184
+ x,
185
+ y,
186
+ width,
187
+ height
188
+ }
189
+ }
190
+ done_json.point_coordinate.tl = {
191
+ x: done_json.x - (width * done_json.scale_x) / 2,
192
+ y: done_json.y - (height * done_json.scale_y) / 2
193
+ }
194
+ done_json.point_coordinate.tc = {
195
+ x: done_json.x,
196
+ y: done_json.y - (height * done_json.scale_y) / 2
197
+ }
198
+ done_json.point_coordinate.tr = {
199
+ x: done_json.x + (width * done_json.scale_x) / 2,
200
+ y: done_json.y - (height * done_json.scale_y) / 2
201
+ }
202
+ done_json.point_coordinate.l = {
203
+ x: done_json.x - (width * done_json.scale_x) / 2,
204
+ y: done_json.y
205
+ }
206
+ done_json.point_coordinate.r = {
207
+ x: done_json.x + (width * done_json.scale_x) / 2,
208
+ y: done_json.y
209
+ }
210
+ done_json.point_coordinate.bl = {
211
+ x: done_json.x - (width * done_json.scale_x) / 2,
212
+ y: done_json.y + (height * done_json.scale_y) / 2
213
+ }
214
+ done_json.point_coordinate.bc = {
215
+ x: done_json.x,
216
+ y: done_json.y + (height * done_json.scale_y) / 2
217
+ }
218
+ done_json.point_coordinate.br = {
219
+ x: done_json.x + (width * done_json.scale_x) / 2,
220
+ y: done_json.y + (height * done_json.scale_y) / 2
221
+ }
222
+ if (done_json.rotate !== 0) {
223
+ setAfterRotationPointCoordinate(done_json)
224
+ }
225
+ }
226
+ }
227
+ /**
228
+ * 根据锚点类型获取锚点坐标
229
+ * @param anchor_type
230
+ * @param done_json
231
+ * @returns
232
+ */
233
+ export const getAnchorPosByAnchorType = (anchor_type: ELineBindAnchors, done_json: IDoneJson) => {
234
+ if (anchor_type === ELineBindAnchors.BottomCenter) {
235
+ return done_json.point_coordinate.bc
236
+ } else if (anchor_type === ELineBindAnchors.Left) {
237
+ return done_json.point_coordinate.l
238
+ } else if (anchor_type === ELineBindAnchors.Right) {
239
+ return done_json.point_coordinate.r
240
+ } else {
241
+ return done_json.point_coordinate.tc
242
+ }
243
+ }
244
+ /**
245
+ * 旋转之后重新设置组件八点坐标
246
+ * @param item
247
+ */
248
+ export const setAfterRotationPointCoordinate = (item: IDoneJson) => {
249
+ item.point_coordinate = {
250
+ tl: calculateRotatedPointCoordinate(
251
+ item.point_coordinate.tl,
252
+ {
253
+ x: item.x,
254
+ y: item.y
255
+ },
256
+ item.rotate
257
+ ),
258
+ tc: calculateRotatedPointCoordinate(
259
+ item.point_coordinate.tc,
260
+ {
261
+ x: item.x,
262
+ y: item.y
263
+ },
264
+ item.rotate
265
+ ),
266
+ tr: calculateRotatedPointCoordinate(
267
+ item.point_coordinate.tr,
268
+ {
269
+ x: item.x,
270
+ y: item.y
271
+ },
272
+ item.rotate
273
+ ),
274
+ l: calculateRotatedPointCoordinate(
275
+ item.point_coordinate.l,
276
+ {
277
+ x: item.x,
278
+ y: item.y
279
+ },
280
+ item.rotate
281
+ ),
282
+ r: calculateRotatedPointCoordinate(
283
+ item.point_coordinate.r,
284
+ {
285
+ x: item.x,
286
+ y: item.y
287
+ },
288
+ item.rotate
289
+ ),
290
+ bl: calculateRotatedPointCoordinate(
291
+ item.point_coordinate.bl,
292
+ {
293
+ x: item.x,
294
+ y: item.y
295
+ },
296
+ item.rotate
297
+ ),
298
+ bc: calculateRotatedPointCoordinate(
299
+ item.point_coordinate.bc,
300
+ {
301
+ x: item.x,
302
+ y: item.y
303
+ },
304
+ item.rotate
305
+ ),
306
+ br: calculateRotatedPointCoordinate(
307
+ item.point_coordinate.br,
308
+ {
309
+ x: item.x,
310
+ y: item.y
311
+ },
312
+ item.rotate
313
+ )
314
+ }
315
+ }
316
+
317
+ export const prosToVBind = (item: IConfigItem) => {
318
+ let temp = {}
319
+ if (item.state) {
320
+ for (const key in item.state) {
321
+ if (key === 'OnOff') {
322
+ for (const on_off_key in item.state[key]?.props) {
323
+ temp = {
324
+ ...temp,
325
+ ...{
326
+ [on_off_key]: item.state[key]?.default
327
+ ? item.state[key]?.props[on_off_key].openVal
328
+ : item.state[key]?.props[on_off_key].closeVal
329
+ }
330
+ }
331
+ }
332
+ }
333
+ }
334
+ }
335
+ for (const key in item.props) {
336
+ temp = { ...temp, ...{ [key]: item.props[key].val } }
337
+ }
338
+ return temp
339
+ }
340
+ export const setArrItemByID = (id: string, key: string, val: any, json_arr: IDoneJson[]) => {
341
+ return new Promise((res) => {
342
+ const find_item = json_arr.find((f) => f.id === id)
343
+ if (!find_item) {
344
+ res({
345
+ status: false,
346
+ msg: '要设置的id不存在'
347
+ })
348
+ }
349
+ eval(`find_item.${key} = val;`)
350
+ res({
351
+ status: true,
352
+ msg: '操作成功'
353
+ })
354
+ })
355
+ }
356
+ export const getCommonClass = (item: IDoneJson) => {
357
+ if (!item.common_animations || !item.common_animations.val) {
358
+ return ``
359
+ }
360
+ return `common-ani animate__animated animate__${item.common_animations.val} animate__${item.common_animations.speed} animate__${item.common_animations.repeat} animate__${item.common_animations.delay}`
361
+ }
362
+
363
+ export const numberArray = (l: number) => {
364
+ let t: number[] = []
365
+ for (let i = 0; i < l; i++) {
366
+ t.push(i)
367
+ }
368
+ return t
369
+ }
370
+
371
+ /*获取字符串width*/
372
+ export const getStringWidth = (str: string, fontSize = 12) => {
373
+ if (str.length > 0) {
374
+ let nodesH = document.createElement('span')
375
+ nodesH.style.fontSize = fontSize + 'px'
376
+ nodesH.style.fontFamily = 'inherit'
377
+ nodesH.innerHTML = str
378
+ nodesH.style.opacity = '0'
379
+ nodesH.style.position = 'fixed'
380
+ nodesH.style.top = '3000px'
381
+ document.body.append(nodesH)
382
+ const width = nodesH.clientWidth
383
+ document.body.removeChild(nodesH)
384
+ return width
385
+ }
386
+ return 0
387
+ }
388
+
389
+ export const valFormat = (v: any) => {
390
+ if (/false|true/.test(v)) {
391
+ return v !== 'false'
392
+ }
393
+ if (/^\d+(\.\d+)?$/.test(v)) {
394
+ return Number(v)
395
+ }
396
+ return v
397
+ }
@@ -0,0 +1,48 @@
1
+ import { connect } from 'mqtt/dist/mqtt'
2
+ import type { MqttClient, PacketCallback } from 'mqtt'
3
+
4
+ let client: MqttClient
5
+
6
+ export const sub = (url: string, user: string, pwd: string, topics: string, callback: Function) => {
7
+ client = connect(url, {
8
+ username: user,
9
+ password: pwd
10
+ })
11
+
12
+ client.on('connect', () => {
13
+ console.log('MQTT服务器连接成功')
14
+ console.log(client.options.clientId)
15
+ client.subscribe(topics, { qos: 1 })
16
+ })
17
+
18
+ client.on('message', callback)
19
+ }
20
+
21
+ export const pub = (url: string, user: string, pwd: string, topics: string, data: any, callback: PacketCallback) => {
22
+ client = connect(url, {
23
+ username: user,
24
+ password: pwd
25
+ })
26
+
27
+ client.on('connect', () => {
28
+ console.log('MQTT服务器连接成功')
29
+ console.log(client.options.clientId)
30
+ client.publish(
31
+ topics,
32
+ JSON.stringify(data),
33
+ {
34
+ qos: 0,
35
+ retain: true
36
+ },
37
+ callback
38
+ )
39
+ })
40
+ }
41
+
42
+ export const close = () => {
43
+ if (client && client.end) {
44
+ client.end(true, {}, () => {
45
+ console.log('MQTT服务连接关闭')
46
+ })
47
+ }
48
+ }
@@ -0,0 +1,7 @@
1
+ import type { ComponentInternalInstance } from 'vue'
2
+ import { getCurrentInstance } from 'vue'
3
+
4
+ export default function () {
5
+ const { appContext } = getCurrentInstance() as ComponentInternalInstance
6
+ return appContext.config.globalProperties
7
+ }
@@ -0,0 +1,214 @@
1
+ import { calculateRotatedPointCoordinate, getCenterPoint } from '.'
2
+ import type { IScalePoint } from './types'
3
+ /**
4
+ * 左上角缩放
5
+ * @param curPosition 按住的缩放按钮的坐标
6
+ * @param symmetricPoint 缩放前对称点的坐标
7
+ * @param rotate 旋转角度
8
+ * @returns
9
+ */
10
+ export const calculateLeftTop = (curPosition: IScalePoint, symmetricPoint: IScalePoint, rotate: number) => {
11
+ //新的中心点坐标
12
+ const newCenterPoint = getCenterPoint(curPosition, symmetricPoint)
13
+ const newTopLeftPoint = calculateRotatedPointCoordinate(curPosition, newCenterPoint, -rotate)
14
+ const newBottomRightPoint = calculateRotatedPointCoordinate(symmetricPoint, newCenterPoint, -rotate)
15
+
16
+ return {
17
+ width: newBottomRightPoint.x - newTopLeftPoint.x,
18
+ height: newBottomRightPoint.y - newTopLeftPoint.y,
19
+ is_old_width: false,
20
+ is_old_height: false
21
+ }
22
+ }
23
+ /**
24
+ * 右上角缩放
25
+ * @param curPosition 按住的缩放按钮的坐标
26
+ * @param symmetricPoint 缩放前对称点的坐标
27
+ * @param rotate 旋转角度
28
+ * @returns
29
+ */
30
+ export const calculateRightTop = (curPosition: IScalePoint, symmetricPoint: IScalePoint, rotate: number) => {
31
+ const newCenterPoint = getCenterPoint(curPosition, symmetricPoint)
32
+ const newTopRightPoint = calculateRotatedPointCoordinate(curPosition, newCenterPoint, -rotate)
33
+ const newBottomLeftPoint = calculateRotatedPointCoordinate(symmetricPoint, newCenterPoint, -rotate)
34
+
35
+ return {
36
+ width: newTopRightPoint.x - newBottomLeftPoint.x,
37
+ height: newBottomLeftPoint.y - newTopRightPoint.y,
38
+ is_old_width: false,
39
+ is_old_height: false
40
+ }
41
+ }
42
+ /**
43
+ * 右下角缩放
44
+ * @param curPosition 按住的缩放按钮的坐标
45
+ * @param symmetricPoint 缩放前对称点的坐标
46
+ * @param rotate 旋转角度
47
+ * @returns
48
+ */
49
+ export const calculateRightBottom = (curPosition: IScalePoint, symmetricPoint: IScalePoint, rotate: number) => {
50
+ const newCenterPoint = getCenterPoint(curPosition, symmetricPoint)
51
+ const newTopLeftPoint = calculateRotatedPointCoordinate(symmetricPoint, newCenterPoint, -rotate)
52
+ const newBottomRightPoint = calculateRotatedPointCoordinate(curPosition, newCenterPoint, -rotate)
53
+
54
+ return {
55
+ width: newBottomRightPoint.x - newTopLeftPoint.x,
56
+ height: newBottomRightPoint.y - newTopLeftPoint.y,
57
+ is_old_width: false,
58
+ is_old_height: false
59
+ }
60
+ }
61
+ /**
62
+ * 左下角缩放
63
+ * @param curPosition 按住的缩放按钮的坐标
64
+ * @param symmetricPoint 缩放前对称点的坐标
65
+ * @param rotate 旋转角度
66
+ * @returns
67
+ */
68
+ export const calculateLeftBottom = (curPosition: IScalePoint, symmetricPoint: IScalePoint, rotate: number) => {
69
+ const newCenterPoint = getCenterPoint(curPosition, symmetricPoint)
70
+ const newTopRightPoint = calculateRotatedPointCoordinate(symmetricPoint, newCenterPoint, -rotate)
71
+ const newBottomLeftPoint = calculateRotatedPointCoordinate(curPosition, newCenterPoint, -rotate)
72
+
73
+ return {
74
+ width: newTopRightPoint.x - newBottomLeftPoint.x,
75
+ height: newBottomLeftPoint.y - newTopRightPoint.y,
76
+ is_old_width: false,
77
+ is_old_height: false
78
+ }
79
+ }
80
+ /**
81
+ * 顶点中心缩放
82
+ * @param curPosition 按住的缩放按钮的坐标
83
+ * @param symmetricPoint 缩放前对称点的坐标
84
+ * @param rotate 旋转角度
85
+ * @param curPoint
86
+ * @returns
87
+ */
88
+ export const calculateTop = (
89
+ curPosition: IScalePoint,
90
+ symmetricPoint: IScalePoint,
91
+ rotate: number,
92
+ curPoint: IScalePoint
93
+ ) => {
94
+ const rotatedCurPosition = calculateRotatedPointCoordinate(curPosition, curPoint, -rotate)
95
+ const rotatedTopMiddlePoint = calculateRotatedPointCoordinate(
96
+ {
97
+ x: curPoint.x,
98
+ y: rotatedCurPosition.y
99
+ },
100
+ curPoint,
101
+ rotate
102
+ )
103
+ const newHeight = Math.sqrt(
104
+ (rotatedTopMiddlePoint.x - symmetricPoint.x) ** 2 + (rotatedTopMiddlePoint.y - symmetricPoint.y) ** 2
105
+ )
106
+ return {
107
+ width: 1,
108
+ height: Math.round(newHeight),
109
+ is_old_width: true,
110
+ is_old_height: false
111
+ }
112
+ }
113
+ /**
114
+ * 右侧中心缩放
115
+ * @param curPosition 按住的缩放按钮的坐标
116
+ * @param symmetricPoint 缩放前对称点的坐标
117
+ * @param rotate 旋转角度
118
+ * @returns
119
+ */
120
+ export const calculateRight = (
121
+ curPosition: IScalePoint,
122
+ symmetricPoint: IScalePoint,
123
+ rotate: number,
124
+ curPoint: IScalePoint
125
+ ) => {
126
+ const rotatedCurPosition = calculateRotatedPointCoordinate(curPosition, curPoint, -rotate)
127
+ const rotatedRightMiddlePoint = calculateRotatedPointCoordinate(
128
+ {
129
+ x: rotatedCurPosition.x,
130
+ y: curPoint.y
131
+ },
132
+ curPoint,
133
+ rotate
134
+ )
135
+
136
+ const newWidth = Math.sqrt(
137
+ (rotatedRightMiddlePoint.x - symmetricPoint.x) ** 2 + (rotatedRightMiddlePoint.y - symmetricPoint.y) ** 2
138
+ )
139
+
140
+ return {
141
+ width: Math.round(newWidth),
142
+ height: 1,
143
+ is_old_width: false,
144
+ is_old_height: true
145
+ }
146
+ }
147
+ /**
148
+ * 底部中心缩放
149
+ * @param curPosition 按住的缩放按钮的坐标
150
+ * @param symmetricPoint 缩放前对称点的坐标
151
+ * @param rotate 旋转角度
152
+ * @returns
153
+ */
154
+ export const calculateBottom = (
155
+ curPosition: IScalePoint,
156
+ symmetricPoint: IScalePoint,
157
+ rotate: number,
158
+ curPoint: IScalePoint
159
+ ) => {
160
+ const rotatedCurPosition = calculateRotatedPointCoordinate(curPosition, curPoint, -rotate)
161
+ const rotatedBottomMiddlePoint = calculateRotatedPointCoordinate(
162
+ {
163
+ x: curPoint.x,
164
+ y: rotatedCurPosition.y
165
+ },
166
+ curPoint,
167
+ rotate
168
+ )
169
+
170
+ const newHeight = Math.sqrt(
171
+ (rotatedBottomMiddlePoint.x - symmetricPoint.x) ** 2 + (rotatedBottomMiddlePoint.y - symmetricPoint.y) ** 2
172
+ )
173
+
174
+ return {
175
+ width: 1,
176
+ height: Math.round(newHeight),
177
+ is_old_width: true,
178
+ is_old_height: false
179
+ }
180
+ }
181
+ /**
182
+ * 左侧中心缩放
183
+ * @param curPosition 按住的缩放按钮的坐标
184
+ * @param symmetricPoint 缩放前对称点的坐标
185
+ * @param rotate 旋转角度
186
+ * @returns
187
+ */
188
+ export const calculateLeft = (
189
+ curPosition: IScalePoint,
190
+ symmetricPoint: IScalePoint,
191
+ rotate: number,
192
+ curPoint: IScalePoint
193
+ ) => {
194
+ const rotatedCurPosition = calculateRotatedPointCoordinate(curPosition, curPoint, -rotate)
195
+ const rotatedLeftMiddlePoint = calculateRotatedPointCoordinate(
196
+ {
197
+ x: rotatedCurPosition.x,
198
+ y: curPoint.y
199
+ },
200
+ curPoint,
201
+ rotate
202
+ )
203
+
204
+ const newWidth = Math.sqrt(
205
+ (rotatedLeftMiddlePoint.x - symmetricPoint.x) ** 2 + (rotatedLeftMiddlePoint.y - symmetricPoint.y) ** 2
206
+ )
207
+
208
+ return {
209
+ width: Math.round(newWidth),
210
+ height: 1,
211
+ is_old_width: false,
212
+ is_old_height: true
213
+ }
214
+ }
@@ -0,0 +1,13 @@
1
+ import type { VNode } from 'vue'
2
+ export interface IScalePoint {
3
+ x: number
4
+ y: number
5
+ }
6
+
7
+ export type RichTxt = string | VNode | HTMLElement
8
+
9
+ export interface PlainObject extends Object {
10
+ [k: keyof any]: any
11
+ }
12
+
13
+ export type Collection = PlainObject | PlainObject[]
@@ -0,0 +1,18 @@
1
+ <script setup lang="ts">
2
+ import SvgEditor from '@/components/svg-editor/index.vue'
3
+ import { useStore } from '@/stores/main'
4
+ import { useRouter } from 'vue-router'
5
+ import type { IDataModel } from '@/components/svg-editor/types'
6
+
7
+ const router = useRouter()
8
+ const store = useStore()
9
+
10
+ function preview(d: IDataModel) {
11
+ store.data = d
12
+ router.push('/Preview')
13
+ }
14
+ </script>
15
+
16
+ <template>
17
+ <SvgEditor :data="(store.data && JSON.stringify(store.data)) || ''" @onPreview="preview" />
18
+ </template>
@@ -0,0 +1,12 @@
1
+ <script setup lang="ts">
2
+ import SvgViewer from '@/components/svg-viewer/index.vue'
3
+ import { useStore } from '@/stores/main'
4
+
5
+ const store = useStore()
6
+ </script>
7
+
8
+ <template>
9
+ <svg-viewer :data="store.data" />
10
+ </template>
11
+
12
+ <style lang="less" scoped></style>