@zhangqingcq/vgce 0.0.24 → 0.0.26
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 +63 -63
- package/dist/style.css +1 -1
- package/dist/vgce.js +3588 -3494
- package/dist/vgce.umd.cjs +45 -45
- package/package.json +1 -1
- package/src/components/config/index.ts +5 -0
- package/src/components/svg-editor/center-panel/index.vue +56 -27
- package/src/components/svg-editor/connection-line/index.vue +1 -1
- package/src/components/svg-editor/connection-panel/index.vue +40 -5
- package/src/components/svg-editor/right-panel/index.vue +22 -2
- package/src/components/svg-editor/top-panel/index.vue +27 -3
- package/src/config/types.ts +1 -1
- package/src/stores/global/index.ts +4 -2
- package/src/utils/index.ts +30 -3
package/package.json
CHANGED
@@ -65,6 +65,11 @@ export const connection_line_system: ISystemStraightLine = {
|
|
65
65
|
type: EConfigItemPropsType.InputNumber,
|
66
66
|
val: 2
|
67
67
|
},
|
68
|
+
point_r: {
|
69
|
+
title: '节点半径',
|
70
|
+
type: EConfigItemPropsType.InputNumber,
|
71
|
+
val: 4
|
72
|
+
},
|
68
73
|
point_position: {
|
69
74
|
title: '点坐标',
|
70
75
|
type: EConfigItemPropsType.JsonEdit,
|
@@ -57,7 +57,8 @@
|
|
57
57
|
const ct: Record<string, any> = {
|
58
58
|
MoveCanvas: 'grab',
|
59
59
|
Rotate: "url('/src/assets/icons/rotate.svg'), auto",
|
60
|
-
Connection: 'crosshair'
|
60
|
+
Connection: 'crosshair',
|
61
|
+
SetConnectionLineNode: 'crosshair'
|
61
62
|
}
|
62
63
|
const cursor_style = computed(() => {
|
63
64
|
if (Object.keys(ct).indexOf(globalStore.intention) > -1) {
|
@@ -119,6 +120,7 @@
|
|
119
120
|
})
|
120
121
|
|
121
122
|
let groupMoved = false
|
123
|
+
let lineNodeMoved = false
|
122
124
|
|
123
125
|
const dropEvent = (e: Record<string, any>) => {
|
124
126
|
if (globalStore.intention == EGlobalStoreIntention.None) {
|
@@ -342,6 +344,7 @@
|
|
342
344
|
(globalStore.intention === EGlobalStoreIntention.Select || globalStore.intention === EGlobalStoreIntention.Move)
|
343
345
|
) {
|
344
346
|
//有选中组件 移动单个组件
|
347
|
+
//todo 对齐功能开发
|
345
348
|
globalStore.handle_svg_info.info.x = x
|
346
349
|
|
347
350
|
globalStore.handle_svg_info.info.y = y
|
@@ -559,8 +562,9 @@
|
|
559
562
|
const _y =
|
560
563
|
globalStore.mouse_info.new_position_y - globalStore.mouse_info.position_y - svgEditLayoutStore.center_offset.y
|
561
564
|
const brotherPoint = globalStore.handle_svg_info.info.props.point_position.val[l - 2]
|
562
|
-
|
563
|
-
let
|
565
|
+
const pr = globalStore.handle_svg_info?.info.props.point_r?.val + 2 || 4
|
566
|
+
let ox = brotherPoint.x < _x ? -pr : brotherPoint.x > _x ? pr : 0
|
567
|
+
let oy = brotherPoint.y < _y ? -pr : brotherPoint.y > _y ? pr : 0
|
564
568
|
if (e.ctrlKey) {
|
565
569
|
//画竖线
|
566
570
|
globalStore.handle_svg_info.info.props.point_position.val[l - 1] = {
|
@@ -580,17 +584,32 @@
|
|
580
584
|
}
|
581
585
|
}
|
582
586
|
} else if (globalStore.intention === EGlobalStoreIntention.SetConnectionLineNode && globalStore.handle_svg_info) {
|
587
|
+
if (
|
588
|
+
!lineNodeMoved &&
|
589
|
+
(globalStore.connection_line_node_info.point_index ===
|
590
|
+
globalStore.handle_svg_info.info.props.point_position.val.length - 1 ||
|
591
|
+
globalStore.connection_line_node_info.point_index === 0)
|
592
|
+
) {
|
593
|
+
lineNodeMoved = true
|
594
|
+
}
|
595
|
+
const l = globalStore.handle_svg_info?.info.props.point_position.val.length
|
596
|
+
const _x = getSvgNowPosition(
|
597
|
+
globalStore.mouse_info.position_x,
|
598
|
+
globalStore.mouse_info.new_position_x,
|
599
|
+
globalStore.connection_line_node_info.init_pos.x
|
600
|
+
)
|
601
|
+
const _y = getSvgNowPosition(
|
602
|
+
globalStore.mouse_info.position_y,
|
603
|
+
globalStore.mouse_info.new_position_y,
|
604
|
+
globalStore.connection_line_node_info.init_pos.y
|
605
|
+
)
|
606
|
+
const brotherPoint = globalStore.handle_svg_info.info.props.point_position.val[l - 2]
|
607
|
+
const pr = globalStore.handle_svg_info?.info.props.point_r?.val + 2 || 4
|
608
|
+
let ox = brotherPoint.x < _x ? -pr : brotherPoint.x > _x ? pr : 0
|
609
|
+
let oy = brotherPoint.y < _y ? -pr : brotherPoint.y > _y ? pr : 0
|
583
610
|
globalStore.handle_svg_info.info.props.point_position.val[globalStore.connection_line_node_info.point_index] = {
|
584
|
-
x:
|
585
|
-
|
586
|
-
globalStore.mouse_info.new_position_x,
|
587
|
-
globalStore.connection_line_node_info.init_pos.x
|
588
|
-
),
|
589
|
-
y: getSvgNowPosition(
|
590
|
-
globalStore.mouse_info.position_y,
|
591
|
-
globalStore.mouse_info.new_position_y,
|
592
|
-
globalStore.connection_line_node_info.init_pos.y
|
593
|
-
)
|
611
|
+
x: _x + ox,
|
612
|
+
y: _y + oy
|
594
613
|
}
|
595
614
|
}
|
596
615
|
}
|
@@ -631,6 +650,17 @@
|
|
631
650
|
globalStore.intention = EGlobalStoreIntention.None
|
632
651
|
} else if (globalStore.intention === EGlobalStoreIntention.Connection) {
|
633
652
|
return
|
653
|
+
} else if (globalStore.intention === EGlobalStoreIntention.SetConnectionLineNode) {
|
654
|
+
//解绑锚点
|
655
|
+
if (lineNodeMoved && globalStore.handle_svg_info?.info.bind_anchors) {
|
656
|
+
if (globalStore.connection_line_node_info.point_index === 0) {
|
657
|
+
globalStore.handle_svg_info.info.bind_anchors.start = null
|
658
|
+
} else {
|
659
|
+
globalStore.handle_svg_info.info.bind_anchors.end = null
|
660
|
+
}
|
661
|
+
}
|
662
|
+
globalStore.intention = EGlobalStoreIntention.None
|
663
|
+
lineNodeMoved = false
|
634
664
|
} else if (globalStore.intention === EGlobalStoreIntention.SelectArea) {
|
635
665
|
//框选
|
636
666
|
globalStore.setHandleSvgInfo(null)
|
@@ -654,7 +684,6 @@
|
|
654
684
|
contextMenuStore.display = false
|
655
685
|
}
|
656
686
|
const onCanvasMouseDown = (e: MouseEvent) => {
|
657
|
-
//todo 画横线或垂线
|
658
687
|
const { clientX, clientY } = e
|
659
688
|
if (globalStore.intention === EGlobalStoreIntention.Connection) {
|
660
689
|
if (!globalStore.handle_svg_info) {
|
@@ -1089,20 +1118,20 @@
|
|
1089
1118
|
/>
|
1090
1119
|
</g>
|
1091
1120
|
</svg>
|
1092
|
-
<!-- 右键菜单 -->
|
1093
|
-
<ul ref="contextMenuRef" class="contextMenu" v-show="contextMenuStore.display">
|
1094
|
-
<li
|
1095
|
-
v-for="(item, key) in contextMenuStore.info"
|
1096
|
-
:key="item.title"
|
1097
|
-
@click="contextMenuStore.onContextMenuClick(key)"
|
1098
|
-
>
|
1099
|
-
<p :class="item.enable ? '' : 'disabled'">
|
1100
|
-
{{ item.title }}
|
1101
|
-
<span class="shortcut">{{ item.hot_key }}</span>
|
1102
|
-
</p>
|
1103
|
-
</li>
|
1104
|
-
</ul>
|
1105
1121
|
</div>
|
1122
|
+
<!-- 右键菜单 -->
|
1123
|
+
<ul ref="contextMenuRef" class="contextMenu" v-show="contextMenuStore.display">
|
1124
|
+
<li
|
1125
|
+
v-for="(item, key) in contextMenuStore.info"
|
1126
|
+
:key="item.title"
|
1127
|
+
@click="contextMenuStore.onContextMenuClick(key)"
|
1128
|
+
>
|
1129
|
+
<p :class="item.enable ? '' : 'disabled'">
|
1130
|
+
{{ item.title }}
|
1131
|
+
<span class="shortcut">{{ item.hot_key }}</span>
|
1132
|
+
</p>
|
1133
|
+
</li>
|
1134
|
+
</ul>
|
1106
1135
|
</template>
|
1107
1136
|
|
1108
1137
|
<style lang="less" scoped>
|
@@ -73,11 +73,40 @@
|
|
73
73
|
getCoordinateOffset(props.itemInfo.actual_bound.height, props.itemInfo.scale_y) +
|
74
74
|
radius.value
|
75
75
|
)
|
76
|
+
|
77
|
+
const anchorUp = (e: any, type: ELineBindAnchors) => {
|
78
|
+
if (globalStore.intention === EGlobalStoreIntention.SetConnectionLineNode) {
|
79
|
+
//移动连线首尾节点,绑定锚点
|
80
|
+
e.stopPropagation()
|
81
|
+
if (globalStore.handle_svg_info?.info.bind_anchors && globalStore.connection_line_node_info) {
|
82
|
+
if (globalStore.connection_line_node_info.point_index === 0) {
|
83
|
+
globalStore.handle_svg_info.info.bind_anchors.start = {
|
84
|
+
type: type,
|
85
|
+
target_id: props.itemInfo.id
|
86
|
+
}
|
87
|
+
} else if (
|
88
|
+
globalStore.connection_line_node_info.point_index ===
|
89
|
+
globalStore.handle_svg_info.info.props.point_position.val.length - 1
|
90
|
+
) {
|
91
|
+
globalStore.handle_svg_info.info.bind_anchors.end = {
|
92
|
+
type: type,
|
93
|
+
target_id: props.itemInfo.id
|
94
|
+
}
|
95
|
+
}
|
96
|
+
|
97
|
+
globalStore.intention = EGlobalStoreIntention.None
|
98
|
+
globalStore.setHandleSvgInfo(null)
|
99
|
+
nextTick(function () {
|
100
|
+
moveAnchors(props.itemInfo)
|
101
|
+
})
|
102
|
+
}
|
103
|
+
}
|
104
|
+
}
|
76
105
|
const bindAnchor = (e: any, type: ELineBindAnchors) => {
|
77
106
|
if (globalStore.intention === EGlobalStoreIntention.None) {
|
78
107
|
createLine(e, type, props.itemInfo)
|
79
108
|
} else if (globalStore.intention === EGlobalStoreIntention.Connection) {
|
80
|
-
|
109
|
+
//在连线的情况下,点击锚点,结束连线并绑定锚点
|
81
110
|
e.stopPropagation()
|
82
111
|
if (globalStore.handle_svg_info?.info.bind_anchors) {
|
83
112
|
globalStore.handle_svg_info.info.bind_anchors.end = {
|
@@ -102,19 +131,25 @@
|
|
102
131
|
stroke-width="2"
|
103
132
|
stroke="rgba(0,0,0,0)"
|
104
133
|
>
|
105
|
-
<g
|
134
|
+
<g
|
135
|
+
@mousedown="bindAnchor($event, ELineBindAnchors.TopCenter)"
|
136
|
+
@mouseup="anchorUp($event, ELineBindAnchors.TopCenter)"
|
137
|
+
>
|
106
138
|
<circle class="out-circle" :cx="cxT" :cy="cyT" :r="outRadius" fill-opacity=".3" />
|
107
139
|
<circle id="connection_tc" :cx="cxT" :cy="cyT" :r="radius" pointer-events="all" />
|
108
140
|
</g>
|
109
|
-
<g @mousedown="bindAnchor($event, ELineBindAnchors.Right)">
|
141
|
+
<g @mousedown="bindAnchor($event, ELineBindAnchors.Right)" @mouseup="anchorUp($event, ELineBindAnchors.Right)">
|
110
142
|
<circle class="out-circle" :cx="cxR" :cy="cyR" :r="outRadius" fill-opacity=".3" />
|
111
143
|
<circle id="connection_r" :cx="cxR" :cy="cyR" :r="radius" pointer-events="all" />
|
112
144
|
</g>
|
113
|
-
<g
|
145
|
+
<g
|
146
|
+
@mousedown="bindAnchor($event, ELineBindAnchors.BottomCenter)"
|
147
|
+
@mouseup="anchorUp($event, ELineBindAnchors.BottomCenter)"
|
148
|
+
>
|
114
149
|
<circle class="out-circle" :cx="cxB" :cy="cyB" :r="outRadius" fill-opacity=".3" />
|
115
150
|
<circle id="connection_bc" :cx="cxB" :cy="cyB" :r="radius" pointer-events="all" />
|
116
151
|
</g>
|
117
|
-
<g @mousedown="bindAnchor($event, ELineBindAnchors.Left)">
|
152
|
+
<g @mousedown="bindAnchor($event, ELineBindAnchors.Left)" @mouseup="anchorUp($event, ELineBindAnchors.Left)">
|
118
153
|
<circle class="out-circle" :cx="cxL" :cy="cyL" :r="outRadius" fill-opacity=".3" />
|
119
154
|
<circle id="connection_l" :cx="cxL" :cy="cyL" :r="radius" :style="{ cursor: 'crosshair' }" pointer-events="all" />
|
120
155
|
</g>
|
@@ -219,11 +219,11 @@
|
|
219
219
|
<el-input v-model="globalStore.handle_svg_info!.info.id" />
|
220
220
|
</el-form-item>
|
221
221
|
<div
|
222
|
-
v-for="(e, k)
|
222
|
+
v-for="(e, k) of globalStore.handle_svg_info!.info.state"
|
223
223
|
:key="'state' + String(k)"
|
224
224
|
v-if="globalStore.handle_svg_info!.info.state"
|
225
225
|
>
|
226
|
-
<el-form-item class="props-row" :label="String(k)" size="small"> {{ e
|
226
|
+
<el-form-item class="props-row" :label="String(k)" size="small"> {{ e!.default }}</el-form-item>
|
227
227
|
|
228
228
|
<el-form-item
|
229
229
|
v-if="k === 'OnOff'"
|
@@ -243,6 +243,26 @@
|
|
243
243
|
</el-form-item>
|
244
244
|
</div>
|
245
245
|
<dynamic-el-form-item :obj-info="globalStore.handle_svg_info!.info.props" code />
|
246
|
+
<el-form-item
|
247
|
+
:label="globalStore.handle_svg_info!.info.animations.type.title"
|
248
|
+
size="small"
|
249
|
+
v-if="globalStore.handle_svg_info!.info.animations"
|
250
|
+
>
|
251
|
+
<el-select v-model="globalStore.handle_svg_info!.info.animations.type.val" placeholder="Select" size="small">
|
252
|
+
<el-option
|
253
|
+
v-for="item in globalStore.handle_svg_info!.info.animations.type.options"
|
254
|
+
:key="item.value"
|
255
|
+
:label="item.label"
|
256
|
+
:value="item.value"
|
257
|
+
/>
|
258
|
+
</el-select>
|
259
|
+
</el-form-item>
|
260
|
+
|
261
|
+
<dynamic-el-form-item
|
262
|
+
:obj-info="globalStore.handle_svg_info!.info.animations"
|
263
|
+
v-if="globalStore.handle_svg_info!.info.animations?.type.val !== 'None'"
|
264
|
+
:hide="['type', 'repeatCount']"
|
265
|
+
/>
|
246
266
|
<bind-anchor
|
247
267
|
v-if="globalStore.handle_svg_info?.info.type === EDoneJsonType.ConnectionLine"
|
248
268
|
v-model="globalStore.handle_svg_info!.info!.bind_anchors!.start"
|
@@ -173,12 +173,30 @@
|
|
173
173
|
</div>
|
174
174
|
<div class="el-divider el-divider--horizontal" role="separator" style="--el-border-style: solid"></div>
|
175
175
|
<div class="font-bold mb-10px text-15px guide-title">横线和竖线</div>
|
176
|
-
<div
|
176
|
+
<div class="guide-text"
|
177
|
+
><p>
|
178
|
+
点击编辑器顶部连线按钮会进入连线状态,该状态下在画板点击鼠标左键即可开始画线,移动并再次点击左键创建新的节点,右键结束画线并退出连线状态;</p
|
179
|
+
>
|
180
|
+
<p>画线的时候按住ctrl即可画竖线,按住shift即可画横线</p></div
|
181
|
+
>
|
182
|
+
<div class="el-divider el-divider--horizontal" role="separator" style="--el-border-style: solid"></div>
|
183
|
+
<div class="font-bold mb-10px text-15px guide-title">绑定锚点</div>
|
184
|
+
<div class="guide-text">
|
185
|
+
<p
|
186
|
+
>组件在未选中时,鼠标经过组件时会出现锚点,鼠标悬浮在锚点上时,会有交互样式,点击左键即可以锚点为起点创建连线;</p
|
187
|
+
>
|
188
|
+
<p>同样,在连线时鼠标经过锚点时,会出现锚点交互样式,点击左键即可以锚点为连线终点结束连线;</p>
|
189
|
+
<p>这两种情况下的连线会绑定组件上的锚点,如需解绑,参考下面的‘锚点解绑’;</p>
|
190
|
+
<p>同样,也可先画线,再选中连线绑定想要绑定的组件锚点(连线只有首尾节点可以绑定锚点)</p>
|
191
|
+
</div>
|
177
192
|
<div class="el-divider el-divider--horizontal" role="separator" style="--el-border-style: solid"></div>
|
178
193
|
<div class="font-bold mb-10px text-15px guide-title">线段选中</div>
|
179
|
-
<div
|
180
|
-
|
194
|
+
<div>
|
195
|
+
若线段绑定了锚点,移动线段,绑定的锚点不会移动。若是想将线段整体移动,需要先解绑,参考下面的‘锚点解绑’
|
181
196
|
</div>
|
197
|
+
<div class="el-divider el-divider--horizontal" role="separator" style="--el-border-style: solid"></div>
|
198
|
+
<div class="font-bold mb-10px text-15px guide-title">锚点解绑</div>
|
199
|
+
<div style="padding-bottom: 14px"> 选中线段,在右侧‘数据’栏里解除绑定;或者鼠标左键拖拽连线上需要解绑的节点</div>
|
182
200
|
</el-scrollbar>
|
183
201
|
</el-dialog>
|
184
202
|
</template>
|
@@ -197,6 +215,12 @@
|
|
197
215
|
.el-divider {
|
198
216
|
border-color: #f1f1f5;
|
199
217
|
}
|
218
|
+
|
219
|
+
.guide-text {
|
220
|
+
p {
|
221
|
+
line-height: 1.9;
|
222
|
+
}
|
223
|
+
}
|
200
224
|
</style>
|
201
225
|
<style lang="less">
|
202
226
|
.guide-dialog {
|
package/src/config/types.ts
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
import { config } from '@/config'
|
2
2
|
import type { IConfigItem } from '@/config/types'
|
3
|
-
import { isOfType, objectDeepClone, setSvgActualInfo } from '@/utils'
|
3
|
+
import { isOfType, objectDeepClone, setSvgActualInfo, unbindAnchors } from '@/utils'
|
4
4
|
import { EGlobalStoreIntention, EMouseInfoState, EScaleInfoType } from './types'
|
5
5
|
import type { IDoneJson, IGlobalStore, IMouseInfo, IScaleInfo } from './types'
|
6
6
|
import { useHistoryRecord } from '@/hooks'
|
@@ -90,7 +90,9 @@ export const useGlobalStore = defineStore('global-store', {
|
|
90
90
|
},
|
91
91
|
spliceDoneJson(index: number) {
|
92
92
|
const globalStore = useGlobalStore()
|
93
|
-
globalStore.done_json.splice(index, 1)
|
93
|
+
const t = globalStore.done_json.splice(index, 1)
|
94
|
+
const item = t[0]
|
95
|
+
unbindAnchors(item.id)
|
94
96
|
useHistoryRecord(globalStore.done_json)
|
95
97
|
}
|
96
98
|
}
|
package/src/utils/index.ts
CHANGED
@@ -286,15 +286,39 @@ export const moveAnchors = (done_json: IDoneJson) => {
|
|
286
286
|
if (d.type === EDoneJsonType.ConnectionLine) {
|
287
287
|
if (d.bind_anchors?.start?.target_id === done_json.id) {
|
288
288
|
const a = getAnchorPosByAnchorType(d.bind_anchors.start.type, done_json)
|
289
|
-
d.props.point_position.val[0] = {
|
289
|
+
d.props.point_position.val[0] = {
|
290
|
+
x: a.x - d.x,
|
291
|
+
y: a.y - d.y
|
292
|
+
}
|
290
293
|
}
|
291
294
|
if (d.bind_anchors?.end?.target_id === done_json.id) {
|
292
295
|
const a = getAnchorPosByAnchorType(d.bind_anchors.end.type, done_json)
|
293
|
-
d.props.point_position.val[d.props.point_position.val.length - 1] = {
|
296
|
+
d.props.point_position.val[d.props.point_position.val.length - 1] = {
|
297
|
+
x: a.x - d.x,
|
298
|
+
y: a.y - d.y
|
299
|
+
}
|
294
300
|
}
|
295
301
|
}
|
296
302
|
}
|
297
303
|
}
|
304
|
+
/**
|
305
|
+
* 解绑连线的锚点
|
306
|
+
* @param id 被绑定的组件的id
|
307
|
+
*/
|
308
|
+
export const unbindAnchors = (id: string) => {
|
309
|
+
const globalStore = useGlobalStore(pinia)
|
310
|
+
for (let d of globalStore.done_json) {
|
311
|
+
if (d.type === EDoneJsonType.ConnectionLine) {
|
312
|
+
if (d.bind_anchors?.start?.target_id === id) {
|
313
|
+
d.bind_anchors.start = null
|
314
|
+
}
|
315
|
+
if (d.bind_anchors?.end?.target_id === id) {
|
316
|
+
d.bind_anchors.end = null
|
317
|
+
}
|
318
|
+
}
|
319
|
+
}
|
320
|
+
}
|
321
|
+
|
298
322
|
/**
|
299
323
|
* 根据锚点类型获取锚点坐标
|
300
324
|
* @param anchor_type
|
@@ -464,7 +488,10 @@ export const createLine = (e: MouseEvent, type?: ELineBindAnchors, itemInfo?: ID
|
|
464
488
|
width: 0,
|
465
489
|
height: 0
|
466
490
|
},
|
467
|
-
center_position: {
|
491
|
+
center_position: {
|
492
|
+
x: 0,
|
493
|
+
y: 0
|
494
|
+
},
|
468
495
|
point_coordinate: {
|
469
496
|
tl: {
|
470
497
|
x: 0,
|