jvs-ppt-ui 0.0.14 → 0.0.16
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/dist/lib/check_imgs.html +18 -0
- package/dist/lib/jvs-ppt-ui/iconfont/iconfont.css +187 -27
- package/dist/lib/jvs-ppt-ui/iconfont/iconfont.js +1 -1
- package/dist/lib/jvs-ppt-ui/iconfont/iconfont.json +345 -65
- package/dist/lib/jvs-ppt-ui/iconfont/iconfont.ttf +0 -0
- package/dist/lib/jvs-ppt-ui/iconfont/iconfont.woff +0 -0
- package/dist/lib/jvs-ppt-ui/iconfont/iconfont.woff2 +0 -0
- package/dist/lib/jvs-ppt-ui/img/al.png +0 -0
- package/dist/lib/jvs-ppt-ui/img/d.png +0 -0
- package/dist/lib/jvs-ppt-ui/img/dl.png +0 -0
- package/dist/lib/jvs-ppt-ui/img/l.png +0 -0
- package/dist/lib/jvs-ppt-ui.es.js +44973 -43349
- package/dist/lib/jvs-ppt-ui.umd.js +102 -102
- package/dist/lib/style.css +1 -1
- package/package.json +1 -1
- package/scripts/check-icons.mjs +22 -0
- package/scripts/patch-anim-icons.mjs +45 -0
- package/src/assets/iconfont/iconfont.css +187 -27
- package/src/assets/iconfont/iconfont.js +1 -1
- package/src/assets/iconfont/iconfont.json +345 -65
- package/src/assets/iconfont/iconfont.ttf +0 -0
- package/src/assets/iconfont/iconfont.woff +0 -0
- package/src/assets/iconfont/iconfont.woff2 +0 -0
- package/src/components/CanvasArea.vue +218 -193
- package/src/components/ChartTypeSelector.vue +509 -148
- package/src/components/Header.vue +327 -44
- package/src/components/PresentationGroupChild.vue +44 -13
- package/src/components/PresentationMode.vue +84 -33
- package/src/components/QuickBorderPopover.vue +51 -11
- package/src/components/QuickColorPopover.vue +65 -21
- package/src/components/SidebarLeft.vue +286 -107
- package/src/components/SidebarRight.vue +45 -38
- package/src/components/TemplateGallery.vue +1110 -1237
- package/src/components/ToastNotification.vue +2 -2
- package/src/components/Toolbar.vue +825 -733
- package/src/components/canvas/CanvasQuickToolbar.vue +17 -30
- package/src/components/canvas/elements/CanvasGroupElement.vue +6 -0
- package/src/components/canvas/elements/CanvasShapeElement.vue +198 -38
- package/src/components/canvas/elements/CanvasTextElement.vue +4 -3
- package/src/components/sidebar/common/SidebarAlignGroup.vue +104 -50
- package/src/components/sidebar/common/SidebarBorderAccordion.vue +375 -148
- package/src/components/sidebar/common/SidebarPositionGroup.vue +358 -149
- package/src/components/sidebar/common/SidebarReflectionAccordion.vue +429 -203
- package/src/components/sidebar/common/SidebarShadowAccordion.vue +844 -416
- package/src/components/sidebar/panels/GradientEditor.vue +671 -316
- package/src/components/sidebar/panels/LayoutThumbSvg.vue +33 -16
- package/src/components/sidebar/panels/SidebarAnimationPanel.vue +701 -138
- package/src/components/sidebar/panels/SidebarChartFormatPanel.vue +3 -3
- package/src/components/sidebar/panels/SidebarDesignPanel.vue +1754 -416
- package/src/components/sidebar/panels/SidebarMediaFormatPanel.vue +12 -0
- package/src/components/sidebar/panels/SidebarShapeFormatPanel.vue +813 -174
- package/src/components/sidebar/panels/SidebarTableFormatPanel.vue +2 -2
- package/src/components/sidebar/panels/SidebarTextFormatPanel.vue +1938 -1427
- package/src/components/sidebar/panels/SidebarTransitionPanel.vue +791 -210
- package/src/composables/canvas/useCanvasShortcuts.ts +20 -6
- package/src/composables/canvas/useCanvasText.ts +1 -1
- package/src/composables/canvas/useCanvasTransform.ts +44 -0
- package/src/composables/presetThemes.ts +43 -44
- package/src/composables/sidebar/useSidebarAnimation.ts +101 -25
- package/src/composables/sidebar/useSidebarDesign.ts +30 -11
- package/src/composables/sidebar/useSidebarElementTransform.ts +10 -1
- package/src/composables/sidebar/useSidebarImage.ts +10 -2
- package/src/composables/sidebar/useSidebarShapeFormat.ts +562 -107
- package/src/composables/useSlides.ts +331 -153
- package/src/main.ts +2 -0
- package/src/style.css +926 -359
- package/src/utils/canvas/elementStyles.ts +42 -1
|
@@ -30,6 +30,9 @@ export function parseColor(colorStr: any) {
|
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
const str = colorStr.trim().toLowerCase()
|
|
33
|
+
if (str === 'transparent' || str === 'none') {
|
|
34
|
+
return { hex: 'transparent', alpha: 0 }
|
|
35
|
+
}
|
|
33
36
|
if (str.startsWith('rgba')) {
|
|
34
37
|
const matches = str.match(/rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*([\d.]+)\s*\)/)
|
|
35
38
|
if (matches) {
|
|
@@ -70,15 +73,151 @@ export function hexToRgba(hex: string, alphaPercent: number) {
|
|
|
70
73
|
return `rgba(${r}, ${g}, ${b}, ${a})`
|
|
71
74
|
}
|
|
72
75
|
|
|
76
|
+
export function generateGradientEndColor(hex: string): string {
|
|
77
|
+
const parsed = parseColor(hex)
|
|
78
|
+
if (!parsed.hex || parsed.hex === 'transparent' || parsed.hex.toLowerCase() === 'none') return '#60A5FA'
|
|
79
|
+
const clean = parsed.hex.replace('#', '')
|
|
80
|
+
if (clean.length < 6) return '#60A5FA'
|
|
81
|
+
const r = parseInt(clean.substring(0, 2), 16) || 0
|
|
82
|
+
const g = parseInt(clean.substring(2, 4), 16) || 0
|
|
83
|
+
const b = parseInt(clean.substring(4, 6), 16) || 0
|
|
84
|
+
|
|
85
|
+
const brightness = (r * 299 + g * 587 + b * 114) / 1000
|
|
86
|
+
if (brightness > 220) {
|
|
87
|
+
const darkR = Math.max(0, Math.round(r * 0.75)).toString(16).padStart(2, '0')
|
|
88
|
+
const darkG = Math.max(0, Math.round(g * 0.75)).toString(16).padStart(2, '0')
|
|
89
|
+
const darkB = Math.max(0, Math.round(b * 0.75)).toString(16).padStart(2, '0')
|
|
90
|
+
return `#${darkR}${darkG}${darkB}`.toUpperCase()
|
|
91
|
+
} else {
|
|
92
|
+
const lightR = Math.min(255, Math.round(r + (255 - r) * 0.55)).toString(16).padStart(2, '0')
|
|
93
|
+
const lightG = Math.min(255, Math.round(g + (255 - g) * 0.55)).toString(16).padStart(2, '0')
|
|
94
|
+
const lightB = Math.min(255, Math.round(b + (255 - b) * 0.55)).toString(16).padStart(2, '0')
|
|
95
|
+
return `#${lightR}${lightG}${lightB}`.toUpperCase()
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function encodeSvgColor(color: string, fallback = '#3B82F6'): string {
|
|
100
|
+
const c = (color || fallback).trim()
|
|
101
|
+
if (!c || c === 'none') return 'transparent'
|
|
102
|
+
return c.replace(/#/g, '%23')
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export function buildPatternSvgDataUrl(type: string, fgColor = '#3B82F6', bgColor = '#FFFFFF'): string {
|
|
106
|
+
const fg = encodeSvgColor(fgColor, '#3B82F6')
|
|
107
|
+
const bg = encodeSvgColor(bgColor, '#FFFFFF')
|
|
108
|
+
const rawFg = (fgColor || '#3B82F6').trim().replace(/#/g, '%23')
|
|
109
|
+
const rawBg = (bgColor || '#FFFFFF').trim().replace(/#/g, '%23')
|
|
110
|
+
|
|
111
|
+
let w = 10
|
|
112
|
+
let h = 10
|
|
113
|
+
let body = ''
|
|
114
|
+
|
|
115
|
+
switch (type) {
|
|
116
|
+
case 'dots-sparse':
|
|
117
|
+
w = 10; h = 10
|
|
118
|
+
body = `<circle cx='2.5' cy='2.5' r='1.1' fill='${fg}'/><circle cx='7.5' cy='7.5' r='1.1' fill='${fg}'/>`
|
|
119
|
+
break
|
|
120
|
+
case 'dots-dense':
|
|
121
|
+
w = 10; h = 10
|
|
122
|
+
body = `<circle cx='5' cy='5' r='2' fill='${fg}'/>`
|
|
123
|
+
break
|
|
124
|
+
case 'diag-up':
|
|
125
|
+
w = 10; h = 10
|
|
126
|
+
body = `<path d='M0 10L10 0M-2 2L2 -2M8 12L12 8' stroke='${fg}' stroke-width='1.5'/>`
|
|
127
|
+
break
|
|
128
|
+
case 'diag-down':
|
|
129
|
+
w = 10; h = 10
|
|
130
|
+
body = `<path d='M0 0L10 10M-2 8L2 12M8 -2L12 2' stroke='${fg}' stroke-width='1.5'/>`
|
|
131
|
+
break
|
|
132
|
+
case 'cross-diag':
|
|
133
|
+
w = 10; h = 10
|
|
134
|
+
body = `<path d='M0 10L10 0M0 0L10 10' stroke='${fg}' stroke-width='1.2'/>`
|
|
135
|
+
break
|
|
136
|
+
case 'grid':
|
|
137
|
+
w = 12; h = 12
|
|
138
|
+
body = `<path d='M12 0H0V12' fill='none' stroke='${fg}' stroke-width='1.2'/>`
|
|
139
|
+
break
|
|
140
|
+
case 'horizontal':
|
|
141
|
+
w = 8; h = 8
|
|
142
|
+
body = `<line x1='0' y1='4' x2='8' y2='4' stroke='${fg}' stroke-width='1.5'/>`
|
|
143
|
+
break
|
|
144
|
+
case 'vertical':
|
|
145
|
+
w = 8; h = 8
|
|
146
|
+
body = `<line x1='4' y1='0' x2='4' y2='8' stroke='${fg}' stroke-width='1.5'/>`
|
|
147
|
+
break
|
|
148
|
+
case 'brick':
|
|
149
|
+
w = 16; h = 16
|
|
150
|
+
body = `<path d='M0 8h16M8 0v8M0 16v-8' fill='none' stroke='${fg}' stroke-width='1.2'/>`
|
|
151
|
+
break
|
|
152
|
+
case 'wave':
|
|
153
|
+
w = 16; h = 8
|
|
154
|
+
body = `<path d='M0 4 Q4 0, 8 4 T16 4' fill='none' stroke='${fg}' stroke-width='1.3'/>`
|
|
155
|
+
break
|
|
156
|
+
case 'checker':
|
|
157
|
+
w = 12; h = 12
|
|
158
|
+
body = `<rect width='6' height='6' fill='${fg}'/><rect x='6' y='6' width='6' height='6' fill='${fg}'/>`
|
|
159
|
+
break
|
|
160
|
+
case 'zigzag':
|
|
161
|
+
w = 12; h = 8
|
|
162
|
+
body = `<path d='M0 6L6 2L12 6' fill='none' stroke='${fg}' stroke-width='1.3' stroke-linecap='round' stroke-linejoin='round'/>`
|
|
163
|
+
break
|
|
164
|
+
default:
|
|
165
|
+
w = 10; h = 10
|
|
166
|
+
body = `<path d='M0 10L10 0M-2 2L2 -2M8 12L12 8' stroke='${fg}' stroke-width='1.5'/>`
|
|
167
|
+
break
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const svg = `<svg xmlns='http://www.w3.org/2000/svg' width='${w}' height='${h}' data-pattern-type='${type}' data-fg='${rawFg}' data-bg='${rawBg}'><rect width='${w}' height='${h}' fill='${bg}'/>${body}</svg>`
|
|
171
|
+
const encoded = svg
|
|
172
|
+
.replace(/'/g, '%22')
|
|
173
|
+
.replace(/</g, '%3C')
|
|
174
|
+
.replace(/>/g, '%3E')
|
|
175
|
+
.replace(/\s+/g, '%20')
|
|
176
|
+
return `data:image/svg+xml;utf8,${encoded}`
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export function parsePatternSvgMeta(url?: string): { type?: string; fg?: string; bg?: string } {
|
|
180
|
+
if (!url || typeof url !== 'string' || !url.startsWith('data:image/svg+xml')) return {}
|
|
181
|
+
let decoded = url
|
|
182
|
+
try {
|
|
183
|
+
decoded = decodeURIComponent(url)
|
|
184
|
+
} catch {
|
|
185
|
+
decoded = url.replace(/%22/g, '"').replace(/%27/g, "'").replace(/%23/g, '#')
|
|
186
|
+
}
|
|
187
|
+
const typeMatch = decoded.match(/data-pattern-type=['"]([^'"]+)['"]/)
|
|
188
|
+
const fgMatch = decoded.match(/data-fg=['"]([^'"]+)['"]/)
|
|
189
|
+
const bgMatch = decoded.match(/data-bg=['"]([^'"]+)['"]/)
|
|
190
|
+
let type = typeMatch ? typeMatch[1] : undefined
|
|
191
|
+
if (!type) {
|
|
192
|
+
if (decoded.includes('M0 10L10 0M0 0L10 10')) type = 'cross-diag'
|
|
193
|
+
else if (decoded.includes('M0 10L10 0')) type = 'diag-up'
|
|
194
|
+
else if (decoded.includes('M12 0H0V12')) type = 'grid'
|
|
195
|
+
else if (decoded.includes('cx="5" cy="5" r="2"') || decoded.includes("cx='5' cy='5' r='2'")) type = 'dots-dense'
|
|
196
|
+
else if (decoded.includes('M0 8h16')) type = 'brick'
|
|
197
|
+
else if (decoded.includes('y1="4" x2="8"') || decoded.includes("y1='4' x2='8'")) type = 'horizontal'
|
|
198
|
+
else if (decoded.includes('Q4 0, 8 4')) type = 'wave'
|
|
199
|
+
else if (decoded.includes('width="6" height="6"') || decoded.includes("width='6' height='6'")) type = 'checker'
|
|
200
|
+
}
|
|
201
|
+
return {
|
|
202
|
+
type,
|
|
203
|
+
fg: fgMatch ? fgMatch[1].replace(/%23/g, '#') : undefined,
|
|
204
|
+
bg: bgMatch ? bgMatch[1].replace(/%23/g, '#') : undefined
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
73
208
|
export const PATTERN_PRESETS = [
|
|
74
|
-
{
|
|
75
|
-
{
|
|
76
|
-
{
|
|
77
|
-
{
|
|
78
|
-
{
|
|
79
|
-
{
|
|
80
|
-
{
|
|
81
|
-
{
|
|
209
|
+
{ key: 'dots-sparse', name: '稀疏圆点', url: buildPatternSvgDataUrl('dots-sparse', '#3B82F6', '#FFFFFF') },
|
|
210
|
+
{ key: 'dots-dense', name: '密集圆点', url: buildPatternSvgDataUrl('dots-dense', '#3B82F6', '#FFFFFF') },
|
|
211
|
+
{ key: 'diag-up', name: '上对角线', url: buildPatternSvgDataUrl('diag-up', '#3B82F6', '#FFFFFF') },
|
|
212
|
+
{ key: 'diag-down', name: '下对角线', url: buildPatternSvgDataUrl('diag-down', '#3B82F6', '#FFFFFF') },
|
|
213
|
+
{ key: 'cross-diag', name: '交叉斜线', url: buildPatternSvgDataUrl('cross-diag', '#3B82F6', '#FFFFFF') },
|
|
214
|
+
{ key: 'grid', name: '细网格', url: buildPatternSvgDataUrl('grid', '#3B82F6', '#FFFFFF') },
|
|
215
|
+
{ key: 'horizontal', name: '横线', url: buildPatternSvgDataUrl('horizontal', '#3B82F6', '#FFFFFF') },
|
|
216
|
+
{ key: 'vertical', name: '竖线', url: buildPatternSvgDataUrl('vertical', '#3B82F6', '#FFFFFF') },
|
|
217
|
+
{ key: 'brick', name: '砖块', url: buildPatternSvgDataUrl('brick', '#3B82F6', '#FFFFFF') },
|
|
218
|
+
{ key: 'wave', name: '波浪', url: buildPatternSvgDataUrl('wave', '#3B82F6', '#FFFFFF') },
|
|
219
|
+
{ key: 'checker', name: '棋盘格', url: buildPatternSvgDataUrl('checker', '#3B82F6', '#FFFFFF') },
|
|
220
|
+
{ key: 'zigzag', name: '之字形', url: buildPatternSvgDataUrl('zigzag', '#3B82F6', '#FFFFFF') }
|
|
82
221
|
]
|
|
83
222
|
|
|
84
223
|
export function useSidebarShapeFormat(
|
|
@@ -143,13 +282,17 @@ export function useSidebarShapeFormat(
|
|
|
143
282
|
|
|
144
283
|
function hasElementFill(el: any): boolean {
|
|
145
284
|
if (!el) return false
|
|
285
|
+
if (activeFillType.value && activeFillType.value !== 'transparent') {
|
|
286
|
+
return true
|
|
287
|
+
}
|
|
146
288
|
// 1. 渐变填充
|
|
147
289
|
const rawFill = (el.style && el.style.fill !== undefined) ? el.style.fill : el.fill
|
|
148
290
|
if (el.gradient || el.style?.gradient || (rawFill && typeof rawFill === 'object' && rawFill.type === 'gradient')) {
|
|
149
291
|
return true
|
|
150
292
|
}
|
|
151
293
|
// 2. 图片/图案填充
|
|
152
|
-
|
|
294
|
+
const hasPatternVal = (el.pattern !== undefined && el.pattern !== '') || (el.style?.pattern !== undefined && el.style?.pattern !== '')
|
|
295
|
+
if (hasPatternVal || (rawFill && typeof rawFill === 'object' && (rawFill.type === 'image' || rawFill.type === 'pattern'))) {
|
|
153
296
|
return true
|
|
154
297
|
}
|
|
155
298
|
// 3. 常规色彩填充
|
|
@@ -258,6 +401,9 @@ export function useSidebarShapeFormat(
|
|
|
258
401
|
|
|
259
402
|
const isFillEnabled = computed({
|
|
260
403
|
get() {
|
|
404
|
+
if (activeFillType.value && activeFillType.value !== 'transparent') {
|
|
405
|
+
return true
|
|
406
|
+
}
|
|
261
407
|
if (isMultiOrGroup()) {
|
|
262
408
|
const elements = getFormattingElements()
|
|
263
409
|
return elements.some((el: any) => hasElementFill(el))
|
|
@@ -265,42 +411,20 @@ export function useSidebarShapeFormat(
|
|
|
265
411
|
return hasElementFill(selectedElement.value)
|
|
266
412
|
},
|
|
267
413
|
set(val: boolean) {
|
|
414
|
+
if (!val) {
|
|
415
|
+
activeFillType.value = null
|
|
416
|
+
}
|
|
268
417
|
const newType = val ? 'color' : 'transparent'
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
elements.forEach((el: any) => {
|
|
272
|
-
if (!el.style) el.style = {}
|
|
273
|
-
if (newType === 'transparent') {
|
|
274
|
-
el.style.fill = 'transparent'
|
|
275
|
-
el.fill = 'transparent'
|
|
276
|
-
delete el.gradient
|
|
277
|
-
delete el.style.gradient
|
|
278
|
-
delete el.pattern
|
|
279
|
-
delete el.style.pattern
|
|
280
|
-
} else {
|
|
281
|
-
if (el.style.fill === 'transparent' || !el.style.fill || el.fill === 'transparent') {
|
|
282
|
-
let defaultColor = '#3b82f6'
|
|
283
|
-
if (el.type === 'shape') {
|
|
284
|
-
const shapeType = el.content || 'rect'
|
|
285
|
-
if (shapeType === 'circle') defaultColor = '#3b82f6'
|
|
286
|
-
else if (shapeType === 'triangle' || shapeType === 'M 100 0 L 0 200 L 200 200 Z') defaultColor = '#f59e0b'
|
|
287
|
-
else defaultColor = '#10b981'
|
|
288
|
-
}
|
|
289
|
-
el.style.fill = defaultColor
|
|
290
|
-
el.fill = defaultColor
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
})
|
|
294
|
-
if (selectedElement.value?.type === 'group') {
|
|
295
|
-
if (!selectedElement.value.style) selectedElement.value.style = {}
|
|
296
|
-
selectedElement.value.style.fill = newType === 'transparent' ? 'transparent' : '#3b82f6'
|
|
297
|
-
selectedElement.value.fill = newType === 'transparent' ? 'transparent' : '#3b82f6'
|
|
298
|
-
}
|
|
299
|
-
} else {
|
|
300
|
-
if (!selectedElement.value) return
|
|
301
|
-
const el = selectedElement.value
|
|
418
|
+
const elements = getFormattingElements()
|
|
419
|
+
elements.forEach((el: any) => {
|
|
302
420
|
if (!el.style) el.style = {}
|
|
303
421
|
if (newType === 'transparent') {
|
|
422
|
+
const curG = getStandardGradientConfig(el)
|
|
423
|
+
if (curG) el._lastGradient = curG
|
|
424
|
+
const curS = el.style.fill || el.fill
|
|
425
|
+
if (typeof curS === 'string' && curS !== 'none' && curS !== 'transparent') {
|
|
426
|
+
el._lastSolidFill = curS
|
|
427
|
+
}
|
|
304
428
|
el.style.fill = 'transparent'
|
|
305
429
|
el.fill = 'transparent'
|
|
306
430
|
delete el.gradient
|
|
@@ -308,7 +432,14 @@ export function useSidebarShapeFormat(
|
|
|
308
432
|
delete el.pattern
|
|
309
433
|
delete el.style.pattern
|
|
310
434
|
} else {
|
|
311
|
-
if (el.
|
|
435
|
+
if (el._lastGradient) {
|
|
436
|
+
el.gradient = el._lastGradient
|
|
437
|
+
el.fill = { type: 'gradient', value: el._lastGradient }
|
|
438
|
+
el.style.fill = 'none'
|
|
439
|
+
} else if (el._lastSolidFill) {
|
|
440
|
+
el.style.fill = el._lastSolidFill
|
|
441
|
+
el.fill = el._lastSolidFill
|
|
442
|
+
} else if (el.style.fill === 'transparent' || !el.style.fill || el.fill === 'transparent') {
|
|
312
443
|
let defaultColor = '#3b82f6'
|
|
313
444
|
if (el.type === 'shape') {
|
|
314
445
|
const shapeType = el.content || 'rect'
|
|
@@ -320,6 +451,11 @@ export function useSidebarShapeFormat(
|
|
|
320
451
|
el.fill = defaultColor
|
|
321
452
|
}
|
|
322
453
|
}
|
|
454
|
+
})
|
|
455
|
+
if (selectedElement.value?.type === 'group') {
|
|
456
|
+
if (!selectedElement.value.style) selectedElement.value.style = {}
|
|
457
|
+
selectedElement.value.style.fill = newType === 'transparent' ? 'transparent' : (selectedElement.value._lastSolidFill || '#3b82f6')
|
|
458
|
+
selectedElement.value.fill = newType === 'transparent' ? 'transparent' : (selectedElement.value._lastSolidFill || '#3b82f6')
|
|
323
459
|
}
|
|
324
460
|
addHistorySnapshot()
|
|
325
461
|
}
|
|
@@ -332,10 +468,11 @@ export function useSidebarShapeFormat(
|
|
|
332
468
|
if (activeFillType.value) return activeFillType.value
|
|
333
469
|
|
|
334
470
|
const rawFill = (el.style && el.style.fill !== undefined) ? el.style.fill : el.fill
|
|
471
|
+
const hasPattern = (el.pattern !== undefined && el.pattern !== '') || (el.style?.pattern !== undefined && el.style?.pattern !== '')
|
|
335
472
|
const patternVal = el.pattern || el.style?.pattern || (rawFill && typeof rawFill === 'object' && (rawFill.type === 'image' || rawFill.type === 'pattern') ? (rawFill.value?.src || rawFill.value?.url || rawFill.value) : '')
|
|
336
473
|
|
|
337
|
-
if (patternVal) {
|
|
338
|
-
if (PATTERN_PRESETS.some(item => item.url === patternVal)) {
|
|
474
|
+
if (hasPattern || patternVal) {
|
|
475
|
+
if (patternVal && (String(patternVal).startsWith('data:image/svg+xml') || el.patternType || el.style?.patternType || PATTERN_PRESETS.some(item => item.url === patternVal))) {
|
|
339
476
|
return 'pattern'
|
|
340
477
|
}
|
|
341
478
|
return 'image'
|
|
@@ -347,29 +484,108 @@ export function useSidebarShapeFormat(
|
|
|
347
484
|
},
|
|
348
485
|
set(val: string) {
|
|
349
486
|
if (!selectedElement.value) return
|
|
350
|
-
const
|
|
487
|
+
const elements = getFormattingElements()
|
|
351
488
|
activeFillType.value = val
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
489
|
+
|
|
490
|
+
elements.forEach((el: any) => {
|
|
491
|
+
if (!el.style) el.style = {}
|
|
492
|
+
|
|
493
|
+
if (val === 'solid') {
|
|
494
|
+
const curG = getStandardGradientConfig(el)
|
|
495
|
+
if (curG) {
|
|
496
|
+
el._lastGradient = curG
|
|
497
|
+
}
|
|
498
|
+
let targetSolid = el._lastSolidFill
|
|
499
|
+
if (!targetSolid || targetSolid === 'none' || targetSolid === 'transparent') {
|
|
500
|
+
if (curG?.colors && curG.colors.length > 0 && curG.colors[0]?.color) {
|
|
501
|
+
targetSolid = curG.colors[0].color
|
|
502
|
+
} else {
|
|
503
|
+
const current = el.style?.fill || el.fill
|
|
504
|
+
if (typeof current === 'string' && current !== 'none' && current !== 'transparent') {
|
|
505
|
+
targetSolid = current
|
|
506
|
+
} else if (fillHex.value && fillHex.value !== 'transparent' && fillHex.value !== 'none') {
|
|
507
|
+
targetSolid = fillHex.value
|
|
508
|
+
} else {
|
|
509
|
+
targetSolid = '#3b82f6'
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
el._lastSolidFill = targetSolid
|
|
514
|
+
delete el.gradient
|
|
515
|
+
delete el.style.gradient
|
|
516
|
+
delete el.pattern
|
|
517
|
+
delete el.style.pattern
|
|
518
|
+
el.style.fill = targetSolid
|
|
519
|
+
el.fill = targetSolid
|
|
520
|
+
styleFill.value = targetSolid
|
|
521
|
+
} else if (val === 'gradient') {
|
|
522
|
+
const current = el.style?.fill || el.fill
|
|
523
|
+
if (typeof current === 'string' && current !== 'none' && current !== 'transparent') {
|
|
524
|
+
el._lastSolidFill = current
|
|
525
|
+
} else if (fillHex.value && fillHex.value !== 'transparent' && fillHex.value !== 'none') {
|
|
526
|
+
el._lastSolidFill = fillHex.value
|
|
527
|
+
}
|
|
528
|
+
delete el.pattern
|
|
529
|
+
delete el.style.pattern
|
|
530
|
+
|
|
531
|
+
const cachedG = getStandardGradientConfig(el) || el._lastGradient
|
|
532
|
+
if (cachedG && cachedG.colors && cachedG.colors.length >= 2) {
|
|
533
|
+
updateGradientConfig({
|
|
534
|
+
colors: cachedG.colors,
|
|
535
|
+
path: cachedG.path,
|
|
536
|
+
rot: cachedG.rot,
|
|
537
|
+
direction: cachedG.direction,
|
|
538
|
+
directionName: cachedG.directionName,
|
|
539
|
+
center: cachedG.center,
|
|
540
|
+
fillToRect: cachedG.fillToRect
|
|
541
|
+
})
|
|
542
|
+
} else {
|
|
543
|
+
const startColor = el._lastSolidFill ? parseColor(el._lastSolidFill).hex : (fillHex.value && fillHex.value !== 'transparent' && fillHex.value !== 'none' ? fillHex.value : '#3b82f6')
|
|
544
|
+
const endColor = generateGradientEndColor(startColor)
|
|
545
|
+
updateGradientConfig({
|
|
546
|
+
startColor,
|
|
547
|
+
endColor
|
|
548
|
+
})
|
|
549
|
+
}
|
|
550
|
+
} else if (val === 'image') {
|
|
551
|
+
const curG = getStandardGradientConfig(el)
|
|
552
|
+
if (curG) el._lastGradient = curG
|
|
553
|
+
const curS = el.style?.fill || el.fill
|
|
554
|
+
if (typeof curS === 'string' && curS !== 'none' && curS !== 'transparent') {
|
|
555
|
+
el._lastSolidFill = curS
|
|
556
|
+
}
|
|
557
|
+
delete el.gradient
|
|
558
|
+
delete el.style.gradient
|
|
559
|
+
const existing = el.pattern || el.style?.pattern || ''
|
|
560
|
+
const isPreset = String(existing).startsWith('data:image/svg+xml') || PATTERN_PRESETS.some(item => item.url === existing)
|
|
561
|
+
const patVal = (!existing || isPreset) ? '' : existing
|
|
562
|
+
el.pattern = patVal
|
|
563
|
+
el.style.pattern = patVal
|
|
564
|
+
el.style.fill = 'none'
|
|
565
|
+
} else if (val === 'pattern') {
|
|
566
|
+
const curG = getStandardGradientConfig(el)
|
|
567
|
+
if (curG) el._lastGradient = curG
|
|
568
|
+
const curS = el.style?.fill || el.fill
|
|
569
|
+
if (typeof curS === 'string' && curS !== 'none' && curS !== 'transparent') {
|
|
570
|
+
el._lastSolidFill = curS
|
|
571
|
+
}
|
|
572
|
+
delete el.gradient
|
|
573
|
+
delete el.style.gradient
|
|
574
|
+
const pType = el.patternType || el.style?.patternType || 'diag-up'
|
|
575
|
+
const pFg = el.patternFg || el.style?.patternFg || (el._lastSolidFill && el._lastSolidFill !== 'none' && el._lastSolidFill !== 'transparent' ? el._lastSolidFill : '#3B82F6')
|
|
576
|
+
const pBg = el.patternBg || el.style?.patternBg || '#FFFFFF'
|
|
577
|
+
el.patternType = pType
|
|
578
|
+
el.patternFg = pFg
|
|
579
|
+
el.patternBg = pBg
|
|
580
|
+
el.style.patternType = pType
|
|
581
|
+
el.style.patternFg = pFg
|
|
582
|
+
el.style.patternBg = pBg
|
|
583
|
+
const patUrl = buildPatternSvgDataUrl(pType, pFg, pBg)
|
|
584
|
+
el.pattern = patUrl
|
|
585
|
+
el.style.pattern = patUrl
|
|
586
|
+
el.style.fill = 'none'
|
|
587
|
+
}
|
|
588
|
+
})
|
|
373
589
|
addHistorySnapshot()
|
|
374
590
|
}
|
|
375
591
|
})
|
|
@@ -386,26 +602,78 @@ export function useSidebarShapeFormat(
|
|
|
386
602
|
}
|
|
387
603
|
return 'transparent'
|
|
388
604
|
}
|
|
605
|
+
const el = selectedElement.value
|
|
606
|
+
if (el?.style?.fill && el.style.fill !== 'none' && el.style.fill !== 'transparent') {
|
|
607
|
+
return parseColor(el.style.fill).hex
|
|
608
|
+
}
|
|
609
|
+
if (el?.fill && typeof el.fill === 'string' && el.fill !== 'none' && el.fill !== 'transparent') {
|
|
610
|
+
return parseColor(el.fill).hex
|
|
611
|
+
}
|
|
612
|
+
if (el?._lastSolidFill) {
|
|
613
|
+
return parseColor(el._lastSolidFill).hex
|
|
614
|
+
}
|
|
389
615
|
const fill = styleFill.value || '#363B4C'
|
|
390
616
|
return parseColor(fill).hex
|
|
391
617
|
},
|
|
392
618
|
set(val: string) {
|
|
393
619
|
if (isMultiOrGroup()) {
|
|
394
620
|
const elements = getFormattingElements()
|
|
621
|
+
const parsed = parseColor(val)
|
|
395
622
|
elements.forEach((el: any) => {
|
|
396
623
|
if (!el.style) el.style = {}
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
el.
|
|
624
|
+
delete el.gradient
|
|
625
|
+
delete el.style.gradient
|
|
626
|
+
delete el.pattern
|
|
627
|
+
delete el.style.pattern
|
|
628
|
+
if (val === 'transparent' || val === 'none') {
|
|
629
|
+
el.style.fill = 'transparent'
|
|
630
|
+
el.fill = 'transparent'
|
|
631
|
+
} else {
|
|
632
|
+
const currentFill = el.style.fill || '#363B4C'
|
|
633
|
+
let currentAlpha = parseColor(currentFill).alpha
|
|
634
|
+
if (currentAlpha === 0 || currentAlpha === undefined) currentAlpha = 100
|
|
635
|
+
const alphaToUse = (parsed.alpha !== undefined && parsed.alpha < 100) ? parsed.alpha : currentAlpha
|
|
636
|
+
const rgba = hexToRgba(parsed.hex, alphaToUse)
|
|
637
|
+
el.style.fill = rgba
|
|
638
|
+
el.fill = rgba
|
|
639
|
+
el._lastSolidFill = rgba
|
|
640
|
+
}
|
|
400
641
|
})
|
|
401
642
|
if (selectedElement.value?.type === 'group') {
|
|
402
643
|
if (!selectedElement.value.style) selectedElement.value.style = {}
|
|
403
644
|
selectedElement.value.style.fill = val
|
|
645
|
+
selectedElement.value.fill = val
|
|
646
|
+
selectedElement.value._lastSolidFill = val
|
|
404
647
|
}
|
|
405
648
|
} else {
|
|
406
649
|
if (!selectedElement.value) return
|
|
407
|
-
const
|
|
408
|
-
|
|
650
|
+
const el = selectedElement.value
|
|
651
|
+
delete el.gradient
|
|
652
|
+
if (el.style) delete el.style.gradient
|
|
653
|
+
delete el.pattern
|
|
654
|
+
if (el.style) delete el.style.pattern
|
|
655
|
+
activeFillType.value = 'solid'
|
|
656
|
+
if (val === 'transparent' || val === 'none') {
|
|
657
|
+
styleFill.value = 'transparent'
|
|
658
|
+
el.fill = 'transparent'
|
|
659
|
+
if (el.style) el.style.fill = 'transparent'
|
|
660
|
+
} else {
|
|
661
|
+
const parsed = parseColor(val)
|
|
662
|
+
let alpha = fillAlpha.value
|
|
663
|
+
if (alpha === 0 || alpha === undefined) alpha = 100
|
|
664
|
+
if (parsed.alpha !== undefined && parsed.alpha < 100) {
|
|
665
|
+
alpha = parsed.alpha
|
|
666
|
+
}
|
|
667
|
+
const rgba = hexToRgba(parsed.hex, alpha)
|
|
668
|
+
styleFill.value = rgba
|
|
669
|
+
el.fill = rgba
|
|
670
|
+
if (el.style) el.style.fill = rgba
|
|
671
|
+
el._lastSolidFill = rgba
|
|
672
|
+
if (parsed.alpha !== undefined && parsed.alpha < 100) {
|
|
673
|
+
el.opacity = alpha / 100
|
|
674
|
+
if (el.style) el.style.opacity = alpha / 100
|
|
675
|
+
}
|
|
676
|
+
}
|
|
409
677
|
}
|
|
410
678
|
addHistorySnapshot()
|
|
411
679
|
}
|
|
@@ -415,6 +683,13 @@ export function useSidebarShapeFormat(
|
|
|
415
683
|
get() {
|
|
416
684
|
if (selectedElement.value) {
|
|
417
685
|
const el = selectedElement.value
|
|
686
|
+
const rawFill = (el.style && el.style.fill !== undefined) ? el.style.fill : el.fill
|
|
687
|
+
if (rawFill) {
|
|
688
|
+
const colorParsed = parseColor(rawFill)
|
|
689
|
+
if (colorParsed.alpha !== undefined && colorParsed.alpha < 100) {
|
|
690
|
+
return colorParsed.alpha
|
|
691
|
+
}
|
|
692
|
+
}
|
|
418
693
|
const op = el.style?.opacity !== undefined ? el.style.opacity : (el.opacity !== undefined ? el.opacity : undefined)
|
|
419
694
|
if (op !== undefined) {
|
|
420
695
|
return Math.round((typeof op === 'number' ? op : parseFloat(op) || 1) * 100)
|
|
@@ -433,7 +708,10 @@ export function useSidebarShapeFormat(
|
|
|
433
708
|
el.style.opacity = alpha
|
|
434
709
|
const currentFill = el.style.fill || '#363B4C'
|
|
435
710
|
const hex = parseColor(currentFill).hex
|
|
436
|
-
|
|
711
|
+
const validHex = (hex && hex !== 'transparent') ? hex : '#3b82f6'
|
|
712
|
+
const rgba = hexToRgba(validHex, val)
|
|
713
|
+
el.style.fill = rgba
|
|
714
|
+
el.fill = rgba
|
|
437
715
|
})
|
|
438
716
|
if (selectedElement.value) {
|
|
439
717
|
if (!selectedElement.value.style) selectedElement.value.style = {}
|
|
@@ -447,8 +725,11 @@ export function useSidebarShapeFormat(
|
|
|
447
725
|
const alpha = val / 100
|
|
448
726
|
el.opacity = alpha
|
|
449
727
|
el.style.opacity = alpha
|
|
450
|
-
const hex = fillHex.value
|
|
451
|
-
|
|
728
|
+
const hex = (fillHex.value && fillHex.value !== 'transparent') ? fillHex.value : '#3b82f6'
|
|
729
|
+
const rgba = hexToRgba(hex, val)
|
|
730
|
+
styleFill.value = rgba
|
|
731
|
+
el.fill = rgba
|
|
732
|
+
if (el.style) el.style.fill = rgba
|
|
452
733
|
}
|
|
453
734
|
addHistorySnapshot()
|
|
454
735
|
}
|
|
@@ -462,8 +743,16 @@ export function useSidebarShapeFormat(
|
|
|
462
743
|
const gradientStartHex = computed<string>({
|
|
463
744
|
get() {
|
|
464
745
|
if (!selectedElement.value) return '#3b82f6'
|
|
465
|
-
const g = getStandardGradientConfig(selectedElement.value)
|
|
466
|
-
|
|
746
|
+
const g = getStandardGradientConfig(selectedElement.value) || selectedElement.value._lastGradient
|
|
747
|
+
if (g?.colors?.[0]?.color) {
|
|
748
|
+
return parseColor(g.colors[0].color).hex
|
|
749
|
+
}
|
|
750
|
+
const solid = selectedElement.value._lastSolidFill || styleFill.value || selectedElement.value.fill
|
|
751
|
+
if (solid && solid !== 'none' && solid !== 'transparent') {
|
|
752
|
+
const parsed = parseColor(solid)
|
|
753
|
+
if (parsed.hex && parsed.hex !== 'transparent') return parsed.hex
|
|
754
|
+
}
|
|
755
|
+
return '#3b82f6'
|
|
467
756
|
},
|
|
468
757
|
set(val: string) {
|
|
469
758
|
updateGradientConfig({ startColor: val })
|
|
@@ -473,9 +762,13 @@ export function useSidebarShapeFormat(
|
|
|
473
762
|
const gradientEndHex = computed<string>({
|
|
474
763
|
get() {
|
|
475
764
|
if (!selectedElement.value) return '#60a5fa'
|
|
476
|
-
const g = getStandardGradientConfig(selectedElement.value)
|
|
765
|
+
const g = getStandardGradientConfig(selectedElement.value) || selectedElement.value._lastGradient
|
|
477
766
|
const colors = g?.colors || []
|
|
478
|
-
|
|
767
|
+
if (colors.length > 0 && colors[colors.length - 1]?.color) {
|
|
768
|
+
return parseColor(colors[colors.length - 1].color).hex
|
|
769
|
+
}
|
|
770
|
+
const start = gradientStartHex.value
|
|
771
|
+
return generateGradientEndColor(start)
|
|
479
772
|
},
|
|
480
773
|
set(val: string) {
|
|
481
774
|
updateGradientConfig({ endColor: val })
|
|
@@ -542,12 +835,13 @@ export function useSidebarShapeFormat(
|
|
|
542
835
|
directionName?: string
|
|
543
836
|
center?: { x: number; y: number }
|
|
544
837
|
fillToRect?: { l: number; t: number; r: number; b: number }
|
|
838
|
+
colors?: any[]
|
|
545
839
|
}) {
|
|
546
840
|
if (!selectedElement.value) return
|
|
547
841
|
const el = selectedElement.value
|
|
548
|
-
const existingG = getStandardGradientConfig(el)
|
|
842
|
+
const existingG = getStandardGradientConfig(el) || el._lastGradient
|
|
549
843
|
const curStart = opt.startColor !== undefined ? opt.startColor : gradientStartHex.value
|
|
550
|
-
const curEnd = opt.endColor !== undefined ? opt.endColor : gradientEndHex.value
|
|
844
|
+
const curEnd = opt.endColor !== undefined ? opt.endColor : (opt.startColor !== undefined ? generateGradientEndColor(opt.startColor) : gradientEndHex.value)
|
|
551
845
|
const curPath = opt.path !== undefined ? opt.path : gradientPathType.value
|
|
552
846
|
const curRot = opt.rot !== undefined ? opt.rot : (existingG?.rot !== undefined ? existingG.rot : gradientAngle.value)
|
|
553
847
|
|
|
@@ -575,10 +869,29 @@ export function useSidebarShapeFormat(
|
|
|
575
869
|
curDirName = '沿路径'
|
|
576
870
|
}
|
|
577
871
|
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
872
|
+
let colors: any[] = []
|
|
873
|
+
if (opt.colors && Array.isArray(opt.colors) && opt.colors.length > 0) {
|
|
874
|
+
colors = opt.colors
|
|
875
|
+
} else if (existingG?.colors && Array.isArray(existingG.colors) && existingG.colors.length >= 2) {
|
|
876
|
+
if (opt.startColor !== undefined || opt.endColor !== undefined) {
|
|
877
|
+
colors = existingG.colors.map((c: any, idx: number) => {
|
|
878
|
+
if (idx === 0 && opt.startColor !== undefined) {
|
|
879
|
+
return { ...c, color: opt.startColor }
|
|
880
|
+
}
|
|
881
|
+
if (idx === existingG.colors.length - 1 && opt.endColor !== undefined) {
|
|
882
|
+
return { ...c, color: opt.endColor }
|
|
883
|
+
}
|
|
884
|
+
return { ...c }
|
|
885
|
+
})
|
|
886
|
+
} else {
|
|
887
|
+
colors = existingG.colors
|
|
888
|
+
}
|
|
889
|
+
} else {
|
|
890
|
+
colors = [
|
|
891
|
+
{ color: curStart, pos: '0%' },
|
|
892
|
+
{ color: curEnd, pos: '100%' }
|
|
893
|
+
]
|
|
894
|
+
}
|
|
582
895
|
|
|
583
896
|
const normalized = normalizeGradientConfig({
|
|
584
897
|
type: curPath === 'line' ? 'linear' : (curPath === 'circle' ? 'radial' : (curPath === 'rect' ? 'rect' : 'path')),
|
|
@@ -593,18 +906,21 @@ export function useSidebarShapeFormat(
|
|
|
593
906
|
colors: colors
|
|
594
907
|
})
|
|
595
908
|
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
909
|
+
const elements = getFormattingElements()
|
|
910
|
+
elements.forEach((targetEl: any) => {
|
|
911
|
+
targetEl.fill = {
|
|
912
|
+
type: 'gradient',
|
|
913
|
+
value: normalized
|
|
914
|
+
}
|
|
915
|
+
targetEl.gradient = normalized
|
|
916
|
+
targetEl._lastGradient = normalized
|
|
602
917
|
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
918
|
+
if (targetEl.style) {
|
|
919
|
+
delete targetEl.style.pattern
|
|
920
|
+
targetEl.style.fill = 'none'
|
|
921
|
+
}
|
|
922
|
+
delete targetEl.pattern
|
|
923
|
+
})
|
|
608
924
|
addHistorySnapshot()
|
|
609
925
|
}
|
|
610
926
|
|
|
@@ -632,6 +948,7 @@ export function useSidebarShapeFormat(
|
|
|
632
948
|
value: normalized
|
|
633
949
|
}
|
|
634
950
|
targetEl.gradient = normalized
|
|
951
|
+
targetEl._lastGradient = normalized
|
|
635
952
|
|
|
636
953
|
if (targetEl.style) {
|
|
637
954
|
delete targetEl.style.pattern
|
|
@@ -646,9 +963,125 @@ export function useSidebarShapeFormat(
|
|
|
646
963
|
}
|
|
647
964
|
}
|
|
648
965
|
|
|
649
|
-
const shapePatternFill = computed(
|
|
650
|
-
|
|
651
|
-
|
|
966
|
+
const shapePatternFill = computed({
|
|
967
|
+
get() {
|
|
968
|
+
if (!selectedElement.value) return ''
|
|
969
|
+
return selectedElement.value.pattern || selectedElement.value.style?.pattern || ''
|
|
970
|
+
},
|
|
971
|
+
set(val: string) {
|
|
972
|
+
if (!selectedElement.value) return
|
|
973
|
+
const elements = getFormattingElements()
|
|
974
|
+
const meta = parsePatternSvgMeta(val)
|
|
975
|
+
elements.forEach((el: any) => {
|
|
976
|
+
if (!el.style) el.style = {}
|
|
977
|
+
if (meta.type) {
|
|
978
|
+
el.patternType = meta.type
|
|
979
|
+
el.style.patternType = meta.type
|
|
980
|
+
}
|
|
981
|
+
if (meta.fg) {
|
|
982
|
+
el.patternFg = meta.fg
|
|
983
|
+
el.style.patternFg = meta.fg
|
|
984
|
+
}
|
|
985
|
+
if (meta.bg) {
|
|
986
|
+
el.patternBg = meta.bg
|
|
987
|
+
el.style.patternBg = meta.bg
|
|
988
|
+
}
|
|
989
|
+
el.pattern = val
|
|
990
|
+
el.style.pattern = val
|
|
991
|
+
el.style.fill = 'none'
|
|
992
|
+
})
|
|
993
|
+
addHistorySnapshot()
|
|
994
|
+
}
|
|
995
|
+
})
|
|
996
|
+
|
|
997
|
+
const shapePatternType = computed({
|
|
998
|
+
get() {
|
|
999
|
+
if (!selectedElement.value) return 'diag-up'
|
|
1000
|
+
const el = selectedElement.value
|
|
1001
|
+
if (el.patternType || el.style?.patternType) return el.patternType || el.style.patternType
|
|
1002
|
+
const meta = parsePatternSvgMeta(el.pattern || el.style?.pattern)
|
|
1003
|
+
return meta.type || 'diag-up'
|
|
1004
|
+
},
|
|
1005
|
+
set(val: string) {
|
|
1006
|
+
if (!selectedElement.value) return
|
|
1007
|
+
const elements = getFormattingElements()
|
|
1008
|
+
const fg = shapePatternFg.value || '#3B82F6'
|
|
1009
|
+
const bg = shapePatternBg.value || '#FFFFFF'
|
|
1010
|
+
const url = buildPatternSvgDataUrl(val, fg, bg)
|
|
1011
|
+
elements.forEach((el: any) => {
|
|
1012
|
+
if (!el.style) el.style = {}
|
|
1013
|
+
el.patternType = val
|
|
1014
|
+
el.style.patternType = val
|
|
1015
|
+
el.patternFg = fg
|
|
1016
|
+
el.style.patternFg = fg
|
|
1017
|
+
el.patternBg = bg
|
|
1018
|
+
el.style.patternBg = bg
|
|
1019
|
+
el.pattern = url
|
|
1020
|
+
el.style.pattern = url
|
|
1021
|
+
el.style.fill = 'none'
|
|
1022
|
+
})
|
|
1023
|
+
addHistorySnapshot()
|
|
1024
|
+
}
|
|
1025
|
+
})
|
|
1026
|
+
|
|
1027
|
+
const shapePatternFg = computed({
|
|
1028
|
+
get() {
|
|
1029
|
+
if (!selectedElement.value) return '#3B82F6'
|
|
1030
|
+
const el = selectedElement.value
|
|
1031
|
+
if (el.patternFg || el.style?.patternFg) return el.patternFg || el.style.patternFg
|
|
1032
|
+
const meta = parsePatternSvgMeta(el.pattern || el.style?.pattern)
|
|
1033
|
+
return meta.fg || '#3B82F6'
|
|
1034
|
+
},
|
|
1035
|
+
set(val: string) {
|
|
1036
|
+
if (!selectedElement.value) return
|
|
1037
|
+
const elements = getFormattingElements()
|
|
1038
|
+
const pType = shapePatternType.value || 'diag-up'
|
|
1039
|
+
const bg = shapePatternBg.value || '#FFFFFF'
|
|
1040
|
+
const url = buildPatternSvgDataUrl(pType, val, bg)
|
|
1041
|
+
elements.forEach((el: any) => {
|
|
1042
|
+
if (!el.style) el.style = {}
|
|
1043
|
+
el.patternType = pType
|
|
1044
|
+
el.style.patternType = pType
|
|
1045
|
+
el.patternFg = val
|
|
1046
|
+
el.style.patternFg = val
|
|
1047
|
+
el.patternBg = bg
|
|
1048
|
+
el.style.patternBg = bg
|
|
1049
|
+
el.pattern = url
|
|
1050
|
+
el.style.pattern = url
|
|
1051
|
+
el.style.fill = 'none'
|
|
1052
|
+
})
|
|
1053
|
+
addHistorySnapshot()
|
|
1054
|
+
}
|
|
1055
|
+
})
|
|
1056
|
+
|
|
1057
|
+
const shapePatternBg = computed({
|
|
1058
|
+
get() {
|
|
1059
|
+
if (!selectedElement.value) return '#FFFFFF'
|
|
1060
|
+
const el = selectedElement.value
|
|
1061
|
+
if (el.patternBg || el.style?.patternBg) return el.patternBg || el.style.patternBg
|
|
1062
|
+
const meta = parsePatternSvgMeta(el.pattern || el.style?.pattern)
|
|
1063
|
+
return meta.bg || '#FFFFFF'
|
|
1064
|
+
},
|
|
1065
|
+
set(val: string) {
|
|
1066
|
+
if (!selectedElement.value) return
|
|
1067
|
+
const elements = getFormattingElements()
|
|
1068
|
+
const pType = shapePatternType.value || 'diag-up'
|
|
1069
|
+
const fg = shapePatternFg.value || '#3B82F6'
|
|
1070
|
+
const url = buildPatternSvgDataUrl(pType, fg, val)
|
|
1071
|
+
elements.forEach((el: any) => {
|
|
1072
|
+
if (!el.style) el.style = {}
|
|
1073
|
+
el.patternType = pType
|
|
1074
|
+
el.style.patternType = pType
|
|
1075
|
+
el.patternFg = fg
|
|
1076
|
+
el.style.patternFg = fg
|
|
1077
|
+
el.patternBg = val
|
|
1078
|
+
el.style.patternBg = val
|
|
1079
|
+
el.pattern = url
|
|
1080
|
+
el.style.pattern = url
|
|
1081
|
+
el.style.fill = 'none'
|
|
1082
|
+
})
|
|
1083
|
+
addHistorySnapshot()
|
|
1084
|
+
}
|
|
652
1085
|
})
|
|
653
1086
|
|
|
654
1087
|
function handleShapePatternUpload(e: Event) {
|
|
@@ -661,6 +1094,7 @@ export function useSidebarShapeFormat(
|
|
|
661
1094
|
if (!selectedElement.value.style) selectedElement.value.style = {}
|
|
662
1095
|
selectedElement.value.pattern = dataUrl
|
|
663
1096
|
selectedElement.value.style.pattern = dataUrl
|
|
1097
|
+
selectedElement.value.style.fill = 'none'
|
|
664
1098
|
addHistorySnapshot()
|
|
665
1099
|
notify('已设置形状图片填充')
|
|
666
1100
|
}
|
|
@@ -670,9 +1104,10 @@ export function useSidebarShapeFormat(
|
|
|
670
1104
|
|
|
671
1105
|
function clearShapePatternFill() {
|
|
672
1106
|
if (selectedElement.value) {
|
|
673
|
-
|
|
1107
|
+
selectedElement.value.pattern = ''
|
|
674
1108
|
if (selectedElement.value.style) {
|
|
675
|
-
|
|
1109
|
+
selectedElement.value.style.pattern = ''
|
|
1110
|
+
selectedElement.value.style.fill = 'none'
|
|
676
1111
|
}
|
|
677
1112
|
addHistorySnapshot()
|
|
678
1113
|
notify('已清除图片填充')
|
|
@@ -802,11 +1237,18 @@ export function useSidebarShapeFormat(
|
|
|
802
1237
|
set(val: string) {
|
|
803
1238
|
if (isMultiOrGroup()) {
|
|
804
1239
|
const elements = getFormattingElements().filter((el: any) => el.type !== 'line')
|
|
1240
|
+
const parsed = parseColor(val)
|
|
805
1241
|
elements.forEach((el: any) => {
|
|
806
1242
|
if (!el.style) el.style = {}
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
1243
|
+
if (val === 'transparent' || val === 'none') {
|
|
1244
|
+
el.style.borderColor = 'transparent'
|
|
1245
|
+
} else {
|
|
1246
|
+
const currentBorder = el.style.borderColor || '#363B4C'
|
|
1247
|
+
let currentAlpha = parseColor(currentBorder).alpha
|
|
1248
|
+
if (currentAlpha === 0 || currentAlpha === undefined) currentAlpha = 100
|
|
1249
|
+
const alphaToUse = (parsed.alpha !== undefined && parsed.alpha < 100) ? parsed.alpha : currentAlpha
|
|
1250
|
+
el.style.borderColor = hexToRgba(parsed.hex, alphaToUse)
|
|
1251
|
+
}
|
|
810
1252
|
})
|
|
811
1253
|
if (selectedElement.value?.type === 'group') {
|
|
812
1254
|
if (!selectedElement.value.style) selectedElement.value.style = {}
|
|
@@ -814,8 +1256,17 @@ export function useSidebarShapeFormat(
|
|
|
814
1256
|
}
|
|
815
1257
|
} else {
|
|
816
1258
|
if (!selectedElement.value) return
|
|
817
|
-
|
|
818
|
-
|
|
1259
|
+
if (val === 'transparent' || val === 'none') {
|
|
1260
|
+
getStyle().borderColor = 'transparent'
|
|
1261
|
+
} else {
|
|
1262
|
+
const parsed = parseColor(val)
|
|
1263
|
+
let alpha = borderAlpha.value
|
|
1264
|
+
if (alpha === 0 || alpha === undefined) alpha = 100
|
|
1265
|
+
if (parsed.alpha !== undefined && parsed.alpha < 100) {
|
|
1266
|
+
alpha = parsed.alpha
|
|
1267
|
+
}
|
|
1268
|
+
getStyle().borderColor = hexToRgba(parsed.hex, alpha)
|
|
1269
|
+
}
|
|
819
1270
|
}
|
|
820
1271
|
addHistorySnapshot()
|
|
821
1272
|
}
|
|
@@ -828,8 +1279,9 @@ export function useSidebarShapeFormat(
|
|
|
828
1279
|
},
|
|
829
1280
|
set(val: number) {
|
|
830
1281
|
if (!selectedElement.value) return
|
|
831
|
-
const hex = borderHex.value
|
|
1282
|
+
const hex = (borderHex.value && borderHex.value !== 'transparent') ? borderHex.value : '#363B4C'
|
|
832
1283
|
getStyle().borderColor = hexToRgba(hex, val)
|
|
1284
|
+
addHistorySnapshot()
|
|
833
1285
|
}
|
|
834
1286
|
})
|
|
835
1287
|
|
|
@@ -1305,6 +1757,9 @@ export function useSidebarShapeFormat(
|
|
|
1305
1757
|
updateGradientConfig,
|
|
1306
1758
|
updateElementGradient,
|
|
1307
1759
|
shapePatternFill,
|
|
1760
|
+
shapePatternType,
|
|
1761
|
+
shapePatternFg,
|
|
1762
|
+
shapePatternBg,
|
|
1308
1763
|
handleShapePatternUpload,
|
|
1309
1764
|
clearShapePatternFill,
|
|
1310
1765
|
styleBorderStyle,
|