@zhangqingcq/vgce 0.1.13 → 0.1.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -5
- package/dist/style.css +1 -1
- package/dist/vgce.js +3545 -3491
- package/dist/vgce.umd.cjs +20 -20
- package/package.json +1 -1
- package/src/assets/base.less +32 -0
- package/src/components/svg-editor/center-panel.vue +17 -14
- package/src/components/svg-editor/right-panel.vue +2 -1
- package/src/components/svg-viewer.vue +74 -27
- package/src/components/vue3-ruler-tool.vue +9 -5
- package/src/config/types.ts +1 -0
- package/src/utils/index.ts +32 -14
- package/src/views/Preview.vue +1 -1
package/package.json
CHANGED
package/src/assets/base.less
CHANGED
@@ -109,7 +109,39 @@ body {
|
|
109
109
|
|
110
110
|
.tree-v {
|
111
111
|
--el-color-primary-light-9: @listActiveColor;
|
112
|
+
|
112
113
|
&.el-tree--highlight-current .el-tree-node.is-current > .el-tree-node__content {
|
113
114
|
color: #fff;
|
114
115
|
}
|
115
116
|
}
|
117
|
+
|
118
|
+
.coverLayer {
|
119
|
+
position: absolute;
|
120
|
+
left: 0;
|
121
|
+
top: 0;
|
122
|
+
bottom: 0;
|
123
|
+
right: 0;
|
124
|
+
}
|
125
|
+
|
126
|
+
.can-not-select {
|
127
|
+
user-select: none;
|
128
|
+
}
|
129
|
+
|
130
|
+
.canvasInfoTxt {
|
131
|
+
color: #bbb;
|
132
|
+
position: absolute;
|
133
|
+
left: 20px;
|
134
|
+
bottom: 10px;
|
135
|
+
font-size: 12px;
|
136
|
+
|
137
|
+
.icoP {
|
138
|
+
margin-left: 10px;
|
139
|
+
position: relative;
|
140
|
+
top: 2px;
|
141
|
+
cursor: pointer;
|
142
|
+
|
143
|
+
&:hover {
|
144
|
+
color: @activeIconOut;
|
145
|
+
}
|
146
|
+
}
|
147
|
+
}
|
@@ -18,7 +18,8 @@
|
|
18
18
|
randomString,
|
19
19
|
resetHandlePointOld,
|
20
20
|
setSvgActualInfo,
|
21
|
-
|
21
|
+
getZoomPosition,
|
22
|
+
myFixed
|
22
23
|
} from '@/utils'
|
23
24
|
import {
|
24
25
|
calculateBottom,
|
@@ -494,10 +495,10 @@
|
|
494
495
|
//算出缩放倍数
|
495
496
|
if (globalStore.handle_svg_info && new_length.width > 0 && new_length.height > 0) {
|
496
497
|
const scale_x = !new_length.is_old_width
|
497
|
-
?
|
498
|
+
? myFixed(new_length.width / globalStore.handle_svg_info.info.actual_bound.width, 3)
|
498
499
|
: 1
|
499
500
|
const scale_y = !new_length.is_old_height
|
500
|
-
?
|
501
|
+
? myFixed(new_length.height / globalStore.handle_svg_info.info.actual_bound.height, 3)
|
501
502
|
: 1
|
502
503
|
const newCenterPoint = getCenterPoint(curPosition, globalStore.scale_info.symmetric_point)
|
503
504
|
if (
|
@@ -549,8 +550,9 @@
|
|
549
550
|
globalStore.handle_svg_info.info.x
|
550
551
|
) /
|
551
552
|
(Math.PI / 180)
|
552
|
-
globalStore.handle_svg_info.info.rotate =
|
553
|
-
|
553
|
+
globalStore.handle_svg_info.info.rotate = myFixed(
|
554
|
+
globalStore.rotate_info.angle + rotateDegreeAfter - rotateDegreeBefore,
|
555
|
+
2
|
554
556
|
)
|
555
557
|
} else if (globalStore.intention === EGlobalStoreIntention.Connection && globalStore.handle_svg_info) {
|
556
558
|
//鼠标移动的实时位置(相对于连线起始点,只在创建第一个点时记录了鼠标原始位置)
|
@@ -766,9 +768,11 @@
|
|
766
768
|
function onMousewheel(e: any) {
|
767
769
|
if (e?.wheelDelta) {
|
768
770
|
if (e.wheelDelta > 0) {
|
769
|
-
configStore.svg.scale =
|
770
|
-
|
771
|
-
|
771
|
+
configStore.svg.scale = myFixed(configStore.svg.scale + 0.1, 1)
|
772
|
+
getZoomPosition(e, configStore.svg.scale, svgEditLayoutStore.center_offset, true)
|
773
|
+
} else if (configStore.svg.scale > 0.1) {
|
774
|
+
configStore.svg.scale = myFixed(configStore.svg.scale - 0.1, 1)
|
775
|
+
getZoomPosition(e, configStore.svg.scale, svgEditLayoutStore.center_offset, false)
|
772
776
|
}
|
773
777
|
}
|
774
778
|
}
|
@@ -817,10 +821,10 @@
|
|
817
821
|
scale_y: number
|
818
822
|
) => {
|
819
823
|
return {
|
820
|
-
x:
|
821
|
-
y:
|
822
|
-
width:
|
823
|
-
height:
|
824
|
+
x: myFixed(actual_bound.x - (actual_bound.width / 2) * scale_x + actual_bound.width / 2, 1),
|
825
|
+
y: myFixed(actual_bound.y - (actual_bound.height / 2) * scale_y + actual_bound.height / 2, 1),
|
826
|
+
width: myFixed(actual_bound.width * scale_x, 1),
|
827
|
+
height: myFixed(actual_bound.height * scale_y, 1)
|
824
828
|
}
|
825
829
|
}
|
826
830
|
const onHandleKeyDown = (e: KeyboardEvent) => {
|
@@ -959,7 +963,7 @@
|
|
959
963
|
@mousewheel="onMousewheel"
|
960
964
|
>
|
961
965
|
<slot name="background" />
|
962
|
-
<div
|
966
|
+
<div class="coverLayer">
|
963
967
|
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%">
|
964
968
|
<defs>
|
965
969
|
<pattern id="pattern_grid" patternUnits="userSpaceOnUse" x="0" y="0" width="20" height="20">
|
@@ -980,7 +984,6 @@
|
|
980
984
|
:key="item.id"
|
981
985
|
:transform="`translate(${item.x},${item.y})rotate(0)scale(1)`"
|
982
986
|
v-show="item.display"
|
983
|
-
@mousewheel="stopEvent"
|
984
987
|
>
|
985
988
|
<g :class="`${getCommonClass(item)}`">
|
986
989
|
<g
|
@@ -313,7 +313,8 @@
|
|
313
313
|
<el-form-item label="行为" size="small">
|
314
314
|
<el-select v-model="item.action" @change="addEventList($event, item)">
|
315
315
|
<el-option value="ChangeAttr" label="改变属性" />
|
316
|
-
<el-option value="JavaScript" label="执行JavaScript" />
|
316
|
+
<el-option value="JavaScript" label="执行 JavaScript" />
|
317
|
+
<el-option value="Emit" label="emit 事件" />
|
317
318
|
</el-select>
|
318
319
|
</el-form-item>
|
319
320
|
|
@@ -1,11 +1,15 @@
|
|
1
1
|
<script setup lang="ts">
|
2
2
|
import { pinia } from '@/hooks'
|
3
|
+
import { ElIcon } from 'element-plus'
|
4
|
+
import { Aim } from '@element-plus/icons-vue'
|
3
5
|
import { useGlobalStore } from '@/stores/global'
|
4
6
|
import { EGlobalStoreIntention, EMouseInfoState } from '@/stores/global/types'
|
5
7
|
import type { IDoneJson } from '@/stores/global/types'
|
6
8
|
import {
|
7
9
|
componentsRegister,
|
8
10
|
getCommonClass,
|
11
|
+
getZoomPosition,
|
12
|
+
myFixed,
|
9
13
|
preventDefault,
|
10
14
|
prosToVBind,
|
11
15
|
setArrItemByID,
|
@@ -25,11 +29,12 @@
|
|
25
29
|
|
26
30
|
setEditorLoadTime()
|
27
31
|
|
28
|
-
const emit = defineEmits(['onMessage'])
|
32
|
+
const emit = defineEmits(['onMessage', 'onEvent'])
|
29
33
|
const props = withDefaults(
|
30
|
-
defineProps<{ vueComp?: Record<string, any>; data?: IDataModel; canvasDrag?: boolean }>(),
|
34
|
+
defineProps<{ vueComp?: Record<string, any>; data?: IDataModel; canvasDrag?: boolean; showCanvasInfo?: boolean }>(),
|
31
35
|
{
|
32
|
-
canvasDrag: true
|
36
|
+
canvasDrag: true,
|
37
|
+
showCanvasInfo: true
|
33
38
|
}
|
34
39
|
)
|
35
40
|
const globalStore = useGlobalStore(pinia)
|
@@ -72,14 +77,18 @@
|
|
72
77
|
return
|
73
78
|
}
|
74
79
|
const { clientX, clientY } = e
|
75
|
-
globalStore.mouse_info.new_position_x =
|
76
|
-
|
77
|
-
|
78
|
-
globalStore.mouse_info.
|
80
|
+
globalStore.mouse_info.new_position_x = Math.round(clientX / preview_data.config.svg.scale)
|
81
|
+
globalStore.mouse_info.new_position_y = Math.round(clientY / preview_data.config.svg.scale)
|
82
|
+
const x = Math.round(
|
83
|
+
globalStore.mouse_info.new_position_x - globalStore.mouse_info.position_x + globalStore.mouse_info.now_position_x
|
84
|
+
)
|
85
|
+
const y = Math.round(
|
86
|
+
globalStore.mouse_info.new_position_y - globalStore.mouse_info.position_y + globalStore.mouse_info.now_position_y
|
87
|
+
)
|
79
88
|
if (globalStore.intention == EGlobalStoreIntention.MoveCanvas) {
|
80
89
|
//移动画布
|
81
|
-
preview_data.layout_center.x =
|
82
|
-
preview_data.layout_center.y =
|
90
|
+
preview_data.layout_center.x = x
|
91
|
+
preview_data.layout_center.y = y
|
83
92
|
}
|
84
93
|
}
|
85
94
|
const onCanvasMouseUp = () => {
|
@@ -106,21 +115,23 @@
|
|
106
115
|
globalStore.intention = EGlobalStoreIntention.MoveCanvas
|
107
116
|
globalStore.mouse_info = {
|
108
117
|
state: EMouseInfoState.Down,
|
109
|
-
position_x: clientX,
|
110
|
-
position_y: clientY,
|
118
|
+
position_x: Math.round(clientX / preview_data.config.svg.scale),
|
119
|
+
position_y: Math.round(clientY / preview_data.config.svg.scale),
|
111
120
|
now_position_x: preview_data.layout_center.x,
|
112
121
|
now_position_y: preview_data.layout_center.y,
|
113
|
-
new_position_x:
|
114
|
-
new_position_y:
|
122
|
+
new_position_x: 0,
|
123
|
+
new_position_y: 0
|
115
124
|
}
|
116
125
|
}
|
117
126
|
|
118
127
|
function onMousewheel(e: any) {
|
119
128
|
if (e?.wheelDelta) {
|
120
129
|
if (e.wheelDelta > 0) {
|
121
|
-
preview_data.config.svg.scale =
|
130
|
+
preview_data.config.svg.scale = myFixed(preview_data.config.svg.scale + 0.1, 1)
|
131
|
+
getZoomPosition(e, preview_data.config.svg.scale, preview_data.layout_center, true)
|
122
132
|
} else {
|
123
|
-
preview_data.config.svg.scale =
|
133
|
+
preview_data.config.svg.scale = myFixed(preview_data.config.svg.scale - 0.1, 1)
|
134
|
+
getZoomPosition(e, preview_data.config.svg.scale, preview_data.layout_center, false)
|
124
135
|
}
|
125
136
|
}
|
126
137
|
}
|
@@ -156,7 +167,6 @@
|
|
156
167
|
return { cursor: t ? 'pointer' : 'default' }
|
157
168
|
}
|
158
169
|
const eventHandle = (root: IDoneJson, type: EEventType) => {
|
159
|
-
console.log(root.events, type)
|
160
170
|
if (root.events?.length > 0) {
|
161
171
|
for (let e of root.events) {
|
162
172
|
if (e.type === type) {
|
@@ -204,6 +214,28 @@
|
|
204
214
|
} else if (e.action === EEventAction.JavaScript) {
|
205
215
|
const t = new Function(e.scripts)
|
206
216
|
t()
|
217
|
+
} else if (e.action === EEventAction.Emit) {
|
218
|
+
const _k: Array<keyof IDoneJson> = [
|
219
|
+
'id',
|
220
|
+
'name',
|
221
|
+
'common_animations',
|
222
|
+
'display',
|
223
|
+
'props',
|
224
|
+
'title',
|
225
|
+
'type',
|
226
|
+
'x',
|
227
|
+
'y'
|
228
|
+
]
|
229
|
+
const _r: Record<string, any> = {}
|
230
|
+
_k.forEach((x) => {
|
231
|
+
if (root?.hasOwnProperty?.(x)) {
|
232
|
+
_r[x] = root[x]
|
233
|
+
}
|
234
|
+
})
|
235
|
+
emit('onEvent', {
|
236
|
+
event: e,
|
237
|
+
target: _r
|
238
|
+
})
|
207
239
|
}
|
208
240
|
}
|
209
241
|
}
|
@@ -230,6 +262,13 @@
|
|
230
262
|
}
|
231
263
|
}
|
232
264
|
|
265
|
+
const resetCanvas = () => {
|
266
|
+
preview_data.layout_center = {
|
267
|
+
x: 0,
|
268
|
+
y: 0
|
269
|
+
}
|
270
|
+
}
|
271
|
+
|
233
272
|
const connectNet = () => {
|
234
273
|
const m = preview_data.config.net.mqtt
|
235
274
|
if (m && m.url && m.user && m.pwd && m.topics) {
|
@@ -240,12 +279,12 @@
|
|
240
279
|
//用户拿到消息后可以配合setNodeAttrByID方法更新界面
|
241
280
|
//setNodeAttrByID的参数id可以在传给本组件的props.data(用户传进来的,自然知道值是多少)里done_json找到
|
242
281
|
/*如何找到指定组件的两种方案:
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
282
|
+
1.用你的项目里前后端约定的svg组件唯一标识符替换掉编辑器生成的id(必须保证唯一),然后调用setNodeAttrByID改变组件属性。
|
283
|
+
2.如果不想改动id(避免因不能保证手动改过的id唯一性导致编辑器功能异常),可以在config里给想要改变的组件的配置文件的props里增加一个字段,
|
284
|
+
如deviceCode(svg-text的配置文件里有被注释的例子),然后在编辑组态时,给对应组件填上对应的deviceCode(这样deviceCode就和组件id实现
|
285
|
+
了映射关系),并保存,后台给前台推MQTT消息时带上指定的deviceCode,前台预览时,在收到MQTT消息后,凭借消息里的deviceCode在done_json
|
286
|
+
找到组件的id(可以用vue的computed计算一份deviceCode和id的映射关系存到一个对象里,这样在需要id时可直接在计算出的对象凭借deviceCode
|
287
|
+
直接取到),即可用setNodeAttrByID改变组件属性*/
|
249
288
|
emit('onMessage', {
|
250
289
|
topics,
|
251
290
|
message
|
@@ -287,12 +326,12 @@
|
|
287
326
|
@contextmenu="preventDefault"
|
288
327
|
>
|
289
328
|
<slot name="background" />
|
290
|
-
<div
|
329
|
+
<div class="coverLayer">
|
291
330
|
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%">
|
292
331
|
<g
|
293
|
-
:transform="`translate(${preview_data.layout_center.x
|
294
|
-
preview_data.config.svg.scale
|
295
|
-
})`"
|
332
|
+
:transform="`translate(${preview_data.layout_center.x * preview_data.config.svg.scale},${
|
333
|
+
preview_data.layout_center.y * preview_data.config.svg.scale
|
334
|
+
})rotate(${0})scale(${preview_data.config.svg.scale})`"
|
296
335
|
>
|
297
336
|
<g
|
298
337
|
v-for="item in preview_data.done_json"
|
@@ -304,7 +343,6 @@
|
|
304
343
|
@mousedown="stopEvent"
|
305
344
|
@mousemove="stopEvent"
|
306
345
|
@mouseup="stopEvent"
|
307
|
-
@mousewheel="stopEvent"
|
308
346
|
>
|
309
347
|
<g :class="`${getCommonClass(item)}`">
|
310
348
|
<g
|
@@ -371,6 +409,15 @@
|
|
371
409
|
</g>
|
372
410
|
</svg>
|
373
411
|
</div>
|
412
|
+
|
413
|
+
<div class="can-not-select canvasInfoTxt" v-show="showCanvasInfo"
|
414
|
+
>缩放倍数:{{ preview_data.config.svg.scale }}倍,画布位置:{{ myFixed(preview_data.layout_center.x, 2) }},{{
|
415
|
+
myFixed(preview_data.layout_center.y, 2)
|
416
|
+
}}
|
417
|
+
<el-icon class="icoP" :size="14" @click="resetCanvas" title="重置位置">
|
418
|
+
<Aim />
|
419
|
+
</el-icon>
|
420
|
+
</div>
|
374
421
|
</div>
|
375
422
|
</template>
|
376
423
|
|
@@ -2,7 +2,7 @@
|
|
2
2
|
import { pinia } from '@/hooks'
|
3
3
|
import { useSvgEditLayoutStore } from '@/stores/svg-edit-layout'
|
4
4
|
import { useConfigStore } from '@/stores/config'
|
5
|
-
import {
|
5
|
+
import { myFixed, preventDefault } from '@/utils'
|
6
6
|
|
7
7
|
const emit = defineEmits(['onLineMouseUp'])
|
8
8
|
const props = withDefaults(
|
@@ -144,12 +144,12 @@
|
|
144
144
|
if (array.length === 0) {
|
145
145
|
for (let i = 0; i < length; i += props.stepLength) {
|
146
146
|
if (i % props.stepLength === 0) {
|
147
|
-
array.push({ id:
|
147
|
+
array.push({ id: myFixed(i / configStore.svg.scale - start, 0) })
|
148
148
|
}
|
149
149
|
}
|
150
150
|
} else {
|
151
151
|
array.forEach((e, i) => {
|
152
|
-
e.id =
|
152
|
+
e.id = myFixed((i * props.stepLength) / configStore.svg.scale - start, 0)
|
153
153
|
})
|
154
154
|
}
|
155
155
|
}
|
@@ -311,10 +311,14 @@
|
|
311
311
|
<span v-for="(item, index) in yScale" :style="{ top: index * stepLength + 'px' }" class="n">{{ item.id }}</span>
|
312
312
|
</div>
|
313
313
|
<div :style="{ top: verticalDottedTop + 'px' }" class="vue-ruler-ref-dot-h"
|
314
|
-
><span>{{
|
314
|
+
><span>{{
|
315
|
+
Math.round((verticalDottedTop - rulerHeight) / configStore.svg.scale - svgEditLayoutStore.center_offset.y)
|
316
|
+
}}</span></div
|
315
317
|
>
|
316
318
|
<div :style="{ left: horizontalDottedLeft + 'px' }" class="vue-ruler-ref-dot-v"
|
317
|
-
><span>{{
|
319
|
+
><span>{{
|
320
|
+
Math.round((horizontalDottedLeft - rulerWidth) / configStore.svg.scale - svgEditLayoutStore.center_offset.x)
|
321
|
+
}}</span></div
|
318
322
|
>
|
319
323
|
<div
|
320
324
|
v-for="item in lineList"
|
package/src/config/types.ts
CHANGED
package/src/utils/index.ts
CHANGED
@@ -18,6 +18,10 @@ export const preventDefault = (e: any) => {
|
|
18
18
|
e.preventDefault()
|
19
19
|
}
|
20
20
|
|
21
|
+
export const myFixed = (d: number, n: number) => {
|
22
|
+
return Number(d.toFixed(n))
|
23
|
+
}
|
24
|
+
|
21
25
|
export function componentsRegister(data?: Record<string, any>) {
|
22
26
|
//注册所有组件
|
23
27
|
const instance = getCurrentInstance()
|
@@ -95,19 +99,17 @@ export const calculateRotatedPointCoordinate = (
|
|
95
99
|
*/
|
96
100
|
|
97
101
|
return {
|
98
|
-
x:
|
99
|
-
(
|
100
|
-
(point.x - center.x) * Math.cos(angleToRadian(rotate)) -
|
102
|
+
x: myFixed(
|
103
|
+
(point.x - center.x) * Math.cos(angleToRadian(rotate)) -
|
101
104
|
(point.y - center.y) * Math.sin(angleToRadian(rotate)) +
|
102
|
-
center.x
|
103
|
-
|
105
|
+
center.x,
|
106
|
+
1
|
104
107
|
),
|
105
|
-
y:
|
106
|
-
(
|
107
|
-
(point.x - center.x) * Math.sin(angleToRadian(rotate)) +
|
108
|
+
y: myFixed(
|
109
|
+
(point.x - center.x) * Math.sin(angleToRadian(rotate)) +
|
108
110
|
(point.y - center.y) * Math.cos(angleToRadian(rotate)) +
|
109
|
-
center.y
|
110
|
-
|
111
|
+
center.y,
|
112
|
+
1
|
111
113
|
)
|
112
114
|
}
|
113
115
|
}
|
@@ -190,10 +192,10 @@ export const setSvgActualInfo = (done_json: IDoneJson, resize?: boolean) => {
|
|
190
192
|
}
|
191
193
|
} else {
|
192
194
|
const BBox = (queryBbox as SVGGraphicsElement).getBBox()
|
193
|
-
x =
|
194
|
-
y =
|
195
|
-
width =
|
196
|
-
height =
|
195
|
+
x = myFixed(BBox.x, 0)
|
196
|
+
y = myFixed(BBox.y, 0)
|
197
|
+
width = myFixed(BBox.width, 0)
|
198
|
+
height = myFixed(BBox.height, 0)
|
197
199
|
}
|
198
200
|
if (
|
199
201
|
rectBBox &&
|
@@ -568,3 +570,19 @@ export const createLine = (e: MouseEvent, type?: ELineBindAnchors, itemInfo?: ID
|
|
568
570
|
new_position_y: 0
|
569
571
|
}
|
570
572
|
}
|
573
|
+
|
574
|
+
export const getZoomPosition = (e: Record<string, any>, scale: any, center: Record<string, any>, isAdd: boolean) => {
|
575
|
+
/*鼠标位置*/
|
576
|
+
const offsetX = e.layerX
|
577
|
+
const offsetY = e.layerY
|
578
|
+
/*上次的画布位置*/
|
579
|
+
const tx = center.x
|
580
|
+
const ty = center.y
|
581
|
+
/*上次的scale*/
|
582
|
+
const ts = myFixed(isAdd ? scale - 0.1 : scale + 0.1, 1)
|
583
|
+
/*画布在没有缩放的时候移动位置*/
|
584
|
+
const lx = myFixed(tx + (offsetX * (ts - 1)) / ts, 1)
|
585
|
+
const ly = myFixed(ty + (offsetY * (ts - 1)) / ts, 1)
|
586
|
+
center.x = myFixed(lx / scale - ((offsetX - lx) * (scale - 1)) / scale, 2)
|
587
|
+
center.y = myFixed(ly / scale - ((offsetY - ly) * (scale - 1)) / scale, 2)
|
588
|
+
}
|
package/src/views/Preview.vue
CHANGED
@@ -15,7 +15,7 @@
|
|
15
15
|
<template>
|
16
16
|
<div class="previewPage">
|
17
17
|
<svg-viewer :data="store.data" />
|
18
|
-
<el-button @click="back" class="backBtn" :icon="ArrowLeftBold">返回</el-button>
|
18
|
+
<el-button type="text" @click="back" class="backBtn" :icon="ArrowLeftBold">返回</el-button>
|
19
19
|
</div>
|
20
20
|
</template>
|
21
21
|
|