diff --git a/core/core-frontend/src/components/data-visualization/canvas/ComponentWrapper.vue b/core/core-frontend/src/components/data-visualization/canvas/ComponentWrapper.vue index 4631393280..7a1b32407f 100644 --- a/core/core-frontend/src/components/data-visualization/canvas/ComponentWrapper.vue +++ b/core/core-frontend/src/components/data-visualization/canvas/ComponentWrapper.vue @@ -13,6 +13,11 @@ import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain' import { activeWatermarkCheckUser, removeActiveWatermark } from '@/components/watermark/watermark' import { isMobile } from '@/utils/utils' import { isDashboard, isMainCanvas } from '@/utils/canvasUtils' +import { + isBlurBgEnabled, + getBlurBgStyle, + getComponentBackgroundStyle +} from '@/utils/backgroundStyleUtils' import { XpackComponent } from '@/components/plugin' import { useAppStoreWithOut } from '@/store/modules/app' import DePreviewPopDialog from '@/components/visualization/DePreviewPopDialog.vue' @@ -222,43 +227,20 @@ const onMouseEnter = () => { eventBus.emit('v-hover', config.value.id) } +const blurBgEnable = computed(() => { + return isBlurBgEnabled(config.value.commonBackground) +}) + +const blurBgStyle = computed(() => { + return getBlurBgStyle(config.value.commonBackground, deepScale.value) +}) + const componentBackgroundStyle = computed(() => { if (config.value.commonBackground) { - const { - backdropFilterEnable, - backdropFilter, - backgroundColorSelect, - backgroundColor, - backgroundImageEnable, - backgroundType, - outerImage, - innerPadding, - borderRadius - } = config.value.commonBackground - let style = { - padding: innerPadding * deepScale.value + 'px', - borderRadius: borderRadius + 'px' - } - let colorRGBA = '' - if (backgroundColorSelect && backgroundColor) { - colorRGBA = backgroundColor - } - if (backgroundImageEnable) { - if (backgroundType === 'outerImage' && typeof outerImage === 'string') { - style['background'] = `url(${imgUrlTrans(outerImage)}) no-repeat ${colorRGBA}` - } else { - style['background-color'] = colorRGBA - } - } else { - style['background-color'] = colorRGBA - } - if (config.value.component !== 'UserView') { - style['overflow'] = 'hidden' - } - if (backdropFilterEnable) { - style['backdrop-filter'] = 'blur(' + backdropFilter + 'px)' - } - return style + return getComponentBackgroundStyle(config.value.commonBackground, { + scale: deepScale.value, + isUserView: config.value.component === 'UserView' + }) } return {} }) @@ -470,6 +452,7 @@ const updateFromMobile = (e, type) => { :id="viewDemoInnerId" :style="componentBackgroundStyle" > +
{ } } +.blur-bg { + width: 100%; + height: 100%; + background-size: 100% 100% !important; +} + .wrapper-edit-bar-active { display: inherit !important; } diff --git a/core/core-frontend/src/components/data-visualization/canvas/Shape.vue b/core/core-frontend/src/components/data-visualization/canvas/Shape.vue index a1ece60a22..6a63db146c 100644 --- a/core/core-frontend/src/components/data-visualization/canvas/Shape.vue +++ b/core/core-frontend/src/components/data-visualization/canvas/Shape.vue @@ -73,6 +73,8 @@ @click="selectCurComponent" @mousedown="handleInnerMouseDownOnShape" > + +
@@ -159,9 +161,10 @@ import Board from '@/components/de-board/Board.vue' import { activeWatermarkCheckUser, removeActiveWatermark } from '@/components/watermark/watermark' import { useI18n } from '@/hooks/web/useI18n' import { - CommonBackground, - ShorthandMode -} from '@/components/visualization/component-background/Types' + isBlurBgEnabled, + getBlurBgStyle, + getComponentBackgroundStyle +} from '@/utils/backgroundStyleUtils' const { t } = useI18n() const dvMainStore = dvMainStoreWithOut() @@ -982,68 +985,23 @@ const padding3D = computed(() => { } }) +// 是否启用背景模糊,有背景图且开启了模糊 +const blurBgEnable = computed(() => { + return isBlurBgEnabled(element.value.commonBackground) +}) + +// 背景模糊层样式 +const blurBgStyle = computed(() => { + return getBlurBgStyle(element.value.commonBackground, scale.value) +}) + const componentBackgroundStyle = computed(() => { if (element.value.commonBackground && element.value.component !== 'GroupArea') { - const { - backdropFilterEnable, - backdropFilter, - backgroundColorSelect, - backgroundColor, - backgroundImageEnable, - backgroundType, - outerImage, - innerPadding, - borderRadius - } = element.value.commonBackground - const commonBackground = element.value.commonBackground as CommonBackground - const innerPaddingTarget = ['Group'].includes(element.value.component) ? 0 : innerPadding - let innerPaddingStyle = innerPaddingTarget * scale.value + 'px' - const paddingMode = commonBackground.innerPadding?.mode - if (paddingMode === ShorthandMode.Uniform) { - innerPaddingStyle = `${commonBackground.innerPadding?.top * scale.value}px` - } else if (paddingMode === ShorthandMode.PerEdge) { - innerPaddingStyle = `${commonBackground.innerPadding?.top * scale.value}px ${ - commonBackground.innerPadding?.right * scale.value - }px ${commonBackground.innerPadding?.bottom * scale.value}px ${ - commonBackground.innerPadding?.left * scale.value - }px` - } - - let borderRadiusStyle = borderRadius + 'px' - const borderRadiusMode = commonBackground.borderRadius?.mode - if (borderRadiusMode === ShorthandMode.Uniform) { - borderRadiusStyle = `${commonBackground.borderRadius?.topLeft * scale.value}px` - } else if (borderRadiusMode === ShorthandMode.PerEdge) { - borderRadiusStyle = `${commonBackground.borderRadius?.topLeft * scale.value}px ${ - commonBackground.borderRadius?.topRight * scale.value - }px ${commonBackground.borderRadius?.bottomRight * scale.value}px ${ - commonBackground.borderRadius?.bottomLeft * scale.value - }px` - } - let style = { - padding: innerPaddingStyle, - borderRadius: borderRadiusStyle - } - let colorRGBA = '' - if (backgroundColorSelect && backgroundColor) { - colorRGBA = backgroundColor - } - if (backgroundImageEnable) { - if (backgroundType === 'outerImage' && typeof outerImage === 'string') { - style['background'] = `url(${imgUrlTrans(outerImage)}) no-repeat ${colorRGBA}` - } else { - style['background-color'] = colorRGBA - } - } else { - style['background-color'] = colorRGBA - } - if (element.value.component !== 'UserView') { - style['overflow'] = 'hidden' - } - if (backdropFilterEnable) { - style['backdrop-filter'] = 'blur(' + backdropFilter + 'px)' - } - return style + return getComponentBackgroundStyle(element.value.commonBackground, { + scale: scale.value, + isUserView: element.value.component === 'UserView', + forceNoPadding: ['Group'].includes(element.value.component) + }) } return {} }) @@ -1277,6 +1235,12 @@ onMounted(() => { background-size: 100% 100% !important; } +.blur-bg { + width: 100%; + height: 100%; + background-size: 100% 100% !important; +} + .shape-selected { outline: 1px solid var(--ed-color-primary, #3370ff); } diff --git a/core/core-frontend/src/utils/backgroundStyleUtils.ts b/core/core-frontend/src/utils/backgroundStyleUtils.ts new file mode 100644 index 0000000000..e54e84e886 --- /dev/null +++ b/core/core-frontend/src/utils/backgroundStyleUtils.ts @@ -0,0 +1,165 @@ +import { imgUrlTrans } from '@/utils/imgUtils' +import type { + CommonBackground, + CornerValues, + EdgeValues +} from '@/components/visualization/component-background/Types' + +/** + * 判断是否启用背景图模糊 + * @param commonBackground 组件背景配置 + * @returns 是否启用背景图模糊 + */ +export function isBlurBgEnabled(commonBackground: CommonBackground | undefined): boolean { + if (!commonBackground) { + return false + } + const { backdropFilterEnable, backgroundImageEnable, backgroundType, outerImage } = + commonBackground + return ( + backdropFilterEnable === true && + backgroundImageEnable === true && + backgroundType === 'outerImage' && + typeof outerImage === 'string' + ) +} + +/** + * 获取边距样式值 + * @param edgeValues 边距配置 + * @param scale 缩放比例 + * @returns CSS 边距样式值 + */ +export function getEdgeValuesStyle(edgeValues: EdgeValues | number | undefined, scale = 1): string { + if (edgeValues === undefined) { + return '0px' + } + if (typeof edgeValues === 'number') { + return `${edgeValues * scale}px` + } + const mode = edgeValues.mode + const top = (edgeValues.top ?? 0) * scale + const right = (edgeValues.right ?? 0) * scale + const bottom = (edgeValues.bottom ?? 0) * scale + const left = (edgeValues.left ?? 0) * scale + if (mode === 'uniform') { + return `${top}px` + } else if (mode === 'per_edge') { + return `${top}px ${right}px ${bottom}px ${left}px` + } + return `${top}px` +} + +/** + * 获取圆角样式值 + * @param cornerValues 圆角配置 + * @param scale 缩放比例 + * @returns CSS 圆角样式值 + */ +export function getCornerValuesStyle( + cornerValues: CornerValues | number | undefined, + scale = 1 +): string { + if (cornerValues === undefined) { + return '0px' + } + if (typeof cornerValues === 'number') { + return `${cornerValues * scale}px` + } + const mode = cornerValues.mode + const topLeft = (cornerValues.topLeft ?? 0) * scale + const topRight = (cornerValues.topRight ?? 0) * scale + const bottomLeft = (cornerValues.bottomLeft ?? 0) * scale + const bottomRight = (cornerValues.bottomRight ?? 0) * scale + if (mode === 'uniform') { + return `${topLeft}px` + } else if (mode === 'per_edge') { + return `${topLeft}px ${topRight}px ${bottomRight}px ${bottomLeft}px` + } + return `${topLeft}px` +} + +/** + * 生成背景模糊层样式 + * @param commonBackground 组件背景配置 + * @param scale 缩放比例 + * @returns CSS 样式对象 + */ +export function getBlurBgStyle( + commonBackground: CommonBackground | undefined, + scale = 1 +): Record { + if (!isBlurBgEnabled(commonBackground)) { + return {} + } + const { outerImage, backdropFilter, borderRadius } = commonBackground + return { + position: 'absolute', + inset: '0', + background: `url(${imgUrlTrans(outerImage!)}) no-repeat center/cover`, + filter: `blur(${backdropFilter ?? 0}px)`, + borderRadius: getCornerValuesStyle(borderRadius, scale), + pointerEvents: 'none' + } +} + +/** + * 生成组件背景样式 + * @param commonBackground 组件背景配置 + * @param options 配置选项 + * @returns CSS 样式对象 + */ +export function getComponentBackgroundStyle( + commonBackground: CommonBackground | undefined, + options: { + scale?: number + isUserView?: boolean + forceNoPadding?: boolean + } = {} +): Record { + if (!commonBackground) { + return {} + } + const { + backdropFilterEnable, + backdropFilter, + backgroundColorSelect, + backgroundColor, + backgroundImageEnable, + backgroundType, + outerImage, + innerPadding, + borderRadius + } = commonBackground + const { scale = 1, isUserView = false, forceNoPadding = false } = options + const style: Record = { + padding: forceNoPadding ? '0px' : getEdgeValuesStyle(innerPadding, scale), + borderRadius: getCornerValuesStyle(borderRadius, scale) + } + // 背景色 + let colorRGBA = '' + if (backgroundColorSelect && backgroundColor) { + colorRGBA = backgroundColor + } + // 背景图 + const blurEnabled = isBlurBgEnabled(commonBackground) + if (backgroundImageEnable) { + if (blurEnabled) { + style['background-color'] = colorRGBA + } else if (backgroundType === 'outerImage' && typeof outerImage === 'string') { + style['background'] = `url(${imgUrlTrans(outerImage)}) no-repeat ${colorRGBA}` + } else { + style['background-color'] = colorRGBA + } + } else { + style['background-color'] = colorRGBA + } + // 溢出处理 + if (!isUserView) { + style['overflow'] = 'hidden' + } + if (backdropFilterEnable && !blurEnabled) { + style['backdrop-filter'] = `blur(${backdropFilter ?? 0}px)` + } + return style +}