@zhangqingcq/vgce 0.0.22 → 0.0.24
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/style.css +1 -1
- package/dist/vgce.js +8980 -8965
- package/dist/vgce.umd.cjs +61 -61
- package/package.json +1 -1
- package/src/assets/icons/add.svg +1 -1
- package/src/components/svg-editor/index.vue +18 -3
- package/src/components/svg-editor/right-panel/list.vue +85 -85
- package/src/components/svg-editor/top-panel/index.vue +15 -23
- package/src/components/svg-viewer/index.vue +14 -1
- package/src/router.ts +0 -5
- package/src/views/EditorS.vue +8 -4
- package/src/views/Preview.vue +38 -12
package/package.json
CHANGED
package/src/assets/icons/add.svg
CHANGED
@@ -1 +1 @@
|
|
1
|
-
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1686279304877" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="12132" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32"><path d="M512 128c211.2 0 384 172.8 384 384s-172.8 384-384 384-384-172.8-384-384 172.8-384 384-384m0-64C262.4 64 64 262.4 64 512s198.4 448 448 448 448-198.4 448-448-198.4-448-448-448z" p-id="12133"></path><path d="M320 512m-32 0a32 32 0 1 0 64 0 32 32 0 1 0-64 0Z" p-id="12134"></path><path d="M704 512m-32 0a32 32 0 1 0 64 0 32 32 0 1 0-64 0Z" p-id="12135"></path><path d="M512 320m-32 0a32 32 0 1 0 64 0 32 32 0 1 0-64 0Z" p-id="12136"></path><path d="M512 704m-32 0a32 32 0 1 0 64 0 32 32 0 1 0-64 0Z" p-id="12137"></path><path d="M320 480h384v64H320z" p-id="12138"></path><path d="M480 320h64v384h-64z" p-id="12139"></path></svg>
|
1
|
+
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1686279304877" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="12132" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32"><path class="icon-out" d="M512 128c211.2 0 384 172.8 384 384s-172.8 384-384 384-384-172.8-384-384 172.8-384 384-384m0-64C262.4 64 64 262.4 64 512s198.4 448 448 448 448-198.4 448-448-198.4-448-448-448z" p-id="12133"></path><path class="icon-in" d="M320 512m-32 0a32 32 0 1 0 64 0 32 32 0 1 0-64 0Z" p-id="12134"></path><path class="icon-in" d="M704 512m-32 0a32 32 0 1 0 64 0 32 32 0 1 0-64 0Z" p-id="12135"></path><path class="icon-in" d="M512 320m-32 0a32 32 0 1 0 64 0 32 32 0 1 0-64 0Z" p-id="12136"></path><path class="icon-in" d="M512 704m-32 0a32 32 0 1 0 64 0 32 32 0 1 0-64 0Z" p-id="12137"></path><path class="icon-in" d="M320 480h384v64H320z" p-id="12138"></path><path class="icon-in" d="M480 320h64v384h-64z" p-id="12139"></path></svg>
|
@@ -72,7 +72,7 @@
|
|
72
72
|
globalStore.setDoneJson(done_json)
|
73
73
|
}
|
74
74
|
onMounted(() => {
|
75
|
-
|
75
|
+
//清除历史记录,解决外部传入不同数据,形成历史记录的问题
|
76
76
|
editPrivateStore.history_doneComponent = []
|
77
77
|
editPrivateStore.history_now_index = 0
|
78
78
|
if (props.data) {
|
@@ -85,9 +85,24 @@
|
|
85
85
|
|
86
86
|
const { appContext } = getCurrentInstance()!
|
87
87
|
|
88
|
+
function onReturnClick(d: IDataModel) {
|
89
|
+
emits('onReturn', {
|
90
|
+
data: d,
|
91
|
+
isChange: editPrivateStore.getTopBtnUndoStatus
|
92
|
+
})
|
93
|
+
}
|
94
|
+
|
88
95
|
function save(d: IDataModel) {
|
89
96
|
if (props.saveFile) {
|
90
|
-
ElMessageBox.prompt(
|
97
|
+
ElMessageBox.prompt(
|
98
|
+
'请输入文件名',
|
99
|
+
'保存',
|
100
|
+
{
|
101
|
+
cancelButtonText: '取消',
|
102
|
+
confirmButtonText: '保存'
|
103
|
+
},
|
104
|
+
appContext
|
105
|
+
)
|
91
106
|
.then((r: any) => {
|
92
107
|
fileWrite(d, r.value.trim())
|
93
108
|
emits('onSave', d)
|
@@ -110,7 +125,7 @@
|
|
110
125
|
<el-header class="top-el-header">
|
111
126
|
<top-panel
|
112
127
|
@change-visible="changeVisible"
|
113
|
-
@on-return="
|
128
|
+
@on-return="onReturnClick"
|
114
129
|
@on-preview="(val: IDataModel) => emits('onPreview', val)"
|
115
130
|
@on-save="save"
|
116
131
|
></top-panel>
|
@@ -1,85 +1,85 @@
|
|
1
|
-
<script setup lang="ts">
|
2
|
-
import type { IAttrItem } from '@/config/types'
|
3
|
-
import { ElIcon, ElInput } from 'element-plus'
|
4
|
-
import SvgAnalysis from '@/components/svg-analysis/index.vue'
|
5
|
-
|
6
|
-
const props = withDefaults(defineProps<{ modelValue: IAttrItem[] }>(), {
|
7
|
-
modelValue: () => [
|
8
|
-
{
|
9
|
-
key: '',
|
10
|
-
val: ''
|
11
|
-
}
|
12
|
-
]
|
13
|
-
})
|
14
|
-
const emit = defineEmits(['update:modelValue'])
|
15
|
-
|
16
|
-
const value = computed({
|
17
|
-
get() {
|
18
|
-
return props.modelValue
|
19
|
-
},
|
20
|
-
set(val) {
|
21
|
-
emit('update:modelValue', val)
|
22
|
-
}
|
23
|
-
})
|
24
|
-
|
25
|
-
const addL = () => {
|
26
|
-
value.value.push({
|
27
|
-
key: '',
|
28
|
-
val: ''
|
29
|
-
})
|
30
|
-
}
|
31
|
-
|
32
|
-
const deleteL = (i: number) => {
|
33
|
-
value.value.splice(i, 1)
|
34
|
-
}
|
35
|
-
</script>
|
36
|
-
|
37
|
-
<template>
|
38
|
-
<div class="wall-l">
|
39
|
-
<div class="head-l">
|
40
|
-
<span>key</span>
|
41
|
-
<span>value</span>
|
42
|
-
|
43
|
-
<el-icon :size="16" class="bt-Icon" @click="addL">
|
44
|
-
<svg-analysis name="add" />
|
45
|
-
</el-icon>
|
46
|
-
</div>
|
47
|
-
<div class="row-l" v-for="(item, i) of value">
|
48
|
-
<el-input class="content-l" v-model="item.key" size="small" placeholder="key" />
|
49
|
-
<el-input class="content-l" v-model="item.val" size="small" placeholder="value" />
|
50
|
-
|
51
|
-
<el-icon :size="16" class="bt-Icon" @click="deleteL(i)">
|
52
|
-
<svg-analysis name="delete" />
|
53
|
-
</el-icon>
|
54
|
-
</div>
|
55
|
-
</div>
|
56
|
-
</template>
|
57
|
-
|
58
|
-
<style lang="less" scoped>
|
59
|
-
.wall-l {
|
60
|
-
background-color: #
|
61
|
-
padding: 4px 5px 2px 5px;
|
62
|
-
border-radius: 4px;
|
63
|
-
.head-l {
|
64
|
-
display: flex;
|
65
|
-
align-items: center;
|
66
|
-
|
67
|
-
span {
|
68
|
-
display: inline-block;
|
69
|
-
width: 42%;
|
70
|
-
margin-right: 10px;
|
71
|
-
color: #666;
|
72
|
-
}
|
73
|
-
}
|
74
|
-
|
75
|
-
.row-l {
|
76
|
-
display: flex;
|
77
|
-
align-items: center;
|
78
|
-
padding-bottom: 6px;
|
79
|
-
.content-l {
|
80
|
-
width: 42%;
|
81
|
-
margin-right: 10px;
|
82
|
-
}
|
83
|
-
}
|
84
|
-
}
|
85
|
-
</style>
|
1
|
+
<script setup lang="ts">
|
2
|
+
import type { IAttrItem } from '@/config/types'
|
3
|
+
import { ElIcon, ElInput } from 'element-plus'
|
4
|
+
import SvgAnalysis from '@/components/svg-analysis/index.vue'
|
5
|
+
|
6
|
+
const props = withDefaults(defineProps<{ modelValue: IAttrItem[] }>(), {
|
7
|
+
modelValue: () => [
|
8
|
+
{
|
9
|
+
key: '',
|
10
|
+
val: ''
|
11
|
+
}
|
12
|
+
]
|
13
|
+
})
|
14
|
+
const emit = defineEmits(['update:modelValue'])
|
15
|
+
|
16
|
+
const value = computed({
|
17
|
+
get() {
|
18
|
+
return props.modelValue
|
19
|
+
},
|
20
|
+
set(val) {
|
21
|
+
emit('update:modelValue', val)
|
22
|
+
}
|
23
|
+
})
|
24
|
+
|
25
|
+
const addL = () => {
|
26
|
+
value.value.push({
|
27
|
+
key: '',
|
28
|
+
val: ''
|
29
|
+
})
|
30
|
+
}
|
31
|
+
|
32
|
+
const deleteL = (i: number) => {
|
33
|
+
value.value.splice(i, 1)
|
34
|
+
}
|
35
|
+
</script>
|
36
|
+
|
37
|
+
<template>
|
38
|
+
<div class="wall-l">
|
39
|
+
<div class="head-l">
|
40
|
+
<span>key</span>
|
41
|
+
<span>value</span>
|
42
|
+
|
43
|
+
<el-icon :size="16" class="bt-Icon" @click="addL">
|
44
|
+
<svg-analysis name="add" />
|
45
|
+
</el-icon>
|
46
|
+
</div>
|
47
|
+
<div class="row-l" v-for="(item, i) of value">
|
48
|
+
<el-input class="content-l" v-model="item.key" size="small" placeholder="key" />
|
49
|
+
<el-input class="content-l" v-model="item.val" size="small" placeholder="value" />
|
50
|
+
|
51
|
+
<el-icon :size="16" class="bt-Icon" @click="deleteL(i)">
|
52
|
+
<svg-analysis name="delete" />
|
53
|
+
</el-icon>
|
54
|
+
</div>
|
55
|
+
</div>
|
56
|
+
</template>
|
57
|
+
|
58
|
+
<style lang="less" scoped>
|
59
|
+
.wall-l {
|
60
|
+
background-color: #f5f8fb;
|
61
|
+
padding: 4px 5px 2px 5px;
|
62
|
+
border-radius: 4px;
|
63
|
+
.head-l {
|
64
|
+
display: flex;
|
65
|
+
align-items: center;
|
66
|
+
|
67
|
+
span {
|
68
|
+
display: inline-block;
|
69
|
+
width: 42%;
|
70
|
+
margin-right: 10px;
|
71
|
+
color: #666;
|
72
|
+
}
|
73
|
+
}
|
74
|
+
|
75
|
+
.row-l {
|
76
|
+
display: flex;
|
77
|
+
align-items: center;
|
78
|
+
padding-bottom: 6px;
|
79
|
+
.content-l {
|
80
|
+
width: 42%;
|
81
|
+
margin-right: 10px;
|
82
|
+
}
|
83
|
+
}
|
84
|
+
}
|
85
|
+
</style>
|
@@ -9,8 +9,6 @@
|
|
9
9
|
import { EVisibleConfKey } from '../types'
|
10
10
|
import type { IDataModel } from '../types'
|
11
11
|
import { EGlobalStoreIntention } from '@/stores/global/types'
|
12
|
-
import { VAceEditor } from 'vue3-ace-editor'
|
13
|
-
import LeftPanel from '@/components/svg-editor/left-panel/index.vue'
|
14
12
|
|
15
13
|
const svgEditLayoutStore = useSvgEditLayoutStore(pinia)
|
16
14
|
const globalStore = useGlobalStore(pinia)
|
@@ -21,21 +19,14 @@
|
|
21
19
|
globalStore.done_json.length <= 0 || globalStore.setDoneJson([])
|
22
20
|
globalStore.intention = EGlobalStoreIntention.None
|
23
21
|
}
|
24
|
-
|
25
|
-
|
26
|
-
layout_center: svgEditLayoutStore.center_offset,
|
27
|
-
config: configStore.$state,
|
28
|
-
done_json: globalStore.done_json
|
29
|
-
}
|
30
|
-
emits('onPreview', data_model)
|
31
|
-
}
|
32
|
-
const onSaveClick = () => {
|
22
|
+
|
23
|
+
const dataBtnClick = (d: 'onReturn' | 'onPreview' | 'onSave') => {
|
33
24
|
const data_model: IDataModel = {
|
34
25
|
layout_center: svgEditLayoutStore.center_offset,
|
35
26
|
config: configStore.$state,
|
36
27
|
done_json: globalStore.done_json
|
37
28
|
}
|
38
|
-
emits(
|
29
|
+
emits(d, data_model)
|
39
30
|
}
|
40
31
|
|
41
32
|
const open = ref(false)
|
@@ -137,15 +128,15 @@
|
|
137
128
|
</el-icon> -->
|
138
129
|
</div>
|
139
130
|
<div class="flex items-center mr-20px">
|
140
|
-
<el-icon title="返回" class="bt-Icon" :size="24" @click="
|
131
|
+
<el-icon title="返回" class="bt-Icon" :size="24" @click="dataBtnClick('onReturn')">
|
141
132
|
<svg-analysis name="return" />
|
142
133
|
</el-icon>
|
143
134
|
<el-divider direction="vertical"></el-divider>
|
144
|
-
<el-icon title="保存" class="bt-Icon" :size="24" @click="
|
135
|
+
<el-icon title="保存" class="bt-Icon" :size="24" @click="dataBtnClick('onSave')">
|
145
136
|
<svg-analysis name="save" />
|
146
137
|
</el-icon>
|
147
138
|
<el-divider direction="vertical"></el-divider>
|
148
|
-
<el-icon title="预览" class="bt-Icon" :size="22" @click="
|
139
|
+
<el-icon title="预览" class="bt-Icon" :size="22" @click="dataBtnClick('onPreview')">
|
149
140
|
<svg-analysis name="preview" />
|
150
141
|
</el-icon>
|
151
142
|
</div>
|
@@ -166,24 +157,24 @@
|
|
166
157
|
<el-scrollbar max-height="60vh">
|
167
158
|
<div class="font-bold mb-10px text-15px guide-title" style="padding-top: 16px">多选</div>
|
168
159
|
<div>鼠标按住左键可以框选,也可以按住ctrl+鼠标左键点图形进行多选</div>
|
169
|
-
<div class="el-divider el-divider--horizontal" role="separator" style="--el-border-style: solid"
|
160
|
+
<div class="el-divider el-divider--horizontal" role="separator" style="--el-border-style: solid"></div>
|
170
161
|
<div class="font-bold mb-10px text-15px guide-title">拖动画布</div>
|
171
162
|
<div>右键画布然后拖动即可,右侧面板‘图纸’栏可微调或重置位置</div>
|
172
|
-
<div class="el-divider el-divider--horizontal" role="separator" style="--el-border-style: solid"
|
163
|
+
<div class="el-divider el-divider--horizontal" role="separator" style="--el-border-style: solid"></div>
|
173
164
|
<div class="font-bold mb-10px text-15px guide-title">画布缩放</div>
|
174
165
|
<div>使用鼠标滚轮或者右侧面板‘图纸’栏可控制画布缩放</div>
|
175
|
-
<div class="el-divider el-divider--horizontal" role="separator" style="--el-border-style: solid"
|
166
|
+
<div class="el-divider el-divider--horizontal" role="separator" style="--el-border-style: solid"></div>
|
176
167
|
<div class="font-bold mb-10px text-15px guide-title">标尺辅助线</div>
|
177
168
|
<div>在标尺区域按住鼠标左键并拖动即可创建标尺辅助线,将标尺辅助线拖动到标尺区域即可删除标尺辅助线</div>
|
178
|
-
<div class="el-divider el-divider--horizontal" role="separator" style="--el-border-style: solid"
|
169
|
+
<div class="el-divider el-divider--horizontal" role="separator" style="--el-border-style: solid"></div>
|
179
170
|
<div class="font-bold mb-10px text-15px guide-title">连线样式</div>
|
180
171
|
<div
|
181
|
-
|
182
|
-
>
|
183
|
-
<div class="el-divider el-divider--horizontal" role="separator" style="--el-border-style: solid"
|
172
|
+
>在右侧‘连线’栏可以统一配置连线样式,配置后先增加的线会应用新样式,之前的线样式不变,如需改变,可选中线手动更改或删除重画
|
173
|
+
</div>
|
174
|
+
<div class="el-divider el-divider--horizontal" role="separator" style="--el-border-style: solid"></div>
|
184
175
|
<div class="font-bold mb-10px text-15px guide-title">横线和竖线</div>
|
185
176
|
<div>画线的时候按住ctrl即可画竖线,按住shift即可画横线</div>
|
186
|
-
<div class="el-divider el-divider--horizontal" role="separator" style="--el-border-style: solid"
|
177
|
+
<div class="el-divider el-divider--horizontal" role="separator" style="--el-border-style: solid"></div>
|
187
178
|
<div class="font-bold mb-10px text-15px guide-title">线段选中</div>
|
188
179
|
<div style="padding-bottom: 14px">
|
189
180
|
若线段绑定了锚点,移动线段,绑定的锚点不会移动。若是想将线段整体移动,需要先选中线段,在右侧‘数据’栏里解除绑定
|
@@ -214,6 +205,7 @@
|
|
214
205
|
margin-right: 0;
|
215
206
|
padding-right: 16px;
|
216
207
|
}
|
208
|
+
|
217
209
|
.el-dialog__body {
|
218
210
|
padding-top: 0;
|
219
211
|
padding-bottom: 8px;
|
@@ -62,7 +62,6 @@
|
|
62
62
|
return
|
63
63
|
}
|
64
64
|
if (!props.canvasDrag) {
|
65
|
-
console.log(props.canvasDrag)
|
66
65
|
return
|
67
66
|
}
|
68
67
|
const { clientX, clientY } = e
|
@@ -139,6 +138,19 @@
|
|
139
138
|
const setNodeAttrByID = (id: string, attr: string, val: any) => {
|
140
139
|
return setArrItemByID(id, attr, val, preview_data.done_json)
|
141
140
|
}
|
141
|
+
|
142
|
+
const getStyle = (root: IDoneJson) => {
|
143
|
+
let t = false
|
144
|
+
if (root.events?.length > 0) {
|
145
|
+
for (let e of root.events) {
|
146
|
+
if (e.type === EEventType.Click) {
|
147
|
+
t = true
|
148
|
+
break
|
149
|
+
}
|
150
|
+
}
|
151
|
+
}
|
152
|
+
return { cursor: t ? 'pointer' : 'default' }
|
153
|
+
}
|
142
154
|
const eventHandle = (root: IDoneJson) => {
|
143
155
|
if (root.events?.length > 0) {
|
144
156
|
for (let e of root.events) {
|
@@ -263,6 +275,7 @@
|
|
263
275
|
:key="item.id"
|
264
276
|
:transform="`translate(${item.x},${item.y})rotate(0)scale(1)`"
|
265
277
|
v-show="item.display"
|
278
|
+
:style="getStyle(item)"
|
266
279
|
@click="eventHandle(item)"
|
267
280
|
>
|
268
281
|
<g :class="`${getCommonClass(item)}`">
|
package/src/router.ts
CHANGED
package/src/views/EditorS.vue
CHANGED
@@ -2,16 +2,20 @@
|
|
2
2
|
import SvgEditor from '@/components/svg-editor/index.vue'
|
3
3
|
import { useStore } from '@/stores/main'
|
4
4
|
import type { IDataModel } from '@/components/svg-editor/types'
|
5
|
+
import Preview from './Preview.vue'
|
5
6
|
|
6
|
-
const router = useRouter()
|
7
7
|
const store = useStore()
|
8
8
|
|
9
|
-
|
9
|
+
const previewShow = ref(false)
|
10
|
+
function previewHandle(d: IDataModel) {
|
10
11
|
store.data = d
|
11
|
-
|
12
|
+
nextTick(function () {
|
13
|
+
previewShow.value = true
|
14
|
+
})
|
12
15
|
}
|
13
16
|
</script>
|
14
17
|
|
15
18
|
<template>
|
16
|
-
<SvgEditor :data="(store.data && JSON.stringify(store.data)) || ''" @onPreview="
|
19
|
+
<SvgEditor :data="(store.data && JSON.stringify(store.data)) || ''" @onPreview="previewHandle" saveFile />
|
20
|
+
<Preview v-if="previewShow" @back="previewShow = false" />
|
17
21
|
</template>
|
package/src/views/Preview.vue
CHANGED
@@ -1,12 +1,38 @@
|
|
1
|
-
<script setup lang="ts">
|
2
|
-
import SvgViewer from '@/components/svg-viewer/index.vue'
|
3
|
-
import {
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
1
|
+
<script setup lang="ts">
|
2
|
+
import SvgViewer from '@/components/svg-viewer/index.vue'
|
3
|
+
import { ElButton } from 'element-plus'
|
4
|
+
import { ArrowLeftBold } from '@element-plus/icons-vue'
|
5
|
+
import { useStore } from '@/stores/main'
|
6
|
+
|
7
|
+
const emit = defineEmits(['back'])
|
8
|
+
const store = useStore()
|
9
|
+
|
10
|
+
function back() {
|
11
|
+
emit('back')
|
12
|
+
}
|
13
|
+
</script>
|
14
|
+
|
15
|
+
<template>
|
16
|
+
<div class="previewPage">
|
17
|
+
<svg-viewer :data="store.data" />
|
18
|
+
<el-button @click="back" class="backBtn" :icon="ArrowLeftBold">返回</el-button>
|
19
|
+
</div>
|
20
|
+
</template>
|
21
|
+
|
22
|
+
<style lang="less" scoped>
|
23
|
+
.previewPage {
|
24
|
+
position: fixed;
|
25
|
+
z-index: 1000;
|
26
|
+
left: 0;
|
27
|
+
right: 0;
|
28
|
+
top: 0;
|
29
|
+
bottom: 0;
|
30
|
+
|
31
|
+
.backBtn {
|
32
|
+
position: absolute;
|
33
|
+
top: 20px;
|
34
|
+
right: 30px;
|
35
|
+
z-index: 100;
|
36
|
+
}
|
37
|
+
}
|
38
|
+
</style>
|