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
|
@@ -101,7 +101,8 @@ const effectiveMasterElements = computed(() => {
|
|
|
101
101
|
if (isMasterEditingView?.value) {
|
|
102
102
|
if (activeLayoutId?.value) {
|
|
103
103
|
const master = slideMasters?.value?.find((m: any) => m.id === activeMasterId.value) || slideMasters?.value?.[0]
|
|
104
|
-
|
|
104
|
+
const layoutElIds = new Set((activeSlide?.value?.elements || []).map((e: any) => e.id))
|
|
105
|
+
return (master?.elements || []).filter((el: any) => !isPlaceholderElement(el) && !layoutElIds.has(el.id))
|
|
105
106
|
}
|
|
106
107
|
return []
|
|
107
108
|
}
|
|
@@ -818,7 +819,8 @@ const {
|
|
|
818
819
|
updateLineGeometry(el, start, end, absControls, allElements, parentGroupDim)
|
|
819
820
|
},
|
|
820
821
|
selectedElementWidth,
|
|
821
|
-
selectedElementHeight
|
|
822
|
+
selectedElementHeight,
|
|
823
|
+
activeSlideVersion
|
|
822
824
|
})
|
|
823
825
|
|
|
824
826
|
const isInteracting = computed(() => {
|
|
@@ -1026,9 +1028,6 @@ const getOverlayHeight = (el: any) => {
|
|
|
1026
1028
|
if (isDragging.value && el?.id && activeDragDimensions.has(el.id)) {
|
|
1027
1029
|
return `${activeDragDimensions.get(el.id)!.height}px`
|
|
1028
1030
|
}
|
|
1029
|
-
if (el.id === selectedElementId.value && !isResizing.value && selectedElementHeight.value && selectedElementHeight.value !== '0px') {
|
|
1030
|
-
return selectedElementHeight.value
|
|
1031
|
-
}
|
|
1032
1031
|
// For table elements: check DOM rendered table height if available
|
|
1033
1032
|
if (el.type === 'text' && el.content?.includes('<table') && !isDragging.value) {
|
|
1034
1033
|
const container = document.getElementById(`editable-${el.id}`) || document.getElementById(`canvas-el-${el.id}`)
|
|
@@ -1185,6 +1184,29 @@ const getFloatingQuickToolbarStyle = (el: any) => {
|
|
|
1185
1184
|
|
|
1186
1185
|
let selectedElementResizeObserver: ResizeObserver | null = null
|
|
1187
1186
|
|
|
1187
|
+
function syncSelectedElementDimensionsFromDom(id: string | null) {
|
|
1188
|
+
if (!id) {
|
|
1189
|
+
selectedElementWidth.value = '0px'
|
|
1190
|
+
selectedElementHeight.value = '0px'
|
|
1191
|
+
return null
|
|
1192
|
+
}
|
|
1193
|
+
const dom = document.getElementById(`canvas-el-${id}`)
|
|
1194
|
+
if (!dom) {
|
|
1195
|
+
selectedElementWidth.value = '0px'
|
|
1196
|
+
selectedElementHeight.value = '0px'
|
|
1197
|
+
return null
|
|
1198
|
+
}
|
|
1199
|
+
const tableEl = dom.querySelector('table')
|
|
1200
|
+
const editableDom = document.getElementById(`editable-${id}`)
|
|
1201
|
+
const selEl = activeSlide.value?.elements.find((x: any) => x.id === id)
|
|
1202
|
+
const isVertical = selEl && (selEl.style?.writingMode === 'vertical-rl' || selEl.style?.writingMode === 'vertical-lr')
|
|
1203
|
+
const initialW = isVertical && editableDom ? Math.max(editableDom.scrollWidth, dom.offsetWidth) : dom.offsetWidth
|
|
1204
|
+
const initialH = dom.offsetHeight > 0 ? dom.offsetHeight : (tableEl && tableEl.offsetHeight > 0 ? tableEl.offsetHeight : 0)
|
|
1205
|
+
selectedElementWidth.value = `${initialW}px`
|
|
1206
|
+
selectedElementHeight.value = `${initialH}px`
|
|
1207
|
+
return { dom, tableEl, editableDom, isVertical }
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1188
1210
|
function observeSelectedElement() {
|
|
1189
1211
|
if (selectedElementResizeObserver) {
|
|
1190
1212
|
selectedElementResizeObserver.disconnect()
|
|
@@ -1197,6 +1219,9 @@ function observeSelectedElement() {
|
|
|
1197
1219
|
return
|
|
1198
1220
|
}
|
|
1199
1221
|
|
|
1222
|
+
// 同步测量一次:若 DOM 已存在(如未选中状态下直接按住拖拽选中),立即更新尺寸,避免 0px 或残留上一个选中元素的尺寸
|
|
1223
|
+
syncSelectedElementDimensionsFromDom(selectedElementId.value)
|
|
1224
|
+
|
|
1200
1225
|
nextTick(() => {
|
|
1201
1226
|
const dom = document.getElementById(`canvas-el-${selectedElementId.value}`)
|
|
1202
1227
|
if (dom) {
|
|
@@ -2167,9 +2192,14 @@ function isPlaceholderElement(el: any): boolean {
|
|
|
2167
2192
|
const isMarkedAsPlaceholder = Boolean(
|
|
2168
2193
|
el.isPlaceholder ||
|
|
2169
2194
|
el.placeholder ||
|
|
2170
|
-
(el.id && typeof el.id === 'string' && el.id.startsWith('ph-')) ||
|
|
2195
|
+
(el.id && typeof el.id === 'string' && (el.id.startsWith('ph-') || el.id.startsWith('ph_'))) ||
|
|
2171
2196
|
(el.name && typeof el.name === 'string' && el.name.includes('占位符'))
|
|
2172
2197
|
)
|
|
2198
|
+
if (isMarkedAsPlaceholder) {
|
|
2199
|
+
if (isMasterEditingView?.value || el.isPlaceholder || el.placeholder || (el.id && (el.id.startsWith('ph-') || el.id.startsWith('ph_')))) {
|
|
2200
|
+
return true
|
|
2201
|
+
}
|
|
2202
|
+
}
|
|
2173
2203
|
if (el.type === 'text') {
|
|
2174
2204
|
const text = (el.content || '').replace(/<[^>]*>/g, '').replace(/ /g, ' ').trim()
|
|
2175
2205
|
if (!text) {
|
|
@@ -2212,6 +2242,7 @@ function isPlaceholderElement(el: any): boolean {
|
|
|
2212
2242
|
'编辑文本样式',
|
|
2213
2243
|
'页脚 / 日期文本',
|
|
2214
2244
|
'页脚占位符',
|
|
2245
|
+
'页脚区',
|
|
2215
2246
|
'页码占位符',
|
|
2216
2247
|
'日期占位符',
|
|
2217
2248
|
'<#>',
|
|
@@ -2485,8 +2516,10 @@ function handleCanvasDblClick(e: MouseEvent) {
|
|
|
2485
2516
|
const pctY = (localY / logicalHeight.value) * 100
|
|
2486
2517
|
|
|
2487
2518
|
const recipe = getActiveSlideThemeRecipe(activeSlide.value)
|
|
2488
|
-
const textColor = recipe.textStyles?.title?.color || recipe.styleColors?.[0] ||
|
|
2489
|
-
const textFont =
|
|
2519
|
+
const textColor = globalFontColor.value || recipe.textStyles?.title?.color || recipe.styleColors?.[0] || recipe.textStyles?.normalText?.color || '#0f172a'
|
|
2520
|
+
const textFont = (globalFontFamily.value && globalFontFamily.value !== '默认字体')
|
|
2521
|
+
? globalFontFamily.value
|
|
2522
|
+
: (recipe.styleFonts?.bodyFont || recipe.styleFonts?.titleFont || 'SourceHanSansCN')
|
|
2490
2523
|
|
|
2491
2524
|
const newTextEl = {
|
|
2492
2525
|
id: 'text-' + Date.now().toString() + Math.random().toString(36).substring(2, 7),
|
|
@@ -2682,10 +2715,12 @@ function handleCanvasMouseDown(e: MouseEvent) {
|
|
|
2682
2715
|
const typeConf = TEXT_TYPE_CONFIGS[textType] || TEXT_TYPE_CONFIGS.normalText
|
|
2683
2716
|
const textCfg = recipe.textStyles?.[textType] || defaultStyleRecipe.textStyles[textType] || defaultStyleRecipe.textStyles.normalText
|
|
2684
2717
|
const isHeading = textType === 'title' || textType === 'headline'
|
|
2685
|
-
const textFont =
|
|
2686
|
-
?
|
|
2687
|
-
: (
|
|
2688
|
-
|
|
2718
|
+
const textFont = (globalFontFamily.value && globalFontFamily.value !== '默认字体')
|
|
2719
|
+
? globalFontFamily.value
|
|
2720
|
+
: (textCfg.fontFamily || (isHeading
|
|
2721
|
+
? (recipe.styleFonts?.titleFont && recipe.styleFonts.titleFont !== '默认字体' ? recipe.styleFonts.titleFont : 'SourceHanSansCN')
|
|
2722
|
+
: (recipe.styleFonts?.bodyFont && recipe.styleFonts.bodyFont !== '默认字体' ? recipe.styleFonts.bodyFont : 'SourceHanSansCN')))
|
|
2723
|
+
const textColor = globalFontColor.value || textCfg.color || (textType === 'smallText' ? '#64748b' : (isHeading ? (recipe.textStyles?.title?.color || '#0f172a') : (recipe.textStyles?.normalText?.color || '#334155')))
|
|
2689
2724
|
const fontSize = `${textCfg.fontSize || typeConf.defaultFontSize}px`
|
|
2690
2725
|
const fontWeight = textCfg.fontWeight || typeConf.defaultFontWeight
|
|
2691
2726
|
const lineHeight = textCfg.lineHeight || typeConf.defaultLineHeight
|
|
@@ -2729,10 +2764,12 @@ function handleCanvasMouseDown(e: MouseEvent) {
|
|
|
2729
2764
|
const typeConf = TEXT_TYPE_CONFIGS[textType] || TEXT_TYPE_CONFIGS.normalText
|
|
2730
2765
|
const textCfg = recipe.textStyles?.[textType] || defaultStyleRecipe.textStyles[textType] || defaultStyleRecipe.textStyles.normalText
|
|
2731
2766
|
const isHeading = textType === 'title' || textType === 'headline'
|
|
2732
|
-
const textFont =
|
|
2733
|
-
?
|
|
2734
|
-
: (
|
|
2735
|
-
|
|
2767
|
+
const textFont = (globalFontFamily.value && globalFontFamily.value !== '默认字体')
|
|
2768
|
+
? globalFontFamily.value
|
|
2769
|
+
: (textCfg.fontFamily || (isHeading
|
|
2770
|
+
? (recipe.styleFonts?.titleFont && recipe.styleFonts.titleFont !== '默认字体' ? recipe.styleFonts.titleFont : 'SourceHanSansCN')
|
|
2771
|
+
: (recipe.styleFonts?.bodyFont && recipe.styleFonts.bodyFont !== '默认字体' ? recipe.styleFonts.bodyFont : 'SourceHanSansCN')))
|
|
2772
|
+
const textColor = globalFontColor.value || textCfg.color || (textType === 'smallText' ? '#64748b' : (isHeading ? (recipe.textStyles?.title?.color || '#0f172a') : (recipe.textStyles?.normalText?.color || '#334155')))
|
|
2736
2773
|
const fontSize = `${textCfg.fontSize || typeConf.defaultFontSize}px`
|
|
2737
2774
|
const fontWeight = textCfg.fontWeight || typeConf.defaultFontWeight
|
|
2738
2775
|
const lineHeight = textCfg.lineHeight || typeConf.defaultLineHeight
|
|
@@ -2775,9 +2812,11 @@ function handleCanvasMouseDown(e: MouseEvent) {
|
|
|
2775
2812
|
const shapeFill = recipe.shape?.fillColor || (recipe.styleColors && recipe.styleColors[0]) || '#2563eb'
|
|
2776
2813
|
const shapeBorder = recipe.shape?.borderColor || (recipe.styleColors && recipe.styleColors[1]) || '#1d4ed8'
|
|
2777
2814
|
const shapeTextCol = recipe.shape?.textColor || '#ffffff'
|
|
2778
|
-
const shapeFont = (
|
|
2779
|
-
?
|
|
2780
|
-
: '
|
|
2815
|
+
const shapeFont = (globalFontFamily.value && globalFontFamily.value !== '默认字体')
|
|
2816
|
+
? globalFontFamily.value
|
|
2817
|
+
: ((recipe.styleFonts?.bodyFont && recipe.styleFonts.bodyFont !== '默认字体')
|
|
2818
|
+
? recipe.styleFonts.bodyFont
|
|
2819
|
+
: 'SourceHanSansCN')
|
|
2781
2820
|
|
|
2782
2821
|
style = {
|
|
2783
2822
|
top: `${creationStartPctY.toFixed(2)}%`,
|
|
@@ -2816,6 +2855,7 @@ function handleCanvasMouseDown(e: MouseEvent) {
|
|
|
2816
2855
|
borderWidth: '2px',
|
|
2817
2856
|
borderStyle: 'solid',
|
|
2818
2857
|
textColor: shapeTextCol,
|
|
2858
|
+
fontFamily: shapeFont,
|
|
2819
2859
|
viewBox: pendingShapeViewBox.value,
|
|
2820
2860
|
pathFormula,
|
|
2821
2861
|
keypoints
|
|
@@ -3579,10 +3619,14 @@ function handleElementMouseDown(e: MouseEvent, el: any) {
|
|
|
3579
3619
|
return
|
|
3580
3620
|
}
|
|
3581
3621
|
|
|
3582
|
-
//
|
|
3622
|
+
// 核心保护:若当前元素正在进行文字编辑,且鼠标按在实际文字字符上(或形状编辑区域内),放行浏览器原生光标定位与拖动划词选择;若按在文本框空白区域则允许拖动文本框
|
|
3583
3623
|
if (isEditingText.value && (selectedElementId.value === el.id || editingElementId.value === el.id)) {
|
|
3584
3624
|
const target = e.target as HTMLElement
|
|
3585
|
-
if (
|
|
3625
|
+
if (el.type === 'text' && !el.latex && !el.content?.includes('<table')) {
|
|
3626
|
+
if (isClickOnTextCharacters(e, `editable-${el.id}`)) {
|
|
3627
|
+
return
|
|
3628
|
+
}
|
|
3629
|
+
} else if (target && (target.closest(`[id^="editable-${el.id}"]`) || target.closest('.shape-text-overlay-wrapper') || el.type === 'shape')) {
|
|
3586
3630
|
return
|
|
3587
3631
|
}
|
|
3588
3632
|
}
|
|
@@ -3782,15 +3826,26 @@ function startChildDrag(e: MouseEvent, child: any, parentGroup: any) {
|
|
|
3782
3826
|
if (isReadonly.value) return
|
|
3783
3827
|
const childContainerEl = document.getElementById(`editable-${child.id}`)
|
|
3784
3828
|
const childCanvasElDom = document.getElementById(`canvas-el-${child.id}`)
|
|
3785
|
-
const isChildClickInside =
|
|
3786
|
-
|
|
3829
|
+
const isChildClickInside = child.type === 'text' && !child.latex && !child.content?.includes('<table')
|
|
3830
|
+
? isClickOnTextCharacters(e, `editable-${child.id}`)
|
|
3831
|
+
: ((childContainerEl && (childContainerEl === e.target || childContainerEl.contains(e.target as Node))) ||
|
|
3832
|
+
(childCanvasElDom && (childCanvasElDom === e.target || childCanvasElDom.contains(e.target as Node))))
|
|
3787
3833
|
|
|
3788
3834
|
if (isEditingText.value && selectedElementId.value === child.id && isChildClickInside) {
|
|
3789
3835
|
return
|
|
3790
3836
|
}
|
|
3791
3837
|
|
|
3838
|
+
if (child.type === 'text' && !child.latex && !child.content?.includes('<table') && isChildClickInside && !e.ctrlKey && !e.shiftKey) {
|
|
3839
|
+
selectedElementId.value = child.id
|
|
3840
|
+
selectedElementIds.value = [child.id]
|
|
3841
|
+
if (!isEditingText.value) {
|
|
3842
|
+
startEditingTextElement(child.id, e)
|
|
3843
|
+
}
|
|
3844
|
+
return
|
|
3845
|
+
}
|
|
3846
|
+
|
|
3792
3847
|
if (isEditingText.value && !isChildClickInside) {
|
|
3793
|
-
checkAndExitEditText(
|
|
3848
|
+
checkAndExitEditText(child, true)
|
|
3794
3849
|
}
|
|
3795
3850
|
e.preventDefault()
|
|
3796
3851
|
pauseHistory.value = true
|
|
@@ -3982,15 +4037,17 @@ function handleChildMouseDown(e: MouseEvent, child: any, parentGroup: any) {
|
|
|
3982
4037
|
if (activeTool.value) return
|
|
3983
4038
|
const childContainerEl = document.getElementById(`editable-${child.id}`)
|
|
3984
4039
|
const childCanvasElDom = document.getElementById(`canvas-el-${child.id}`)
|
|
3985
|
-
const isChildClickInside =
|
|
3986
|
-
|
|
4040
|
+
const isChildClickInside = child.type === 'text' && !child.latex && !child.content?.includes('<table')
|
|
4041
|
+
? isClickOnTextCharacters(e, `editable-${child.id}`)
|
|
4042
|
+
: ((childContainerEl && (childContainerEl === e.target || childContainerEl.contains(e.target as Node))) ||
|
|
4043
|
+
(childCanvasElDom && (childCanvasElDom === e.target || childCanvasElDom.contains(e.target as Node))))
|
|
3987
4044
|
|
|
3988
4045
|
if (isEditingText.value && selectedElementId.value === child.id && isChildClickInside) {
|
|
3989
4046
|
return
|
|
3990
4047
|
}
|
|
3991
4048
|
|
|
3992
4049
|
if (isEditingText.value && !isChildClickInside) {
|
|
3993
|
-
checkAndExitEditText(
|
|
4050
|
+
checkAndExitEditText(child, true)
|
|
3994
4051
|
}
|
|
3995
4052
|
e.stopPropagation()
|
|
3996
4053
|
if (isReadonly.value) return
|
|
@@ -4087,6 +4144,9 @@ function handleChildClick(e: MouseEvent, child: any, parentGroup: any) {
|
|
|
4087
4144
|
} else {
|
|
4088
4145
|
selectedElementId.value = child.id
|
|
4089
4146
|
selectedElementIds.value = [child.id]
|
|
4147
|
+
if (child.type === 'text' && !child.content?.includes('<table') && !child.latex && isClickOnTextCharacters(e, `editable-${child.id}`)) {
|
|
4148
|
+
startEditingTextElement(child.id, e)
|
|
4149
|
+
}
|
|
4090
4150
|
}
|
|
4091
4151
|
}
|
|
4092
4152
|
}
|
|
@@ -4158,7 +4218,7 @@ function handleElementClick(e: MouseEvent, elId: string) {
|
|
|
4158
4218
|
selectElement(elId, e)
|
|
4159
4219
|
}
|
|
4160
4220
|
|
|
4161
|
-
// Check if they clicked the actual text content rather than
|
|
4221
|
+
// Check if they clicked the actual text content rather than blank areas or draggable border handles
|
|
4162
4222
|
const target = e.target as HTMLElement
|
|
4163
4223
|
const el = activeSlide.value?.elements.find((x: any) => x.id === elId)
|
|
4164
4224
|
if (el) {
|
|
@@ -4173,9 +4233,12 @@ function handleElementClick(e: MouseEvent, elId: string) {
|
|
|
4173
4233
|
const isEmptyText = !textVal
|
|
4174
4234
|
const isPlaceholder = isPlaceholderElement(el)
|
|
4175
4235
|
const isClickingTextContent = target && (
|
|
4176
|
-
|
|
4177
|
-
|
|
4178
|
-
|
|
4236
|
+
el.type === 'text'
|
|
4237
|
+
? (!target.closest('.text-edit-drag-helper') && isClickOnTextCharacters(e, `editable-${el.id}`))
|
|
4238
|
+
: (
|
|
4239
|
+
(target.closest('.shape-text-overlay') && (isEmptyText || isPlaceholder || isClickOnTextCharacters(e, `editable-${el.id}`))) ||
|
|
4240
|
+
(isPlaceholder && target.closest('.canvas-element') && !target.closest('.text-edit-drag-helper'))
|
|
4241
|
+
)
|
|
4179
4242
|
)
|
|
4180
4243
|
|
|
4181
4244
|
if (isClickingTextContent && (!isEditingText.value || selectedElementId.value !== el.id) && !e.ctrlKey && !e.shiftKey) {
|
|
@@ -4271,16 +4334,26 @@ function getElementWidthHeight(el: any): { width: number; height: number } {
|
|
|
4271
4334
|
// 关键:拖拽期间绝不查询 DOM,杜绝强制重排
|
|
4272
4335
|
const dom = isDragging.value ? null : (document.getElementById(`canvas-el-${el.id}`) || document.getElementById(`editable-${el.id}`))
|
|
4273
4336
|
|
|
4337
|
+
let usedSelectedWidth = false
|
|
4338
|
+
let usedSelectedHeight = false
|
|
4274
4339
|
if (el.id === selectedElementId.value && !isResizing.value && el.type !== 'group') {
|
|
4275
4340
|
if (selectedElementWidth.value && selectedElementWidth.value !== '0px') {
|
|
4276
4341
|
const parsedW = parseFloat(selectedElementWidth.value)
|
|
4277
|
-
if (!isNaN(parsedW) && parsedW > 0)
|
|
4342
|
+
if (!isNaN(parsedW) && parsedW > 0) {
|
|
4343
|
+
width = parsedW
|
|
4344
|
+
usedSelectedWidth = true
|
|
4345
|
+
}
|
|
4278
4346
|
}
|
|
4279
4347
|
if (selectedElementHeight.value && selectedElementHeight.value !== '0px') {
|
|
4280
4348
|
const parsedH = parseFloat(selectedElementHeight.value)
|
|
4281
|
-
if (!isNaN(parsedH) && parsedH > 0)
|
|
4349
|
+
if (!isNaN(parsedH) && parsedH > 0) {
|
|
4350
|
+
height = parsedH
|
|
4351
|
+
usedSelectedHeight = true
|
|
4352
|
+
}
|
|
4282
4353
|
}
|
|
4283
|
-
}
|
|
4354
|
+
}
|
|
4355
|
+
|
|
4356
|
+
if (!usedSelectedWidth) {
|
|
4284
4357
|
if (isWidthAuto && dom) {
|
|
4285
4358
|
const isVertical = el.type === 'text' && (el.style?.writingMode === 'vertical-rl' || el.style?.writingMode === 'vertical-lr')
|
|
4286
4359
|
const editableDom = document.getElementById(`editable-${el.id}`)
|
|
@@ -4292,7 +4365,9 @@ function getElementWidthHeight(el: any): { width: number; height: number } {
|
|
|
4292
4365
|
width = parseFloat(wStr) || 200
|
|
4293
4366
|
}
|
|
4294
4367
|
}
|
|
4368
|
+
}
|
|
4295
4369
|
|
|
4370
|
+
if (!usedSelectedHeight) {
|
|
4296
4371
|
if (isHeightAuto && dom) {
|
|
4297
4372
|
height = dom.offsetHeight
|
|
4298
4373
|
} else if (el.style?.height !== undefined && el.style.height !== 'auto') {
|
|
@@ -4304,6 +4379,8 @@ function getElementWidthHeight(el: any): { width: number; height: number } {
|
|
|
4304
4379
|
} else if (el.type === 'text') {
|
|
4305
4380
|
if (dom) {
|
|
4306
4381
|
height = dom.offsetHeight
|
|
4382
|
+
} else if (typeof el.height === 'number' && el.height > 0) {
|
|
4383
|
+
height = el.height
|
|
4307
4384
|
} else {
|
|
4308
4385
|
height = 40
|
|
4309
4386
|
}
|
|
@@ -4460,59 +4537,92 @@ function isClickOnTextCharacters(e: MouseEvent, containerId: string): boolean {
|
|
|
4460
4537
|
if (!container) return false
|
|
4461
4538
|
|
|
4462
4539
|
const target = e.target as HTMLElement
|
|
4463
|
-
if (target &&
|
|
4464
|
-
return
|
|
4540
|
+
if (target && target.closest('.text-edit-drag-helper')) {
|
|
4541
|
+
return false
|
|
4465
4542
|
}
|
|
4466
4543
|
|
|
4467
|
-
|
|
4468
|
-
|
|
4469
|
-
|
|
4470
|
-
|
|
4544
|
+
const x = e.clientX
|
|
4545
|
+
const y = e.clientY
|
|
4546
|
+
const tolerance = 2
|
|
4547
|
+
|
|
4548
|
+
const walker = document.createTreeWalker(container, NodeFilter.SHOW_TEXT, null)
|
|
4549
|
+
const range = document.createRange()
|
|
4550
|
+
let node: Node | null
|
|
4551
|
+
while ((node = walker.nextNode())) {
|
|
4552
|
+
const text = node.textContent || ''
|
|
4553
|
+
if (!text.replace(/[\r\n\u200B]/g, '').length) continue
|
|
4554
|
+
range.selectNodeContents(node)
|
|
4555
|
+
const rects = range.getClientRects()
|
|
4556
|
+
for (let i = 0; i < rects.length; i++) {
|
|
4557
|
+
const rect = rects[i]
|
|
4558
|
+
if (rect.width <= 0 || rect.height <= 0) continue
|
|
4559
|
+
if (
|
|
4560
|
+
x >= rect.left - tolerance &&
|
|
4561
|
+
x <= rect.right + tolerance &&
|
|
4562
|
+
y >= rect.top - tolerance &&
|
|
4563
|
+
y <= rect.bottom + tolerance
|
|
4564
|
+
) {
|
|
4471
4565
|
return true
|
|
4472
4566
|
}
|
|
4473
|
-
}
|
|
4567
|
+
}
|
|
4568
|
+
}
|
|
4569
|
+
|
|
4570
|
+
// 当处于文本编辑状态时,若存在空行(<br>),允许在空行光标位置附近点击定位,其余空白区域保持可拖拽
|
|
4571
|
+
if (isEditingText.value) {
|
|
4572
|
+
const brs = container.querySelectorAll('br')
|
|
4573
|
+
for (let i = 0; i < brs.length; i++) {
|
|
4574
|
+
const rect = brs[i].getBoundingClientRect()
|
|
4575
|
+
if (rect.height > 0 && y >= rect.top - tolerance && y <= rect.bottom + tolerance) {
|
|
4576
|
+
if (x >= rect.left - 4 && x <= rect.left + Math.max(rect.width, 8) + 4) {
|
|
4577
|
+
return true
|
|
4578
|
+
}
|
|
4579
|
+
}
|
|
4580
|
+
}
|
|
4474
4581
|
}
|
|
4475
4582
|
|
|
4476
4583
|
return false
|
|
4477
4584
|
}
|
|
4478
4585
|
|
|
4479
4586
|
function handleTextMouseMove(e: MouseEvent, el: any) {
|
|
4480
|
-
if (isDragging.value || isCanvasDragging.value) return
|
|
4587
|
+
if (isReadonly.value || isDragging.value || isCanvasDragging.value) return
|
|
4481
4588
|
if (el.latex || el.content?.includes('<table')) return
|
|
4482
4589
|
const containerId = `editable-${el.id}`
|
|
4483
4590
|
const container = document.getElementById(containerId)
|
|
4484
|
-
|
|
4485
|
-
if (container) {
|
|
4486
|
-
container.style.cursor = 'text'
|
|
4487
|
-
}
|
|
4488
|
-
return
|
|
4489
|
-
}
|
|
4591
|
+
const canvasElDom = document.getElementById(`canvas-el-${el.id}`)
|
|
4490
4592
|
if (!container) return
|
|
4491
4593
|
|
|
4492
|
-
|
|
4493
|
-
|
|
4494
|
-
|
|
4495
|
-
|
|
4496
|
-
|
|
4497
|
-
|
|
4498
|
-
|
|
4499
|
-
|
|
4500
|
-
|
|
4594
|
+
if (el.type === 'shape') {
|
|
4595
|
+
if (isEditingText.value && (selectedElementId.value === el.id || editingElementId?.value === el.id)) {
|
|
4596
|
+
container.style.cursor = 'text'
|
|
4597
|
+
return
|
|
4598
|
+
}
|
|
4599
|
+
const textVal = el.text ? String(el.text).replace(/<[^>]*>/g, '').trim() : ''
|
|
4600
|
+
const isEmptyText = !textVal
|
|
4601
|
+
const isPlaceholder = isPlaceholderElement(el)
|
|
4602
|
+
if (isEmptyText || isPlaceholder) {
|
|
4603
|
+
container.style.cursor = 'text'
|
|
4604
|
+
return
|
|
4605
|
+
}
|
|
4501
4606
|
}
|
|
4502
4607
|
|
|
4503
4608
|
const isOverText = isClickOnTextCharacters(e, containerId)
|
|
4504
|
-
|
|
4505
|
-
|
|
4506
|
-
|
|
4507
|
-
|
|
4609
|
+
const nextCursor = isOverText ? 'text' : 'move'
|
|
4610
|
+
container.style.cursor = nextCursor
|
|
4611
|
+
if (canvasElDom) {
|
|
4612
|
+
canvasElDom.style.cursor = nextCursor
|
|
4508
4613
|
}
|
|
4509
4614
|
}
|
|
4510
4615
|
|
|
4511
4616
|
function handleTextMouseLeave(_e: MouseEvent, el: any) {
|
|
4617
|
+
if (isReadonly.value) return
|
|
4512
4618
|
const container = document.getElementById(`editable-${el.id}`)
|
|
4513
|
-
|
|
4619
|
+
const canvasElDom = document.getElementById(`canvas-el-${el.id}`)
|
|
4620
|
+
if (container) {
|
|
4514
4621
|
container.style.cursor = 'move'
|
|
4515
4622
|
}
|
|
4623
|
+
if (canvasElDom) {
|
|
4624
|
+
canvasElDom.style.cursor = 'move'
|
|
4625
|
+
}
|
|
4516
4626
|
}
|
|
4517
4627
|
|
|
4518
4628
|
function startDrag(e: MouseEvent, el: any) {
|
|
@@ -4520,8 +4630,10 @@ function startDrag(e: MouseEvent, el: any) {
|
|
|
4520
4630
|
const target = e.target as HTMLElement
|
|
4521
4631
|
const container = document.getElementById(`editable-${el.id}`)
|
|
4522
4632
|
const canvasElDom = document.getElementById(`canvas-el-${el.id}`)
|
|
4523
|
-
const isInsideEditingContainer =
|
|
4524
|
-
|
|
4633
|
+
const isInsideEditingContainer = el.type === 'text' && !el.latex && !el.content?.includes('<table')
|
|
4634
|
+
? isClickOnTextCharacters(e, `editable-${el.id}`)
|
|
4635
|
+
: ((container && (container === target || container.contains(target))) ||
|
|
4636
|
+
(canvasElDom && (canvasElDom === target || canvasElDom.contains(target))))
|
|
4525
4637
|
if (isEditingText.value && selectedElementId.value === el.id && isInsideEditingContainer) {
|
|
4526
4638
|
return
|
|
4527
4639
|
}
|
|
@@ -4532,11 +4644,14 @@ function startDrag(e: MouseEvent, el: any) {
|
|
|
4532
4644
|
const isEmptyText = !textVal
|
|
4533
4645
|
const isPlaceholder = isPlaceholderElement(el)
|
|
4534
4646
|
|
|
4535
|
-
// Check if they clicked inside the actual text characters
|
|
4647
|
+
// Check if they clicked inside the actual text characters
|
|
4536
4648
|
const isClickingTextContent = target && (
|
|
4537
|
-
|
|
4538
|
-
|
|
4539
|
-
|
|
4649
|
+
el.type === 'text'
|
|
4650
|
+
? (!target.closest('.text-edit-drag-helper') && isClickOnTextCharacters(e, `editable-${el.id}`))
|
|
4651
|
+
: (
|
|
4652
|
+
(target.closest('.shape-text-overlay') && (isEmptyText || isPlaceholder || isClickOnTextCharacters(e, `editable-${el.id}`))) ||
|
|
4653
|
+
(isPlaceholder && target.closest('.canvas-element') && !target.closest('.text-edit-drag-helper'))
|
|
4654
|
+
)
|
|
4540
4655
|
)
|
|
4541
4656
|
|
|
4542
4657
|
if (isClickingTextContent && !e.ctrlKey && !e.shiftKey) {
|
|
@@ -4562,7 +4677,7 @@ function startDrag(e: MouseEvent, el: any) {
|
|
|
4562
4677
|
}
|
|
4563
4678
|
|
|
4564
4679
|
e.preventDefault()
|
|
4565
|
-
checkAndExitEditText(
|
|
4680
|
+
checkAndExitEditText(el, true)
|
|
4566
4681
|
|
|
4567
4682
|
dragOccurred = false
|
|
4568
4683
|
hasClonedForCtrlDrag = false
|
|
@@ -4589,11 +4704,13 @@ function startDrag(e: MouseEvent, el: any) {
|
|
|
4589
4704
|
selectedElementIds.value = [...selectedElementIds.value, ...targetIds.filter(x => !selectedElementIds.value.includes(x))]
|
|
4590
4705
|
selectedElementId.value = el.id
|
|
4591
4706
|
}
|
|
4707
|
+
syncSelectedElementDimensionsFromDom(selectedElementId.value)
|
|
4592
4708
|
} else {
|
|
4593
4709
|
if (!targetIds.every(tid => selectedElementIds.value.includes(tid))) {
|
|
4594
4710
|
selectedElementIds.value = targetIds
|
|
4595
4711
|
selectedElementId.value = el.id
|
|
4596
4712
|
}
|
|
4713
|
+
syncSelectedElementDimensionsFromDom(selectedElementId.value)
|
|
4597
4714
|
}
|
|
4598
4715
|
|
|
4599
4716
|
// Abort dragging if any of the selected elements is locked
|
|
@@ -4602,11 +4719,7 @@ function startDrag(e: MouseEvent, el: any) {
|
|
|
4602
4719
|
return
|
|
4603
4720
|
}
|
|
4604
4721
|
|
|
4605
|
-
|
|
4606
|
-
isCanvasDragging.value = true
|
|
4607
|
-
isDragging.value = true
|
|
4608
|
-
|
|
4609
|
-
// 录入活跃拖拽尺寸缓存,拖拽全程绝不二次读 DOM
|
|
4722
|
+
// 在开启 isDragging 锁闭 DOM 读取之前,先同步完成活跃拖拽尺寸缓存采集,确保初次按下拖拽时获取到真实 DOM 高度,拖拽全程绝不二次读 DOM
|
|
4610
4723
|
activeDragDimensions.clear()
|
|
4611
4724
|
|
|
4612
4725
|
// Get initial client coordinates
|
|
@@ -4699,6 +4812,10 @@ function startDrag(e: MouseEvent, el: any) {
|
|
|
4699
4812
|
}
|
|
4700
4813
|
})
|
|
4701
4814
|
|
|
4815
|
+
pauseHistory.value = true
|
|
4816
|
+
isCanvasDragging.value = true
|
|
4817
|
+
isDragging.value = true
|
|
4818
|
+
|
|
4702
4819
|
window.addEventListener('mousemove', handleDrag, { capture: true, passive: false } as any)
|
|
4703
4820
|
window.addEventListener('mouseup', stopDrag, { capture: true } as any)
|
|
4704
4821
|
window.addEventListener('pointerup', stopDrag, { capture: true } as any)
|
|
@@ -5080,8 +5197,8 @@ const selectedElementKeypoints = computed(() => {
|
|
|
5080
5197
|
const actualH = geom.height || 200
|
|
5081
5198
|
const viewBoxW = el.viewBox?.[0] || 200
|
|
5082
5199
|
const viewBoxH = el.viewBox?.[1] || 200
|
|
5083
|
-
const w = viewBoxW
|
|
5084
|
-
const h = viewBoxH
|
|
5200
|
+
const w = el.pathFormula === 'roundRect' ? actualW : viewBoxW
|
|
5201
|
+
const h = el.pathFormula === 'roundRect' ? actualH : viewBoxH
|
|
5085
5202
|
|
|
5086
5203
|
return el.keypoints.map((keypoint: any, index: number) => {
|
|
5087
5204
|
const getBaseSize = formulaObj.getBaseSize?.[index]
|
|
@@ -7646,11 +7763,13 @@ async function handleGlobalPaste(e: ClipboardEvent) {
|
|
|
7646
7763
|
} else if (block.type === 'text') {
|
|
7647
7764
|
const textHeightPercent = 8
|
|
7648
7765
|
const topPos = currentTopPercent
|
|
7766
|
+
const pasteColor = globalFontColor.value || '#000000'
|
|
7767
|
+
const pasteFont = (globalFontFamily.value && globalFontFamily.value !== '默认字体') ? globalFontFamily.value : 'SourceHanSansCN'
|
|
7649
7768
|
|
|
7650
7769
|
const newTextEl = {
|
|
7651
7770
|
id: 'text-' + Date.now().toString() + Math.random().toString(36).substring(2, 7),
|
|
7652
7771
|
type: 'text' as const,
|
|
7653
|
-
content: `<div>${block.content.replace(/\r\n/g, '<br>').replace(/\n/g, '<br>')}</div>`,
|
|
7772
|
+
content: `<div style="color:${pasteColor}; font-family:${pasteFont};">${block.content.replace(/\r\n/g, '<br>').replace(/\n/g, '<br>')}</div>`,
|
|
7654
7773
|
style: {
|
|
7655
7774
|
top: `${topPos.toFixed(2)}%`,
|
|
7656
7775
|
left: `${leftPercent}%`,
|
|
@@ -7658,8 +7777,13 @@ async function handleGlobalPaste(e: ClipboardEvent) {
|
|
|
7658
7777
|
height: 'auto',
|
|
7659
7778
|
rotate: 0,
|
|
7660
7779
|
fontSize: '18px',
|
|
7661
|
-
color:
|
|
7662
|
-
|
|
7780
|
+
color: pasteColor,
|
|
7781
|
+
textColor: pasteColor,
|
|
7782
|
+
fontFamily: pasteFont
|
|
7783
|
+
},
|
|
7784
|
+
color: pasteColor,
|
|
7785
|
+
textColor: pasteColor,
|
|
7786
|
+
fontFamily: pasteFont
|
|
7663
7787
|
}
|
|
7664
7788
|
|
|
7665
7789
|
currentTopPercent += textHeightPercent + gapPercent
|
|
@@ -8030,7 +8154,7 @@ async function handleGlobalPaste(e: ClipboardEvent) {
|
|
|
8030
8154
|
: (el.type === 'line'
|
|
8031
8155
|
? `${el.style?.left}_${el.style?.top}_${el.style?.width}_${el.style?.height}_${el.start?.join(',')}_${el.end?.join(',')}_${el.broken?.join(',')}_${el.broken2?.join(',')}_${el.curve?.join(',')}`
|
|
8032
8156
|
: 'frozen'))
|
|
8033
|
-
: `${el.id}_${el.style?.left}_${el.style?.top}_${el.style?.width}_${el.style?.height}_${el.style?.rotate}_${el.type === 'line' ? `${el.start?.join(',')}_${el.end?.join(',')}_${el.broken?.join(',')}_${el.broken2?.join(',')}_${el.curve?.join(',')}_` : ''}${selectedElementIds.includes(el.id)}_${selectedElementId === el.id}_${isEditingText}_${activeTab}_${activeSlideVersion}`
|
|
8157
|
+
: `${el.id}_${el.style?.left}_${el.style?.top}_${el.style?.width}_${el.style?.height}_${el.style?.rotate}_${el.type === 'line' ? `${el.start?.join(',')}_${el.end?.join(',')}_${el.broken?.join(',')}_${el.broken2?.join(',')}_${el.curve?.join(',')}_` : ''}${selectedElementIds.includes(el.id)}_${selectedElementId === el.id}_${isEditingText}_${activeTab}_${activeSlideVersion}_${(el.style as any)?.reflection?.enabled}_${(el.style as any)?.reflection?.distance}_${(el.style as any)?.reflection?.size}_${(el.style as any)?.reflection?.blur}_${(el.style as any)?.reflection?.opacity}`
|
|
8034
8158
|
]"
|
|
8035
8159
|
:class="{
|
|
8036
8160
|
selected: selectedElementIds.includes(el.id),
|
|
@@ -8047,7 +8171,7 @@ async function handleGlobalPaste(e: ClipboardEvent) {
|
|
|
8047
8171
|
width: (el.type === 'text' && !isMasterOrPlaceholder(el) && (el.autoFit?.type === 'shape' || el.style?.width === 'auto') && !el.content?.includes('<table') && !el.latex && (el.style?.writingMode === 'vertical-rl' || el.style?.writingMode === 'vertical-lr')) ? 'auto' : (el.style?.width || 'auto'),
|
|
8048
8172
|
height: (el.type === 'text' && !isMasterOrPlaceholder(el) && (el.autoFit?.type === 'shape' || el.style?.height === 'auto') && !el.content?.includes('<table') && !el.latex && el.style?.writingMode !== 'vertical-rl' && el.style?.writingMode !== 'vertical-lr') ? 'auto' : (el.style?.height || (el.height ? `${el.height}px` : 'auto')),
|
|
8049
8173
|
zIndex: 3,
|
|
8050
|
-
cursor: isReadonly ? 'default' : ((isEditingText && (selectedElementId === el.id || editingElementId === el.id) &&
|
|
8174
|
+
cursor: isReadonly ? 'default' : ((isEditingText && (selectedElementId === el.id || editingElementId === el.id) && el.type === 'shape' && !el.latex && !el.content?.includes('<table')) ? 'text' : undefined),
|
|
8051
8175
|
transform: el.type === 'line' ? 'none' : `rotate(${el.style?.rotate || 0}deg) scale(${!isTextContainingElement(el) && ((el.style as any)?.flipH || el.flipH || el.isFlipH) ? -1 : 1}, ${!isTextContainingElement(el) && ((el.style as any)?.flipV || el.flipV || el.isFlipV) ? -1 : 1})`,
|
|
8052
8176
|
opacity: (el.style as any)?.opacity !== undefined ? (el.style as any)?.opacity : 1,
|
|
8053
8177
|
filter: getElementDropShadowFilter(el),
|
|
@@ -8236,6 +8360,8 @@ async function handleGlobalPaste(e: ClipboardEvent) {
|
|
|
8236
8360
|
@text-blur="(ev, child) => handleTextBlur(ev, child)"
|
|
8237
8361
|
@text-input="(ev, child) => handleInput(ev, child)"
|
|
8238
8362
|
@text-key-down="(ev, child) => handleTextKeyDown(ev, child)"
|
|
8363
|
+
@text-mouse-move="(ev, child) => handleTextMouseMove(ev, child)"
|
|
8364
|
+
@text-mouse-leave="(ev, child) => handleTextMouseLeave(ev, child)"
|
|
8239
8365
|
@start-editing="(id, ev) => { const target = findElementInSlide(id); if (target && target.type === 'shape') startEditingShapeText(target, ev); else startEditingTextElement(id, ev); }"
|
|
8240
8366
|
@formula-dbl-click="(child) => handleFormulaDblClick(child)"
|
|
8241
8367
|
@table-dbl-click="(ev, child) => handleTableDblClick(ev, child)"
|
|
@@ -8302,118 +8428,17 @@ async function handleGlobalPaste(e: ClipboardEvent) {
|
|
|
8302
8428
|
|
|
8303
8429
|
<!-- Shape element -->
|
|
8304
8430
|
<template v-else-if="el.type === 'shape'">
|
|
8305
|
-
<
|
|
8306
|
-
|
|
8307
|
-
|
|
8308
|
-
|
|
8309
|
-
|
|
8310
|
-
|
|
8311
|
-
|
|
8312
|
-
|
|
8313
|
-
|
|
8314
|
-
|
|
8315
|
-
|
|
8316
|
-
<svg viewBox="0 0 100 100" preserveAspectRatio="none"
|
|
8317
|
-
style="width: 100%; height: 100%; display: block; overflow: visible;"
|
|
8318
|
-
:style="{ filter: (el.shadow && el.shadow.type === 'inner') ? `url(#shape-inner-shadow-${el.id})` : '' }">
|
|
8319
|
-
<polygon points="50,0 0,100 100,100"
|
|
8320
|
-
:fill="el.style.fill !== undefined ? el.style.fill : '#f59e0b'"
|
|
8321
|
-
:stroke="el.style.borderColor || '#d97706'"
|
|
8322
|
-
:stroke-width="el.style.borderWidth ? parseInt(el.style.borderWidth) * 1.5 : 3"
|
|
8323
|
-
:stroke-dasharray="el.style.borderStyle === 'dashed' ? '5 5' : ''" />
|
|
8324
|
-
</svg>
|
|
8325
|
-
</div>
|
|
8326
|
-
<div v-else-if="el.content && (el.content.trim().startsWith('M') || el.content.trim().startsWith('m'))"
|
|
8327
|
-
style="width: 100%; height: 100%; overflow: visible;">
|
|
8328
|
-
<svg overflow="visible" style="width: 100%; height: 100%; display: block; overflow: visible;"
|
|
8329
|
-
:style="{ filter: (el.shadow && el.shadow.type === 'inner') ? `url(#shape-inner-shadow-${el.id})` : '' }">
|
|
8330
|
-
<g
|
|
8331
|
-
:transform="el.shapType === 'arc' ? `scale(${getElementWidthHeight(el).width / (el.viewBox ? el.viewBox[0] : 200)}, ${getElementWidthHeight(el).height / (el.viewBox ? el.viewBox[1] : 200)})` : `translate(${(el.style.borderWidth ? parseFloat(el.style.borderWidth) : 2) / 2}, ${(el.style.borderWidth ? parseFloat(el.style.borderWidth) : 2) / 2}) scale(${Math.max(0, getElementWidthHeight(el).width - (el.style.borderWidth ? parseFloat(el.style.borderWidth) : 2)) / (el.viewBox ? el.viewBox[0] : 200)}, ${Math.max(0, getElementWidthHeight(el).height - (el.style.borderWidth ? parseFloat(el.style.borderWidth) : 2)) / (el.viewBox ? el.viewBox[1] : 200)})`">
|
|
8332
|
-
<path vector-effect="non-scaling-stroke" :d="el.content"
|
|
8333
|
-
:fill="getElementFill(el) !== undefined ? getElementFill(el) : '#3b82f6'"
|
|
8334
|
-
:stroke="getElementBorderColor(el) || 'none'" :stroke-width="getElementBorderWidth(el)"
|
|
8335
|
-
:stroke-linecap="(el.style?.strokeLinecap || el.borderLineCap || el.lineCap || (el.shapType === 'arc' ? 'round' : undefined)) as any"
|
|
8336
|
-
:stroke-dasharray="el.style?.borderStyle === 'dashed' || (el as any).borderType === 'dashed' ? '5 5' : ''" />
|
|
8337
|
-
</g>
|
|
8338
|
-
</svg>
|
|
8339
|
-
</div>
|
|
8340
|
-
<div v-else :style="{
|
|
8341
|
-
width: '100%',
|
|
8342
|
-
height: '100%',
|
|
8343
|
-
backgroundColor: (getElementFill(el) !== undefined && getElementFill(el) !== 'none') ? getElementFill(el) : (getElementFill(el) === 'none' ? 'transparent' : '#10b981'),
|
|
8344
|
-
borderRadius: '4px',
|
|
8345
|
-
borderWidth: `${getElementBorderWidth(el)}px`,
|
|
8346
|
-
borderStyle: el.style?.borderStyle || (el as any).borderType || 'solid',
|
|
8347
|
-
borderColor: getElementBorderColor(el) || 'transparent',
|
|
8348
|
-
filter: (el.shadow && el.shadow.type === 'inner') ? `url(#shape-inner-shadow-${el.id})` : ''
|
|
8349
|
-
}"></div>
|
|
8350
|
-
|
|
8351
|
-
<div class="shape-text-overlay-wrapper"
|
|
8352
|
-
style="position: absolute; display: flex; flex-direction: column; pointer-events: none; box-sizing: border-box;"
|
|
8353
|
-
:style="{
|
|
8354
|
-
left: isEllipseShape(el) ? '14.6%' : '0px',
|
|
8355
|
-
top: isEllipseShape(el) ? '14.6%' : '0px',
|
|
8356
|
-
width: isEllipseShape(el) ? '70.8%' : '100%',
|
|
8357
|
-
height: isEllipseShape(el) ? '70.8%' : '100%',
|
|
8358
|
-
justifyContent: (el.style.verticalAlign === 'top' || el.style.verticalAlign === 'up') ? 'flex-start' : ((el.style.verticalAlign === 'bottom' || el.style.verticalAlign === 'down') ? 'flex-end' : 'center'),
|
|
8359
|
-
padding: isEllipseShape(el) ? '0px' : (el.style.padding || '4.8px 9.6px 4.8px 9.6px')
|
|
8360
|
-
}">
|
|
8361
|
-
<div class="text-reflection-wrapper" style="position: relative; width: 100%; height: auto;">
|
|
8362
|
-
<div class="shape-text-overlay" :style="{
|
|
8363
|
-
display: 'block',
|
|
8364
|
-
width: '100%',
|
|
8365
|
-
maxWidth: '100%',
|
|
8366
|
-
outline: 'none',
|
|
8367
|
-
padding: '0px',
|
|
8368
|
-
boxSizing: 'content-box',
|
|
8369
|
-
overflow: 'wrap',
|
|
8370
|
-
wordBreak: 'break-word',
|
|
8371
|
-
pointerEvents: 'none',
|
|
8372
|
-
userSelect: 'none',
|
|
8373
|
-
color: el.style.textColor || el.style.color || (el.style.fill === '#ffffff' || el.style.fill === '#FFFFFF' ? '#475569' : '#ffffff'),
|
|
8374
|
-
fontFamily: el.style.fontFamily || 'inherit',
|
|
8375
|
-
fontSize: el.style.fontSize || '16px',
|
|
8376
|
-
fontWeight: el.style.fontWeight || ((getSafeShapeText(el).includes('<')) ? 'normal' : 'normal'),
|
|
8377
|
-
fontStyle: (el.style as any).fontStyle || 'normal',
|
|
8378
|
-
textDecoration: (el.style.textDecoration as any) || 'none',
|
|
8379
|
-
lineHeight: el.style.lineHeight || 1.35,
|
|
8380
|
-
textAlign: (el.style.textAlign as any) || 'center',
|
|
8381
|
-
whiteSpace: (el.style as any).whiteSpace || 'normal',
|
|
8382
|
-
'--paragraphSpace': `${(el.style as any).paragraphSpace === undefined ? 3 : (el.style as any).paragraphSpace}px`
|
|
8383
|
-
}" v-html="normalizeHtmlFontFamily(getSafeShapeText(el))">
|
|
8384
|
-
</div>
|
|
8385
|
-
|
|
8386
|
-
<!-- Shape Text Reflection Clone -->
|
|
8387
|
-
<div v-if="(el.style as any).textReflection && (el.style as any).textReflection.enabled"
|
|
8388
|
-
class="text-element-reflection"
|
|
8389
|
-
style="position: absolute; left: 0; width: 100%; pointer-events: none; z-index: 1;" :style="{
|
|
8390
|
-
top: `calc(100% + ${(el.style as any).textReflection.distance !== undefined ? (el.style as any).textReflection.distance : 20}px - ${getReflectionLeadingCompensation(el)}px)`,
|
|
8391
|
-
transform: 'translateY(100%) scaleY(-1)',
|
|
8392
|
-
opacity: (100 - ((el.style as any).textReflection.opacity !== undefined ? (el.style as any).textReflection.opacity : 10)) / 100,
|
|
8393
|
-
filter: (el.style as any).textReflection.blur ? `blur(${(((el.style as any).textReflection.blur !== undefined ? (el.style as any).textReflection.blur : 0) * 1.33).toFixed(1)}px)` : 'none',
|
|
8394
|
-
['-webkit-mask-image']: `linear-gradient(to bottom, rgba(0,0,0,1) 0%, rgba(0,0,0,0) ${((el.style as any).textReflection.size !== undefined ? (el.style as any).textReflection.size : 8)}%, rgba(0,0,0,0) 100%)`,
|
|
8395
|
-
['mask-image']: `linear-gradient(to bottom, rgba(0,0,0,1) 0%, rgba(0,0,0,0) ${((el.style as any).textReflection.size !== undefined ? (el.style as any).textReflection.size : 8)}%, rgba(0,0,0,0) 100%)`,
|
|
8396
|
-
color: el.style.textColor || el.style.color || (el.style.fill === '#ffffff' || el.style.fill === '#FFFFFF' ? '#475569' : '#ffffff'),
|
|
8397
|
-
fontFamily: el.style.fontFamily || 'inherit',
|
|
8398
|
-
fontSize: el.style.fontSize || '16px',
|
|
8399
|
-
fontWeight: el.style.fontWeight || 'normal',
|
|
8400
|
-
fontStyle: (el.style as any).fontStyle || 'normal',
|
|
8401
|
-
textDecoration: (el.style.textDecoration as any) || 'none',
|
|
8402
|
-
['-webkit-text-stroke']: getTextStrokeStyle(el),
|
|
8403
|
-
['paint-order']: (el.style as any).enableTextStroke ? 'stroke fill' : 'normal',
|
|
8404
|
-
['text-shadow']: (el.style as any).textShadow || 'none',
|
|
8405
|
-
lineHeight: el.style.lineHeight || 1.35,
|
|
8406
|
-
textAlign: (el.style.textAlign as any) || 'center',
|
|
8407
|
-
whiteSpace: (el.style as any).whiteSpace || 'normal',
|
|
8408
|
-
transformOrigin: 'top left',
|
|
8409
|
-
height: 'auto'
|
|
8410
|
-
}"
|
|
8411
|
-
v-html="el.style.textBackground && el.style.textBackground !== 'transparent'
|
|
8412
|
-
? `<span style='background-color: ${el.style.textBackground}; display: inline;'>${normalizeHtmlFontFamily(getSafeShapeText(el))}</span>`
|
|
8413
|
-
: normalizeHtmlFontFamily(getSafeShapeText(el))">
|
|
8414
|
-
</div>
|
|
8415
|
-
</div>
|
|
8416
|
-
</div>
|
|
8431
|
+
<CanvasShapeElement
|
|
8432
|
+
:element="el"
|
|
8433
|
+
:active-slide="activeSlide"
|
|
8434
|
+
:is-reflection="true"
|
|
8435
|
+
:theme-recipe="getActiveSlideThemeRecipe(activeSlide)"
|
|
8436
|
+
:normalize-html-font-family="normalizeHtmlFontFamily"
|
|
8437
|
+
:get-text-stroke-style="getTextStrokeStyle"
|
|
8438
|
+
:get-element-text-shadow="getElementTextShadow"
|
|
8439
|
+
:get-reflection-leading-compensation="getReflectionLeadingCompensation"
|
|
8440
|
+
:is-image-placeholder="isImagePlaceholder"
|
|
8441
|
+
/>
|
|
8417
8442
|
</template>
|
|
8418
8443
|
|
|
8419
8444
|
<!-- Image element -->
|